summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/android/extract.h117
-rw-r--r--src/3rdparty/angle/src/common/angleutils.h2
-rw-r--r--src/3rdparty/harfbuzz-ng/AUTHORS1
-rw-r--r--src/3rdparty/harfbuzz-ng/NEWS119
-rw-r--r--src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro7
-rw-r--r--src/3rdparty/harfbuzz-ng/include/harfbuzz/hb-ot-font.h1
-rw-r--r--src/3rdparty/harfbuzz-ng/src/config.h14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-atomic-private.hh14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-blob.cc2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-blob.h7
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer-private.hh1
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer.cc87
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer.h23
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-common.cc28
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-common.h27
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-coretext.cc200
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-coretext.h6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-open-file-private.hh12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh125
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh517
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc289
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-font.h41
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh37
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh10
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh28
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh58
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh57
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-private.hh64
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc34
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-map-private.hh18
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc54
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh1239
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc150
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc36
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc136
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh1920
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh111
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc721
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc334
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc73
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-private.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-sea.cc15
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc89
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-fallback.cc70
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-private.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc98
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape.h21
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc62
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot.h1
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-private.hh186
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-shaper-list.hh12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-unicode-private.hh111
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-unicode.cc11
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-utf-private.hh319
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-version.h14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-warning.cc11
-rw-r--r--src/3rdparty/pcre/AUTHORS6
-rw-r--r--src/3rdparty/pcre/LICENCE6
-rw-r--r--src/3rdparty/pcre/config.h10
-rwxr-xr-xsrc/3rdparty/pcre/import_from_pcre_tarball.sh8
-rw-r--r--src/3rdparty/pcre/patches/bug_1423_jit_condition_misoptimization_fix.diff15
-rw-r--r--src/3rdparty/pcre/pcre.h12
-rw-r--r--src/3rdparty/pcre/pcre_byte_order.c6
-rw-r--r--src/3rdparty/pcre/pcre_compile.c141
-rw-r--r--src/3rdparty/pcre/pcre_dfa_exec.c69
-rw-r--r--src/3rdparty/pcre/pcre_exec.c102
-rw-r--r--src/3rdparty/pcre/pcre_globals.c4
-rw-r--r--src/3rdparty/pcre/pcre_internal.h118
-rw-r--r--src/3rdparty/pcre/pcre_jit_compile.c1923
-rw-r--r--src/3rdparty/pcre/pcre_string_utils.c8
-rw-r--r--src/3rdparty/pcre/pcre_study.c62
-rw-r--r--src/3rdparty/pcre/pcre_xclass.c5
-rw-r--r--src/3rdparty/pcre/sljit/sljitConfig.h11
-rw-r--r--src/3rdparty/pcre/sljit/sljitConfigInternal.h31
-rw-r--r--src/3rdparty/pcre/sljit/sljitLir.c214
-rw-r--r--src/3rdparty/pcre/sljit/sljitLir.h43
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeARM_32.c (renamed from src/3rdparty/pcre/sljit/sljitNativeARM_v5.c)201
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeARM_64.c1902
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c (renamed from src/3rdparty/pcre/sljit/sljitNativeARM_Thumb2.c)479
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c122
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeMIPS_64.c469
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c323
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativePPC_32.c2
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativePPC_64.c4
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativePPC_common.c598
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c86
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeTILEGX-encoder.c10159
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c2580
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeX86_32.c40
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeX86_64.c50
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeX86_common.c386
-rw-r--r--src/android/accessibility/jar/src/org/qtproject/qt5/android/accessibility/QtAccessibilityDelegate.java17
-rw-r--r--src/android/accessibility/jar/src/org/qtproject/qt5/android/accessibility/QtNativeAccessibility.java2
-rw-r--r--src/android/jar/jar.pri3
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java1686
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java14
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java17
-rw-r--r--src/angle/patches/0019-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch28
-rw-r--r--src/concurrent/doc/qtconcurrent.qdocconf1
-rw-r--r--src/corelib/animation/qvariantanimation.cpp6
-rw-r--r--src/corelib/codecs/qutfcodec.cpp47
-rw-r--r--src/corelib/corelib.pro16
-rw-r--r--src/corelib/doc/qtcore.qdocconf1
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp8
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp10
-rw-r--r--src/corelib/doc/snippets/qloggingcategory/main.cpp31
-rw-r--r--src/corelib/global/archdetect.cpp131
-rw-r--r--src/corelib/global/global.pri7
-rw-r--r--src/corelib/global/qcompilerdetection.h106
-rw-r--r--src/corelib/global/qflags.h17
-rw-r--r--src/corelib/global/qglobal.cpp585
-rw-r--r--src/corelib/global/qglobal.h41
-rw-r--r--src/corelib/global/qglobalstatic.h2
-rw-r--r--src/corelib/global/qhooks.cpp69
-rw-r--r--src/corelib/global/qhooks_p.h (renamed from src/gui/kernel/qkeymapper_qpa.cpp)56
-rw-r--r--src/corelib/global/qlibraryinfo.cpp65
-rw-r--r--src/corelib/global/qlogging.cpp216
-rw-r--r--src/corelib/global/qlogging.h4
-rw-r--r--src/corelib/global/qnamespace.h1
-rw-r--r--src/corelib/global/qnamespace.qdoc20
-rw-r--r--src/corelib/global/qnumeric.cpp2
-rw-r--r--src/corelib/global/qsysinfo.h12
-rw-r--r--src/corelib/global/qsystemdetection.h12
-rw-r--r--src/corelib/global/qtypeinfo.h2
-rw-r--r--src/corelib/io/qdatastream.cpp36
-rw-r--r--src/corelib/io/qdatastream.h8
-rw-r--r--src/corelib/io/qdebug.cpp96
-rw-r--r--src/corelib/io/qdebug.h87
-rw-r--r--src/corelib/io/qfiledevice.cpp11
-rw-r--r--src/corelib/io/qfiledevice.h4
-rw-r--r--src/corelib/io/qfileselector.cpp9
-rw-r--r--src/corelib/io/qfsfileengine.cpp16
-rw-r--r--src/corelib/io/qfsfileengine_p.h1
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp8
-rw-r--r--src/corelib/io/qfsfileengine_win.cpp20
-rw-r--r--src/corelib/io/qlockfile_win.cpp25
-rw-r--r--src/corelib/io/qloggingcategory.cpp80
-rw-r--r--src/corelib/io/qloggingcategory.h32
-rw-r--r--src/corelib/io/qloggingregistry.cpp51
-rw-r--r--src/corelib/io/qloggingregistry_p.h6
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice.cpp39
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice_p.h6
-rw-r--r--src/corelib/io/qsavefile.cpp24
-rw-r--r--src/corelib/io/qsavefile_p.h1
-rw-r--r--src/corelib/io/qsettings.cpp297
-rw-r--r--src/corelib/io/qstandardpaths.cpp35
-rw-r--r--src/corelib/io/qstandardpaths.h4
-rw-r--r--src/corelib/io/qstandardpaths_android.cpp5
-rw-r--r--src/corelib/io/qstandardpaths_blackberry.cpp5
-rw-r--r--src/corelib/io/qstandardpaths_ios.mm3
-rw-r--r--src/corelib/io/qstandardpaths_mac.cpp16
-rw-r--r--src/corelib/io/qstandardpaths_unix.cpp8
-rw-r--r--src/corelib/io/qstandardpaths_win.cpp34
-rw-r--r--src/corelib/io/qstandardpaths_winrt.cpp7
-rw-r--r--src/corelib/io/qtemporaryfile.cpp3
-rw-r--r--src/corelib/io/qtextstream.cpp4
-rw-r--r--src/corelib/io/qurl.cpp64
-rw-r--r--src/corelib/io/qurl.h9
-rw-r--r--src/corelib/io/qwinoverlappedionotifier.cpp60
-rw-r--r--src/corelib/io/qwinoverlappedionotifier_p.h1
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.cpp4
-rw-r--r--src/corelib/itemmodels/qabstractproxymodel.cpp24
-rw-r--r--src/corelib/itemmodels/qabstractproxymodel.h4
-rw-r--r--src/corelib/itemmodels/qitemselectionmodel.cpp24
-rw-r--r--src/corelib/json/qjson_p.h71
-rw-r--r--src/corelib/json/qjsonarray.cpp25
-rw-r--r--src/corelib/json/qjsonarray.h14
-rw-r--r--src/corelib/json/qjsondocument.cpp2
-rw-r--r--src/corelib/json/qjsonobject.cpp16
-rw-r--r--src/corelib/json/qjsonvalue.cpp19
-rw-r--r--src/corelib/json/qjsonvalue.h8
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp9
-rw-r--r--src/corelib/kernel/qcoreapplication.h1
-rw-r--r--src/corelib/kernel/qcoreapplication_p.h1
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp30
-rw-r--r--src/corelib/kernel/qcorecmdlineargs_p.h38
-rw-r--r--src/corelib/kernel/qcoreevent.cpp102
-rw-r--r--src/corelib/kernel/qcoreevent.h11
-rw-r--r--src/corelib/kernel/qeventdispatcher_winrt.cpp250
-rw-r--r--src/corelib/kernel/qfunctions_winrt.h95
-rw-r--r--src/corelib/kernel/qmath.h52
-rw-r--r--src/corelib/kernel/qmath.qdoc33
-rw-r--r--src/corelib/kernel/qmetaobject.cpp57
-rw-r--r--src/corelib/kernel/qmetatype.cpp5
-rw-r--r--src/corelib/kernel/qmetatype.h53
-rw-r--r--src/corelib/kernel/qmimedata.cpp2
-rw-r--r--src/corelib/kernel/qobject.cpp37
-rw-r--r--src/corelib/kernel/qtimer.cpp185
-rw-r--r--src/corelib/kernel/qtimer.h64
-rw-r--r--src/corelib/mimetypes/qmimetype.cpp13
-rw-r--r--src/corelib/mimetypes/qmimetype.h5
-rw-r--r--src/corelib/plugin/qlibrary.cpp39
-rw-r--r--src/corelib/plugin/qlibrary_p.h7
-rw-r--r--src/corelib/plugin/qlibrary_unix.cpp1
-rw-r--r--src/corelib/plugin/qpluginloader.cpp11
-rw-r--r--src/corelib/statemachine/qabstracttransition.cpp33
-rw-r--r--src/corelib/statemachine/qabstracttransition.h14
-rw-r--r--src/corelib/statemachine/qhistorystate.cpp28
-rw-r--r--src/corelib/statemachine/qhistorystate.h16
-rw-r--r--src/corelib/statemachine/qsignaltransition.cpp21
-rw-r--r--src/corelib/statemachine/qsignaltransition.h17
-rw-r--r--src/corelib/statemachine/qstate.cpp42
-rw-r--r--src/corelib/statemachine/qstate.h21
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp37
-rw-r--r--src/corelib/statemachine/qstatemachine.h4
-rw-r--r--src/corelib/thread/qgenericatomic.h12
-rw-r--r--src/corelib/thread/qthread_p.h23
-rw-r--r--src/corelib/thread/qthread_win.cpp147
-rw-r--r--src/corelib/thread/qthread_winrt.cpp458
-rw-r--r--src/corelib/thread/thread.pri5
-rw-r--r--src/corelib/tools/qarraydata.cpp33
-rw-r--r--src/corelib/tools/qarraydata.h16
-rw-r--r--src/corelib/tools/qarraydataops.h16
-rw-r--r--src/corelib/tools/qbytearray.cpp61
-rw-r--r--src/corelib/tools/qbytearray.h50
-rw-r--r--src/corelib/tools/qchar.cpp8
-rw-r--r--src/corelib/tools/qchar.h66
-rw-r--r--src/corelib/tools/qcommandlineparser.cpp22
-rw-r--r--src/corelib/tools/qcommandlineparser.h1
-rw-r--r--src/corelib/tools/qdatetime.cpp8
-rw-r--r--src/corelib/tools/qdatetime.h20
-rw-r--r--src/corelib/tools/qfreelist_p.h4
-rw-r--r--src/corelib/tools/qhash.cpp39
-rw-r--r--src/corelib/tools/qhash.h105
-rw-r--r--src/corelib/tools/qiterator.h13
-rw-r--r--src/corelib/tools/qiterator.qdoc20
-rw-r--r--src/corelib/tools/qline.cpp14
-rw-r--r--src/corelib/tools/qline.h14
-rw-r--r--src/corelib/tools/qlist.cpp6
-rw-r--r--src/corelib/tools/qlist.h14
-rw-r--r--src/corelib/tools/qlocale.cpp14
-rw-r--r--src/corelib/tools/qpoint.cpp13
-rw-r--r--src/corelib/tools/qrect.cpp12
-rw-r--r--src/corelib/tools/qrect.h36
-rw-r--r--src/corelib/tools/qregularexpression.cpp114
-rw-r--r--src/corelib/tools/qregularexpression.h9
-rw-r--r--src/corelib/tools/qringbuffer_p.h318
-rw-r--r--src/corelib/tools/qscopedvaluerollback.cpp11
-rw-r--r--src/corelib/tools/qscopedvaluerollback.h9
-rw-r--r--src/corelib/tools/qset.h9
-rw-r--r--src/corelib/tools/qshareddata.cpp32
-rw-r--r--src/corelib/tools/qshareddata.h19
-rw-r--r--src/corelib/tools/qsharedpointer.cpp104
-rw-r--r--src/corelib/tools/qsharedpointer.h11
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h108
-rw-r--r--src/corelib/tools/qsimd.cpp143
-rw-r--r--src/corelib/tools/qsimd_p.h127
-rw-r--r--src/corelib/tools/qsize.cpp12
-rw-r--r--src/corelib/tools/qstring.cpp245
-rw-r--r--src/corelib/tools/qstring.h3
-rw-r--r--src/corelib/tools/qstringlist.cpp72
-rw-r--r--src/corelib/tools/qstringlist.h13
-rw-r--r--src/corelib/tools/qtimezoneprivate.cpp8
-rw-r--r--src/corelib/tools/qtimezoneprivate_p.h11
-rw-r--r--src/corelib/tools/qtimezoneprivate_tz.cpp2
-rw-r--r--src/corelib/tools/qtimezoneprivate_win.cpp4
-rw-r--r--src/corelib/tools/qtools_p.h2
-rw-r--r--src/corelib/tools/qunicodetables.cpp8
-rw-r--r--src/corelib/tools/qvector.cpp28
-rw-r--r--src/corelib/tools/qvector.h54
-rw-r--r--src/corelib/tools/tools.pri16
-rw-r--r--src/corelib/xml/qxmlstream.cpp2
-rw-r--r--src/dbus/qdbusintegrator.cpp89
-rw-r--r--src/gui/accessible/qaccessible.cpp59
-rw-r--r--src/gui/accessible/qaccessible.h7
-rw-r--r--src/gui/accessible/qaccessiblebridge.cpp2
-rw-r--r--src/gui/accessible/qaccessiblebridge.h2
-rw-r--r--src/gui/accessible/qaccessiblecache.cpp2
-rw-r--r--src/gui/accessible/qaccessiblecache_mac.mm10
-rw-r--r--src/gui/accessible/qaccessiblecache_p.h12
-rw-r--r--src/gui/accessible/qaccessibleobject.cpp2
-rw-r--r--src/gui/accessible/qaccessibleobject.h2
-rw-r--r--src/gui/accessible/qaccessibleplugin.cpp2
-rw-r--r--src/gui/accessible/qaccessibleplugin.h2
-rw-r--r--src/gui/accessible/qplatformaccessibility.cpp2
-rw-r--r--src/gui/accessible/qplatformaccessibility.h2
-rw-r--r--src/gui/doc/images/qpixelformat-argb32buffer.pngbin0 -> 14282 bytes
-rw-r--r--src/gui/doc/qtgui.qdocconf1
-rw-r--r--src/gui/doc/src/dnd.qdoc10
-rw-r--r--src/gui/image/image.pri10
-rw-r--r--src/gui/image/qbmphandler.cpp4
-rw-r--r--src/gui/image/qicon.cpp18
-rw-r--r--src/gui/image/qicon_p.h4
-rw-r--r--src/gui/image/qimage.cpp435
-rw-r--r--src/gui/image/qimage.h9
-rw-r--r--src/gui/image/qimage_conversions.cpp615
-rw-r--r--src/gui/image/qimage_mips_dspr2.cpp20
-rw-r--r--src/gui/image/qimage_mips_dspr2_asm.S92
-rw-r--r--src/gui/image/qimage_p.h6
-rw-r--r--src/gui/image/qimagereader.cpp37
-rw-r--r--src/gui/image/qimagereader.h2
-rw-r--r--src/gui/image/qimagewriter.cpp41
-rw-r--r--src/gui/image/qimagewriter.h2
-rw-r--r--src/gui/image/qjpeghandler.cpp6
-rw-r--r--src/gui/image/qpicture.cpp2
-rw-r--r--src/gui/image/qpixmap.cpp20
-rw-r--r--src/gui/image/qppmhandler.cpp4
-rw-r--r--src/gui/kernel/kernel.pri11
-rw-r--r--src/gui/kernel/qclipboard.cpp32
-rw-r--r--src/gui/kernel/qclipboard_qpa.cpp89
-rw-r--r--src/gui/kernel/qcursor.cpp127
-rw-r--r--src/gui/kernel/qcursor_qpa.cpp135
-rw-r--r--src/gui/kernel/qdnd.cpp1
-rw-r--r--src/gui/kernel/qevent.cpp308
-rw-r--r--src/gui/kernel/qevent.h19
-rw-r--r--src/gui/kernel/qevent_p.h14
-rw-r--r--src/gui/kernel/qguiapplication.cpp93
-rw-r--r--src/gui/kernel/qguiapplication.h7
-rw-r--r--src/gui/kernel/qguiapplication_p.h5
-rw-r--r--src/gui/kernel/qkeymapper.cpp31
-rw-r--r--src/gui/kernel/qoffscreensurface.cpp3
-rw-r--r--src/gui/kernel/qopenglcontext.cpp91
-rw-r--r--src/gui/kernel/qopenglcontext.h5
-rw-r--r--src/gui/kernel/qopenglcontext_p.h4
-rw-r--r--src/gui/kernel/qpalette.cpp30
-rw-r--r--src/gui/kernel/qpixelformat.cpp630
-rw-r--r--src/gui/kernel/qpixelformat.h452
-rw-r--r--src/gui/kernel/qplatformintegration.cpp21
-rw-r--r--src/gui/kernel/qplatformnativeinterface.cpp6
-rw-r--r--src/gui/kernel/qplatformnativeinterface.h2
-rw-r--r--src/gui/kernel/qplatformsystemtrayicon.cpp (renamed from src/gui/kernel/qplatformsystemtrayicon_qpa.cpp)0
-rw-r--r--src/gui/kernel/qplatformwindow.cpp23
-rw-r--r--src/gui/kernel/qplatformwindow.h1
-rw-r--r--src/gui/kernel/qscreen.cpp10
-rw-r--r--src/gui/kernel/qscreen.h1
-rw-r--r--src/gui/kernel/qwindow.cpp167
-rw-r--r--src/gui/kernel/qwindow_p.h10
-rw-r--r--src/gui/kernel/qwindowdefs_win.h4
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp32
-rw-r--r--src/gui/kernel/qwindowsysteminterface.h14
-rw-r--r--src/gui/kernel/qwindowsysteminterface_p.h17
-rw-r--r--src/gui/math3d/qmatrix4x4.cpp46
-rw-r--r--src/gui/math3d/qmatrix4x4.h7
-rw-r--r--src/gui/opengl/opengl.pri1
-rw-r--r--src/gui/opengl/qopengl.cpp11
-rw-r--r--src/gui/opengl/qopengl.h32
-rw-r--r--src/gui/opengl/qopenglextensions_p.h2
-rw-r--r--src/gui/opengl/qopenglframebufferobject.cpp215
-rw-r--r--src/gui/opengl/qopenglframebufferobject.h1
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp40
-rw-r--r--src/gui/opengl/qopenglpaintengine.cpp12
-rw-r--r--src/gui/opengl/qopenglpaintengine_p.h2
-rw-r--r--src/gui/opengl/qopengltexture.cpp397
-rw-r--r--src/gui/opengl/qopengltexture.h14
-rw-r--r--src/gui/opengl/qopengltextureblitter.cpp21
-rw-r--r--src/gui/opengl/qopengltextureblitter_p.h1
-rw-r--r--src/gui/opengl/qopengltexturecache.cpp149
-rw-r--r--src/gui/opengl/qopengltexturecache_p.h18
-rw-r--r--src/gui/opengl/qopenglversionfunctions.cpp16
-rw-r--r--src/gui/opengl/qopenglvertexarrayobject.cpp42
-rw-r--r--src/gui/painting/painting.pri13
-rw-r--r--src/gui/painting/qblendfunctions.cpp809
-rw-r--r--src/gui/painting/qcolor.h10
-rw-r--r--src/gui/painting/qcolor_p.cpp10
-rw-r--r--src/gui/painting/qdrawhelper.cpp163
-rw-r--r--src/gui/painting/qdrawhelper_p.h117
-rw-r--r--src/gui/painting/qmatrix.h2
-rw-r--r--src/gui/painting/qmemrotate.cpp5
-rw-r--r--src/gui/painting/qpaintengine.h2
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp6
-rw-r--r--src/gui/painting/qpaintengine_raster_p.h2
-rw-r--r--src/gui/painting/qpainter.cpp2
-rw-r--r--src/gui/painting/qpainterpath.cpp3
-rw-r--r--src/gui/painting/qpen.cpp18
-rw-r--r--src/gui/painting/qpen.h2
-rw-r--r--src/gui/painting/qplatformbackingstore.cpp49
-rw-r--r--src/gui/painting/qpolygon.h10
-rw-r--r--src/gui/painting/qregion.h28
-rw-r--r--src/gui/painting/qtextureglyphcache.cpp20
-rw-r--r--src/gui/painting/qtransform.h6
-rw-r--r--src/gui/text/qfont.cpp239
-rw-r--r--src/gui/text/qfont_p.h2
-rw-r--r--src/gui/text/qfont_qpa.cpp95
-rw-r--r--src/gui/text/qfontdatabase.h2
-rw-r--r--src/gui/text/qfontengine.cpp115
-rw-r--r--src/gui/text/qfontengine_p.h23
-rw-r--r--src/gui/text/qfontengine_qpf2.cpp (renamed from src/gui/text/qfontengine_qpa.cpp)286
-rw-r--r--src/gui/text/qfontengine_qpf2_p.h (renamed from src/gui/text/qfontengine_qpa_p.h)49
-rw-r--r--src/gui/text/qplatformfontdatabase.cpp18
-rw-r--r--src/gui/text/qrawfont.cpp18
-rw-r--r--src/gui/text/qrawfont_p.h3
-rw-r--r--src/gui/text/qtextengine.cpp266
-rw-r--r--src/gui/text/qtextengine_p.h39
-rw-r--r--src/gui/text/qtextlayout.cpp25
-rw-r--r--src/gui/text/text.pri6
-rw-r--r--src/gui/util/qdesktopservices.cpp2
-rw-r--r--src/gui/util/qgridlayoutengine.cpp26
-rw-r--r--src/gui/util/qgridlayoutengine_p.h12
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp6
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp2
-rw-r--r--src/network/access/qnetworkaccessbackend.cpp4
-rw-r--r--src/network/access/qnetworkaccessmanager_p.h2
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp16
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp4
-rw-r--r--src/network/access/qspdyprotocolhandler.cpp20
-rw-r--r--src/network/doc/qtnetwork.qdocconf1
-rw-r--r--src/network/kernel/qauthenticator.cpp9
-rw-r--r--src/network/kernel/qauthenticator.h1
-rw-r--r--src/network/kernel/qdnslookup.cpp14
-rw-r--r--src/network/kernel/qdnslookup_winrt.cpp30
-rw-r--r--src/network/kernel/qhostinfo_winrt.cpp43
-rw-r--r--src/network/kernel/qnetworkinterface_winrt.cpp28
-rw-r--r--src/network/network.pro11
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp17
-rw-r--r--src/network/socket/qnativesocketengine_winrt.cpp20
-rw-r--r--src/network/socket/qnativesocketengine_winrt_p.h6
-rw-r--r--src/network/ssl/qsslcertificate.cpp36
-rw-r--r--src/network/ssl/qsslcertificate.h6
-rw-r--r--src/network/ssl/qsslconfiguration.cpp13
-rw-r--r--src/network/ssl/qsslconfiguration.h1
-rw-r--r--src/network/ssl/qsslconfiguration_p.h4
-rw-r--r--src/network/ssl/qsslkey.cpp32
-rw-r--r--src/network/ssl/qsslkey.h1
-rw-r--r--src/network/ssl/qsslkey_p.h1
-rw-r--r--src/network/ssl/qsslsocket.cpp42
-rw-r--r--src/network/ssl/qsslsocket.h3
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp101
-rw-r--r--src/network/ssl/qsslsocket_openssl_p.h5
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp16
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols_p.h10
-rw-r--r--src/network/ssl/qsslsocket_p.h3
-rw-r--r--src/opengl/gl2paintengineex/qglgradientcache.cpp14
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp95
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h8
-rw-r--r--src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp81
-rw-r--r--src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h2
-rw-r--r--src/opengl/opengl.pro3
-rw-r--r--src/opengl/qgl.cpp701
-rw-r--r--src/opengl/qgl_p.h2
-rw-r--r--src/opengl/qgl_qpa.cpp464
-rw-r--r--src/opengl/qglbuffer.cpp4
-rw-r--r--src/opengl/qglframebufferobject.cpp36
-rw-r--r--src/opengl/qglpaintdevice.cpp9
-rw-r--r--src/opengl/qglpixelbuffer.cpp33
-rw-r--r--src/opengl/qglshaderprogram.cpp5
-rw-r--r--src/platformheaders/doc/qtplatformheaders.qdocconf53
-rw-r--r--src/platformheaders/doc/snippets/qxcbwindowfunctions/main.cpp61
-rw-r--r--src/platformheaders/doc/src/qtplatformheaders.qdoc82
-rw-r--r--src/platformheaders/eglfsfunctions/eglfsfunctions.pri1
-rw-r--r--src/platformheaders/eglfsfunctions/qeglfsfunctions.h (renamed from src/plugins/platforms/winrt/qwinrtplatformtheme.cpp)45
-rw-r--r--src/platformheaders/eglfsfunctions/qeglfsfunctions.qdoc67
-rw-r--r--src/platformheaders/nativecontexts/nativecontexts.pri4
-rw-r--r--src/platformheaders/nativecontexts/qcocoanativecontext.h70
-rw-r--r--src/platformheaders/nativecontexts/qcocoanativecontext.qdoc58
-rw-r--r--src/platformheaders/nativecontexts/qeglnativecontext.h74
-rw-r--r--src/platformheaders/nativecontexts/qeglnativecontext.qdoc64
-rw-r--r--src/platformheaders/nativecontexts/qglxnativecontext.h83
-rw-r--r--src/platformheaders/nativecontexts/qglxnativecontext.qdoc83
-rw-r--r--src/platformheaders/nativecontexts/qwglnativecontext.h76
-rw-r--r--src/platformheaders/nativecontexts/qwglnativecontext.qdoc131
-rw-r--r--src/platformheaders/platformheaders.pro14
-rw-r--r--src/platformheaders/xcbfunctions/qxcbwindowfunctions.h88
-rw-r--r--src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc83
-rw-r--r--src/platformheaders/xcbfunctions/xcbfunctions.pri1
-rw-r--r--src/platformsupport/accessibility/accessibility.pri9
-rw-r--r--src/platformsupport/accessibility/qaccessiblebridgeutils.cpp119
-rw-r--r--src/platformsupport/accessibility/qaccessiblebridgeutils_p.h (renamed from src/gui/text/qrawfont_qpa.cpp)33
-rw-r--r--src/platformsupport/eglconvenience/eglconvenience.pri11
-rw-r--r--src/platformsupport/eglconvenience/qeglcompositor.cpp43
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp15
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h2
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcontext.cpp82
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcontext_p.h7
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformintegration.cpp78
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformintegration_p.h11
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformwindow.cpp8
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformwindow_p.h1
-rw-r--r--src/platformsupport/fbconvenience/qfbscreen.cpp6
-rw-r--r--src/platformsupport/fbconvenience/qfbscreen_p.h2
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp1
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig.cpp2
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig_p.h4
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm2
-rw-r--r--src/platformsupport/glxconvenience/qglxconvenience.cpp39
-rw-r--r--src/platformsupport/glxconvenience/qglxconvenience_p.h3
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp6
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h9
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp26
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h3
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp75
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h10
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp19
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h2
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouch.cpp12
-rw-r--r--src/platformsupport/linuxaccessibility/application.cpp41
-rw-r--r--src/platformsupport/linuxaccessibility/application_p.h3
-rw-r--r--src/platformsupport/linuxaccessibility/atspiadaptor.cpp49
-rw-r--r--src/platformsupport/linuxaccessibility/atspiadaptor_p.h7
-rw-r--r--src/platformsupport/linuxaccessibility/bridge.cpp8
-rw-r--r--src/platformsupport/linuxaccessibility/bridge_p.h2
-rw-r--r--src/platformsupport/linuxaccessibility/cache.cpp2
-rw-r--r--src/platformsupport/linuxaccessibility/cache_p.h2
-rw-r--r--src/platformsupport/linuxaccessibility/constant_mappings.cpp2
-rw-r--r--src/platformsupport/linuxaccessibility/constant_mappings_p.h2
-rw-r--r--src/platformsupport/linuxaccessibility/dbusconnection.cpp10
-rw-r--r--src/platformsupport/linuxaccessibility/dbusconnection_p.h2
-rw-r--r--src/platformsupport/linuxaccessibility/struct_marshallers.cpp2
-rw-r--r--src/platformsupport/linuxaccessibility/struct_marshallers_p.h2
-rw-r--r--src/platformsupport/platformsupport.pro1
-rw-r--r--src/platformsupport/themes/genericunix/qgenericunixthemes.cpp167
-rw-r--r--src/platformsupport/themes/genericunix/qgenericunixthemes_p.h2
-rw-r--r--src/plugins/accessible/accessible.pro5
-rw-r--r--src/plugins/accessible/widgets/widgets.json54
-rw-r--r--src/plugins/bearer/android/android.pro4
-rw-r--r--src/plugins/bearer/android/jar/bundledjar.pro3
-rw-r--r--src/plugins/bearer/android/jar/distributedjar.pro2
-rw-r--r--src/plugins/bearer/android/jar/jar.pri13
-rw-r--r--src/plugins/bearer/android/jar/jar.pro2
-rw-r--r--src/plugins/bearer/android/jar/src/org/qtproject/qt5/android/bearer/QtNetworkReceiver.java95
-rw-r--r--src/plugins/bearer/android/src/android.json3
-rw-r--r--src/plugins/bearer/android/src/main.cpp65
-rw-r--r--src/plugins/bearer/android/src/qandroidbearerengine.cpp405
-rw-r--r--src/plugins/bearer/android/src/qandroidbearerengine.h97
-rw-r--r--src/plugins/bearer/android/src/src.pro17
-rw-r--r--src/plugins/bearer/android/src/wrappers/androidconnectivitymanager.cpp394
-rw-r--r--src/plugins/bearer/android/src/wrappers/androidconnectivitymanager.h170
-rw-r--r--src/plugins/bearer/android/src/wrappers/wrappers.pri6
-rw-r--r--src/plugins/bearer/bearer.pro1
-rw-r--r--src/plugins/bearer/connman/qconnmanengine.cpp29
-rw-r--r--src/plugins/imageformats/ico/ico.json2
-rw-r--r--src/plugins/imageformats/ico/main.cpp2
-rw-r--r--src/plugins/imageformats/ico/qicohandler.cpp10
-rw-r--r--src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.InputContext.xml10
-rw-r--r--src/plugins/platforminputcontexts/ibus/main.cpp9
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.cpp2
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.h15
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp61
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h2
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibustypes.cpp140
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibustypes.h27
-rw-r--r--src/plugins/platforms/android/android.pro7
-rw-r--r--src/plugins/platforms/android/androidjniaccessibility.cpp48
-rw-r--r--src/plugins/platforms/android/extract.cpp135
-rw-r--r--src/plugins/platforms/android/qandroidplatformbackingstore.h2
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.cpp2
-rw-r--r--src/plugins/platforms/cocoa/cocoa.pro8
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm11
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h8
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm58
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm22
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm30
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm18
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm13
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.mm16
-rw-r--r--src/plugins/platforms/cocoa/qcocoasystemsettings.mm23
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm8
-rw-r--r--src/plugins/platforms/cocoa/qnsview.h4
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm8
-rw-r--r--src/plugins/platforms/cocoa/qnsviewaccessibility.mm2
-rw-r--r--src/plugins/platforms/cocoa/qpaintengine_mac.mm6
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h18
-rw-r--r--src/plugins/platforms/eglfs/qeglfscontext.cpp7
-rw-r--r--src/plugins/platforms/eglfs/qeglfscontext.h4
-rw-r--r--src/plugins/platforms/eglfs/qeglfsintegration.cpp16
-rw-r--r--src/plugins/platforms/eglfs/qeglfsintegration.h3
-rw-r--r--src/plugins/platforms/eglfs/qeglfswindow.cpp4
-rw-r--r--src/plugins/platforms/ios/ios.pro12
-rw-r--r--src/plugins/platforms/ios/qiosapplicationdelegate.h3
-rw-r--r--src/plugins/platforms/ios/qiosapplicationdelegate.mm45
-rw-r--r--src/plugins/platforms/ios/qioscontext.mm1
-rw-r--r--src/plugins/platforms/ios/qiosintegration.h8
-rw-r--r--src/plugins/platforms/ios/qiosintegration.mm32
-rw-r--r--src/plugins/platforms/ios/qiosplatformaccessibility.h (renamed from src/plugins/platforms/winrt/qwinrtplatformtheme.h)16
-rw-r--r--src/plugins/platforms/ios/qiosplatformaccessibility.mm85
-rw-r--r--src/plugins/platforms/ios/qiosscreen.h5
-rw-r--r--src/plugins/platforms/ios/qiosscreen.mm121
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.h8
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm32
-rw-r--r--src/plugins/platforms/ios/qioswindow.h2
-rw-r--r--src/plugins/platforms/ios/qioswindow.mm317
-rw-r--r--src/plugins/platforms/ios/quiaccessibilityelement.h58
-rw-r--r--src/plugins/platforms/ios/quiaccessibilityelement.mm193
-rw-r--r--src/plugins/platforms/ios/quiview.h28
-rw-r--r--src/plugins/platforms/ios/quiview.mm345
-rw-r--r--src/plugins/platforms/ios/quiview_accessibility.mm117
-rw-r--r--src/plugins/platforms/ios/quiview_textinput.mm3
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp2
-rw-r--r--src/plugins/platforms/qnx/qqnxscreen.cpp99
-rw-r--r--src/plugins/platforms/qnx/qqnxscreen.h4
-rw-r--r--src/plugins/platforms/windows/accessible/comutils.cpp2
-rw-r--r--src/plugins/platforms/windows/accessible/comutils.h2
-rw-r--r--src/plugins/platforms/windows/accessible/iaccessible2.cpp65
-rw-r--r--src/plugins/platforms/windows/accessible/iaccessible2.h2
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp2
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsaccessibility.h2
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp11
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h2
-rw-r--r--src/plugins/platforms/windows/cursors.qrc25
-rw-r--r--src/plugins/platforms/windows/images/closedhandcursor_32.pngbin0 -> 278 bytes
-rw-r--r--src/plugins/platforms/windows/images/closedhandcursor_48.pngbin0 -> 350 bytes
-rw-r--r--src/plugins/platforms/windows/images/closedhandcursor_64.pngbin0 -> 418 bytes
-rw-r--r--src/plugins/platforms/windows/images/dragcopycursor_32.pngbin0 -> 300 bytes
-rw-r--r--src/plugins/platforms/windows/images/dragcopycursor_48.pngbin0 -> 376 bytes
-rw-r--r--src/plugins/platforms/windows/images/dragcopycursor_64.pngbin0 -> 444 bytes
-rw-r--r--src/plugins/platforms/windows/images/draglinkcursor_32.pngbin0 -> 345 bytes
-rw-r--r--src/plugins/platforms/windows/images/draglinkcursor_48.pngbin0 -> 394 bytes
-rw-r--r--src/plugins/platforms/windows/images/draglinkcursor_64.pngbin0 -> 470 bytes
-rw-r--r--src/plugins/platforms/windows/images/dragmovecursor_32.pngbin0 -> 322 bytes
-rw-r--r--src/plugins/platforms/windows/images/dragmovecursor_48.pngbin0 -> 390 bytes
-rw-r--r--src/plugins/platforms/windows/images/dragmovecursor_64.pngbin0 -> 463 bytes
-rw-r--r--src/plugins/platforms/windows/images/openhandcursor_32.pngbin0 -> 315 bytes
-rw-r--r--src/plugins/platforms/windows/images/openhandcursor_48.pngbin0 -> 363 bytes
-rw-r--r--src/plugins/platforms/windows/images/openhandcursor_64.pngbin0 -> 452 bytes
-rw-r--r--src/plugins/platforms/windows/images/splithcursor_32.pngbin0 -> 178 bytes
-rw-r--r--src/plugins/platforms/windows/images/splithcursor_48.pngbin0 -> 210 bytes
-rw-r--r--src/plugins/platforms/windows/images/splithcursor_64.pngbin0 -> 243 bytes
-rw-r--r--src/plugins/platforms/windows/images/splitvcursor_32.pngbin0 -> 187 bytes
-rw-r--r--src/plugins/platforms/windows/images/splitvcursor_48.pngbin0 -> 212 bytes
-rw-r--r--src/plugins/platforms/windows/images/splitvcursor_64.pngbin0 -> 211 bytes
-rw-r--r--src/plugins/platforms/windows/qtwindowsglobal.h10
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.h10
-rw-r--r--src/plugins/platforms/windows/qwindowsclipboard.cpp40
-rw-r--r--src/plugins/platforms/windows/qwindowsclipboard.h15
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp59
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h24
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp509
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.h11
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp214
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.h6
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.cpp829
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.h257
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.cpp72
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.h23
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp25
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.cpp7
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.h62
-rw-r--r--src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp385
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.h132
-rw-r--r--src/plugins/platforms/windows/qwindowsguieventdispatcher.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.h6
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp190
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h29
-rw-r--r--src/plugins/platforms/windows/qwindowsinternalmimedata.h6
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.cpp32
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.h6
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.cpp70
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.h18
-rw-r--r--src/plugins/platforms/windows/qwindowsopenglcontext.h89
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.cpp146
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.h52
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp52
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.h28
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.cpp7
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.h12
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp124
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h79
-rw-r--r--src/plugins/platforms/windows/windows.pri11
-rw-r--r--src/plugins/platforms/winrt/qwinrtcursor.cpp60
-rw-r--r--src/plugins/platforms/winrt/qwinrtcursor.h24
-rw-r--r--src/plugins/platforms/winrt/qwinrtintegration.cpp58
-rw-r--r--src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp232
-rw-r--r--src/plugins/platforms/winrt/qwinrtmessagedialoghelper.h (renamed from src/plugins/platforms/winrt/qwinrtplatformmessagedialoghelper.h)29
-rw-r--r--src/plugins/platforms/winrt/qwinrtplatformmessagedialoghelper.cpp204
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.cpp544
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.h84
-rw-r--r--src/plugins/platforms/winrt/qwinrtservices.cpp122
-rw-r--r--src/plugins/platforms/winrt/qwinrtservices.h27
-rw-r--r--src/plugins/platforms/winrt/qwinrttheme.cpp211
-rw-r--r--src/plugins/platforms/winrt/qwinrttheme.h70
-rw-r--r--src/plugins/platforms/winrt/winrt.pro10
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp164
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.h11
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp5
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h5
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp52
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp7
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.h5
-rw-r--r--src/plugins/platforms/xcb/qxcbimage.cpp15
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp23
-rw-r--r--src/plugins/platforms/xcb/qxcbmime.cpp7
-rw-r--r--src/plugins/platforms/xcb/qxcbmime.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp140
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.h23
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp9
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp189
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h7
-rw-r--r--src/plugins/platforms/xcb/qxcbxsettings.cpp45
-rw-r--r--src/plugins/plugins.pro1
-rw-r--r--src/printsupport/doc/qtprintsupport.qdocconf1
-rw-r--r--src/printsupport/kernel/qcups.cpp152
-rw-r--r--src/printsupport/kernel/qpaintengine_alpha.cpp40
-rw-r--r--src/printsupport/kernel/qpaintengine_alpha_p.h4
-rw-r--r--src/printsupport/kernel/qprintengine_win.cpp8
-rw-r--r--src/sql/doc/qtsql.qdocconf1
-rw-r--r--src/sql/kernel/qsqlquery.cpp26
-rw-r--r--src/src.pro12
-rw-r--r--src/testlib/doc/qttestlib.qdocconf1
-rw-r--r--src/testlib/doc/snippets/code/doc_src_qsignalspy.cpp5
-rw-r--r--src/testlib/qplaintestlogger.cpp18
-rw-r--r--src/testlib/qsignalspy.h57
-rw-r--r--src/testlib/qsignalspy.qdoc14
-rw-r--r--src/testlib/qtestaccessible.h51
-rw-r--r--src/testlib/qtestcase.cpp2
-rw-r--r--src/testlib/qtestcase.h2
-rw-r--r--src/testlib/qtestlog.cpp8
-rw-r--r--src/testlib/qxmltestlogger.cpp7
-rw-r--r--src/testlib/qxunittestlogger.cpp14
-rw-r--r--src/tools/bootstrap/bootstrap.pro1
-rw-r--r--src/tools/moc/generator.cpp6
-rw-r--r--src/tools/moc/moc.cpp7
-rw-r--r--src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp6
-rw-r--r--src/tools/qdoc/atom.cpp76
-rw-r--r--src/tools/qdoc/atom.h87
-rw-r--r--src/tools/qdoc/codemarker.cpp19
-rw-r--r--src/tools/qdoc/codemarker.h3
-rw-r--r--src/tools/qdoc/codeparser.cpp61
-rw-r--r--src/tools/qdoc/codeparser.h2
-rw-r--r--src/tools/qdoc/config.cpp117
-rw-r--r--src/tools/qdoc/config.h10
-rw-r--r--src/tools/qdoc/cppcodemarker.cpp46
-rw-r--r--src/tools/qdoc/cppcodemarker.h2
-rw-r--r--src/tools/qdoc/cppcodeparser.cpp226
-rw-r--r--src/tools/qdoc/ditaxmlgenerator.cpp871
-rw-r--r--src/tools/qdoc/ditaxmlgenerator.h16
-rw-r--r--src/tools/qdoc/doc.cpp174
-rw-r--r--src/tools/qdoc/doc/config/qdoc.qdocconf1
-rw-r--r--src/tools/qdoc/doc/files/qtgui.qdocconf1
-rw-r--r--src/tools/qdoc/doc/qdoc-manual-markupcmds.qdoc28
-rw-r--r--src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc9
-rw-r--r--src/tools/qdoc/doc/qdoc-manual-topiccmds.qdoc4
-rw-r--r--src/tools/qdoc/generator.cpp299
-rw-r--r--src/tools/qdoc/generator.h30
-rw-r--r--src/tools/qdoc/helpprojectwriter.cpp111
-rw-r--r--src/tools/qdoc/htmlgenerator.cpp1112
-rw-r--r--src/tools/qdoc/htmlgenerator.h23
-rw-r--r--src/tools/qdoc/location.cpp2
-rw-r--r--src/tools/qdoc/location.h2
-rw-r--r--src/tools/qdoc/main.cpp312
-rw-r--r--src/tools/qdoc/node.cpp889
-rw-r--r--src/tools/qdoc/node.h338
-rw-r--r--src/tools/qdoc/puredocparser.cpp2
-rw-r--r--src/tools/qdoc/puredocparser.h1
-rw-r--r--src/tools/qdoc/qdocdatabase.cpp1525
-rw-r--r--src/tools/qdoc/qdocdatabase.h384
-rw-r--r--src/tools/qdoc/qdocindexfiles.cpp634
-rw-r--r--src/tools/qdoc/qdocindexfiles.h8
-rw-r--r--src/tools/qdoc/qdoctagfiles.cpp38
-rw-r--r--src/tools/qdoc/qmlcodeparser.h1
-rw-r--r--src/tools/qdoc/qmlvisitor.cpp14
-rw-r--r--src/tools/qdoc/text.cpp16
-rw-r--r--src/tools/qdoc/text.h1
-rw-r--r--src/tools/qdoc/tree.cpp1137
-rw-r--r--src/tools/qdoc/tree.h141
-rw-r--r--src/tools/rcc/main.cpp73
-rw-r--r--src/tools/rcc/rcc.cpp188
-rw-r--r--src/tools/rcc/rcc.h11
-rw-r--r--src/widgets/accessible/accessible.pri21
-rw-r--r--src/widgets/accessible/complexwidgets.cpp (renamed from src/plugins/accessible/widgets/complexwidgets.cpp)16
-rw-r--r--src/widgets/accessible/complexwidgets.h (renamed from src/plugins/accessible/widgets/complexwidgets.h)2
-rw-r--r--src/widgets/accessible/itemviews.cpp (renamed from src/plugins/accessible/widgets/itemviews.cpp)4
-rw-r--r--src/widgets/accessible/itemviews.h (renamed from src/plugins/accessible/widgets/itemviews.h)2
-rw-r--r--src/widgets/accessible/qaccessiblemenu.cpp (renamed from src/plugins/accessible/widgets/qaccessiblemenu.cpp)6
-rw-r--r--src/widgets/accessible/qaccessiblemenu.h (renamed from src/plugins/accessible/widgets/qaccessiblemenu.h)2
-rw-r--r--src/widgets/accessible/qaccessiblewidget.cpp6
-rw-r--r--src/widgets/accessible/qaccessiblewidget.h2
-rw-r--r--src/widgets/accessible/qaccessiblewidgetfactory.cpp (renamed from src/plugins/accessible/widgets/main.cpp)25
-rw-r--r--src/widgets/accessible/qaccessiblewidgetfactory_p.h53
-rw-r--r--src/widgets/accessible/qaccessiblewidgets.cpp (renamed from src/plugins/accessible/widgets/qaccessiblewidgets.cpp)109
-rw-r--r--src/widgets/accessible/qaccessiblewidgets.h (renamed from src/plugins/accessible/widgets/qaccessiblewidgets.h)2
-rw-r--r--src/widgets/accessible/rangecontrols.cpp (renamed from src/plugins/accessible/widgets/rangecontrols.cpp)19
-rw-r--r--src/widgets/accessible/rangecontrols.h (renamed from src/plugins/accessible/widgets/rangecontrols.h)2
-rw-r--r--src/widgets/accessible/simplewidgets.cpp (renamed from src/plugins/accessible/widgets/simplewidgets.cpp)32
-rw-r--r--src/widgets/accessible/simplewidgets.h (renamed from src/plugins/accessible/widgets/simplewidgets.h)3
-rw-r--r--src/widgets/accessible/widgets.pro (renamed from src/plugins/accessible/widgets/widgets.pro)0
-rw-r--r--src/widgets/dialogs/qcolordialog.cpp77
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp78
-rw-r--r--src/widgets/dialogs/qfiledialog.h4
-rw-r--r--src/widgets/dialogs/qfiledialog_p.h6
-rw-r--r--src/widgets/dialogs/qinputdialog.cpp40
-rw-r--r--src/widgets/dialogs/qsidebar.cpp3
-rw-r--r--src/widgets/dialogs/qwizard.cpp2
-rw-r--r--src/widgets/doc/qtwidgets.qdocconf1
-rw-r--r--src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc5
-rw-r--r--src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc20
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.cpp43
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.h3
-rw-r--r--src/widgets/graphicsview/qgraphicsitem_p.h15
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.cpp88
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.h5
-rw-r--r--src/widgets/graphicsview/qgraphicsscene_p.h2
-rw-r--r--src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp24
-rw-r--r--src/widgets/graphicsview/qgraphicssceneevent.cpp58
-rw-r--r--src/widgets/graphicsview/qgraphicssceneevent.h6
-rw-r--r--src/widgets/graphicsview/qgraphicssceneindex.cpp3
-rw-r--r--src/widgets/graphicsview/qgraphicsscenelinearindex_p.h45
-rw-r--r--src/widgets/graphicsview/qgraphicsview.cpp8
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp25
-rw-r--r--src/widgets/itemviews/qfileiconprovider.cpp6
-rw-r--r--src/widgets/itemviews/qtableview.cpp9
-rw-r--r--src/widgets/kernel/kernel.pri7
-rw-r--r--src/widgets/kernel/qapplication.cpp430
-rw-r--r--src/widgets/kernel/qapplication.h1
-rw-r--r--src/widgets/kernel/qapplication_qpa.cpp493
-rw-r--r--src/widgets/kernel/qdesktopwidget.cpp142
-rw-r--r--src/widgets/kernel/qdesktopwidget_p.h (renamed from src/widgets/kernel/qdesktopwidget_qpa_p.h)4
-rw-r--r--src/widgets/kernel/qdesktopwidget_qpa.cpp193
-rw-r--r--src/widgets/kernel/qgesturemanager.cpp2
-rw-r--r--src/widgets/kernel/qshortcut.cpp2
-rw-r--r--src/widgets/kernel/qwidget.cpp1112
-rw-r--r--src/widgets/kernel/qwidget.h1
-rw-r--r--src/widgets/kernel/qwidget_p.h4
-rw-r--r--src/widgets/kernel/qwidget_qpa.cpp1126
-rw-r--r--src/widgets/kernel/qwidgetbackingstore_p.h1
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp6
-rw-r--r--src/widgets/kernel/qwidgetwindow_p.h (renamed from src/widgets/kernel/qwidgetwindow_qpa_p.h)6
-rw-r--r--src/widgets/statemachine/qguistatemachine.cpp2
-rw-r--r--src/widgets/styles/qandroidstyle.cpp386
-rw-r--r--src/widgets/styles/qandroidstyle_p.h9
-rw-r--r--src/widgets/styles/qcommonstyle.cpp3
-rw-r--r--src/widgets/styles/qfusionstyle.cpp140
-rw-r--r--src/widgets/styles/qmacstyle_mac.mm65
-rw-r--r--src/widgets/styles/qstyle.cpp3
-rw-r--r--src/widgets/styles/qstyle.h1
-rw-r--r--src/widgets/styles/qstyleoption.cpp2
-rw-r--r--src/widgets/styles/qstylesheetstyle.cpp21
-rw-r--r--src/widgets/styles/qwindowsvistastyle.cpp8
-rw-r--r--src/widgets/util/qflickgesture.cpp2
-rw-r--r--src/widgets/util/qsystemtrayicon.cpp68
-rw-r--r--src/widgets/util/qsystemtrayicon_p.h9
-rw-r--r--src/widgets/util/qsystemtrayicon_qpa.cpp51
-rw-r--r--src/widgets/util/qsystemtrayicon_x11.cpp72
-rw-r--r--src/widgets/widgets.pro3
-rw-r--r--src/widgets/widgets/qabstractspinbox.cpp2
-rw-r--r--src/widgets/widgets/qcheckbox.h1
-rw-r--r--src/widgets/widgets/qdockarealayout.cpp8
-rw-r--r--src/widgets/widgets/qdockwidget.cpp22
-rw-r--r--src/widgets/widgets/qdockwidget_p.h8
-rw-r--r--src/widgets/widgets/qgroupbox.cpp2
-rw-r--r--src/widgets/widgets/qlineedit.cpp3
-rw-r--r--src/widgets/widgets/qlineedit.h3
-rw-r--r--src/widgets/widgets/qlineedit_p.cpp14
-rw-r--r--src/widgets/widgets/qlineedit_p.h1
-rw-r--r--src/widgets/widgets/qmainwindow.cpp4
-rw-r--r--src/widgets/widgets/qmainwindow.h7
-rw-r--r--src/widgets/widgets/qmdiarea.cpp75
-rw-r--r--src/widgets/widgets/qmdiarea_p.h22
-rw-r--r--src/widgets/widgets/qmenu.cpp4
-rw-r--r--src/widgets/widgets/qplaintextedit.cpp2
-rw-r--r--src/widgets/widgets/qradiobutton.h1
-rw-r--r--src/widgets/widgets/qtabbar.cpp40
-rw-r--r--src/widgets/widgets/qtabbar.h4
-rw-r--r--src/widgets/widgets/qtabbar_p.h4
-rw-r--r--src/widgets/widgets/qtabwidget.cpp23
-rw-r--r--src/widgets/widgets/qtabwidget.h4
-rw-r--r--src/widgets/widgets/qtextedit.cpp2
-rw-r--r--src/widgets/widgets/qtoolbar.cpp4
-rw-r--r--src/widgets/widgets/qtoolbutton.cpp5
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol.cpp6
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol_p.h5
-rw-r--r--src/widgets/widgets/qwidgetresizehandler.cpp4
-rw-r--r--src/widgets/widgets/qwidgettextcontrol.cpp10
-rw-r--r--src/winmain/qtmain_win.cpp50
-rw-r--r--src/winmain/qtmain_winrt.cpp4
-rw-r--r--src/winmain/winmain.pro2
-rw-r--r--src/xml/doc/qtxml.qdocconf1
877 files changed, 54747 insertions, 18332 deletions
diff --git a/src/3rdparty/android/extract.h b/src/3rdparty/android/extract.h
new file mode 100644
index 0000000000..f7928e20a8
--- /dev/null
+++ b/src/3rdparty/android/extract.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2005 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef EXTRACT_H
+#define EXTRACT_H
+
+#include <cstdint>
+#include <cstring>
+// shamelessly stolen from ResourceTypes.h Android's sources
+/**
+ * This chunk specifies how to split an image into segments for
+ * scaling.
+ *
+ * There are J horizontal and K vertical segments. These segments divide
+ * the image into J*K regions as follows (where J=4 and K=3):
+ *
+ * F0 S0 F1 S1
+ * +-----+----+------+-------+
+ * S2| 0 | 1 | 2 | 3 |
+ * +-----+----+------+-------+
+ * | | | | |
+ * | | | | |
+ * F2| 4 | 5 | 6 | 7 |
+ * | | | | |
+ * | | | | |
+ * +-----+----+------+-------+
+ * S3| 8 | 9 | 10 | 11 |
+ * +-----+----+------+-------+
+ *
+ * Each horizontal and vertical segment is considered to by either
+ * stretchable (marked by the Sx labels) or fixed (marked by the Fy
+ * labels), in the horizontal or vertical axis, respectively. In the
+ * above example, the first is horizontal segment (F0) is fixed, the
+ * next is stretchable and then they continue to alternate. Note that
+ * the segment list for each axis can begin or end with a stretchable
+ * or fixed segment.
+ *
+ * The relative sizes of the stretchy segments indicates the relative
+ * amount of stretchiness of the regions bordered by the segments. For
+ * example, regions 3, 7 and 11 above will take up more horizontal space
+ * than regions 1, 5 and 9 since the horizontal segment associated with
+ * the first set of regions is larger than the other set of regions. The
+ * ratios of the amount of horizontal (or vertical) space taken by any
+ * two stretchable slices is exactly the ratio of their corresponding
+ * segment lengths.
+ *
+ * xDivs and yDivs point to arrays of horizontal and vertical pixel
+ * indices. The first pair of Divs (in either array) indicate the
+ * starting and ending points of the first stretchable segment in that
+ * axis. The next pair specifies the next stretchable segment, etc. So
+ * in the above example xDiv[0] and xDiv[1] specify the horizontal
+ * coordinates for the regions labeled 1, 5 and 9. xDiv[2] and
+ * xDiv[3] specify the coordinates for regions 3, 7 and 11. Note that
+ * the leftmost slices always start at x=0 and the rightmost slices
+ * always end at the end of the image. So, for example, the regions 0,
+ * 4 and 8 (which are fixed along the X axis) start at x value 0 and
+ * go to xDiv[0] and slices 2, 6 and 10 start at xDiv[1] and end at
+ * xDiv[2].
+ *
+ * The array pointed to by the colors field lists contains hints for
+ * each of the regions. They are ordered according left-to-right and
+ * top-to-bottom as indicated above. For each segment that is a solid
+ * color the array entry will contain that color value; otherwise it
+ * will contain NO_COLOR. Segments that are completely transparent
+ * will always have the value TRANSPARENT_COLOR.
+ *
+ * The PNG chunk type is "npTc".
+ */
+struct Res_png_9patch
+{
+ Res_png_9patch() : wasDeserialized(false), xDivs(NULL),
+ yDivs(NULL), colors(NULL) { }
+
+ int8_t wasDeserialized;
+ int8_t numXDivs;
+ int8_t numYDivs;
+ int8_t numColors;
+
+ // These tell where the next section of a patch starts.
+ // For example, the first patch includes the pixels from
+ // 0 to xDivs[0]-1 and the second patch includes the pixels
+ // from xDivs[0] to xDivs[1]-1.
+ // Note: allocation/free of these pointers is left to the caller.
+ int32_t* xDivs;
+ int32_t* yDivs;
+
+ int32_t paddingLeft, paddingRight;
+ int32_t paddingTop, paddingBottom;
+
+ enum {
+ // The 9 patch segment is not a solid color.
+ NO_COLOR = 0x00000001,
+
+ // The 9 patch segment is completely transparent.
+ TRANSPARENT_COLOR = 0x00000000
+ };
+ // Note: allocation/free of this pointer is left to the caller.
+ uint32_t* colors;
+
+ // Deserialize/Unmarshall the patch data
+ static Res_png_9patch* deserialize(const void* data);
+};
+
+#endif
diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h
index 7723f0fb72..3d4246f55c 100644
--- a/src/3rdparty/angle/src/common/angleutils.h
+++ b/src/3rdparty/angle/src/common/angleutils.h
@@ -56,7 +56,7 @@ void SafeDeleteArray(T*& resource)
resource = NULL;
}
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
#endif
diff --git a/src/3rdparty/harfbuzz-ng/AUTHORS b/src/3rdparty/harfbuzz-ng/AUTHORS
index c611d7d476..81cdc4cf37 100644
--- a/src/3rdparty/harfbuzz-ng/AUTHORS
+++ b/src/3rdparty/harfbuzz-ng/AUTHORS
@@ -4,5 +4,6 @@ Martin Hosken
Jonathan Kew
Lars Knoll
Werner Lemberg
+Roozbeh Pournader
Owen Taylor
David Turner
diff --git a/src/3rdparty/harfbuzz-ng/NEWS b/src/3rdparty/harfbuzz-ng/NEWS
index 0a2477268a..f4fabc7cd9 100644
--- a/src/3rdparty/harfbuzz-ng/NEWS
+++ b/src/3rdparty/harfbuzz-ng/NEWS
@@ -1,3 +1,122 @@
+Overview of changes leading to 0.9.32
+Thursday, July 17, 2014
+=====================================
+
+- Apply Arabic shaping features in spec order exactly.
+- Another fix for Mongolian free variation selectors.
+- For non-Arabic scripts in Arabic shaper apply 'rlig' and 'calt'
+ together.
+- Minor adjustment to U+FFFD logic.
+- Fix hb-coretext build.
+
+
+Overview of changes leading to 0.9.31
+Wednesday, July 16, 2014
+=====================================
+
+- Only accept valid UTF-8/16/32; we missed many cases before.
+- Better shaping of invalid UTF-8/16/32. Falls back to
+ U+FFFD REPLACEMENT CHARACTER now.
+- With all changes in this release, the buffer will contain fully
+ valid Unicode after hb_buffer_add_utf8/16/32 no matter how
+ broken the input is. This can be overriden though. See below.
+- Fix Mongolian Variation Selectors for fonts without GDEF.
+- Fix minor invalid buffer access.
+- Accept zh-Hant and zh-Hans language tags. hb_ot_tag_to_language()
+ now uses these instead of private tags.
+- Build fixes.
+- New API:
+ * hb_buffer_add_codepoints(). This does what hb_buffer_add_utf32()
+ used to do, ie. no validity check on the input at all. add_utf32
+ now replaces invalid Unicode codepoints with the replacement
+ character (see below).
+ * hb_buffer_set_replacement_codepoint()
+ * hb_buffer_get_replacement_codepoint()
+ Previously, in hb_buffer_add_utf8 and hb_buffer_add_utf16, when
+ we detected broken input, we replaced that with (hb_codepoint_t)-1.
+ This has changed to use U+FFFD now, but can be changed using these
+ new API.
+
+
+Overview of changes leading to 0.9.30
+Wednesday, July 9, 2014
+=====================================
+
+- Update to Unicode 7.0.0:
+ * New scripts Manichaean and Psalter Pahlavi are shaped using
+ Arabic shaper.
+ * All the other new scripts to through the generic shaper for
+ now.
+- Minor Indic improvements.
+- Fix graphite2 backend cluster mapping [crasher!]
+- API changes:
+ * New HB_SCRIPT_* values for Unicode 7.0 scripts.
+ * New function hb_ot_layout_language_get_required_feature().
+- Build fixes.
+
+
+Overview of changes leading to 0.9.29
+Thursday, May 29, 2014
+=====================================
+
+- Implement cmap in hb-ot-font.h. No variation-selectors yet.
+- Myanmar: Allow MedialYa+Asat.
+- Various Indic fixes:
+ * Support most characters in Extended Devanagary and Vedic
+ Unicode blocks.
+ * Allow digits and a some punctuation as consonant placeholders.
+- Build fixes.
+
+
+Overview of changes leading to 0.9.28
+Monday, April 28, 2014
+=====================================
+
+- Unbreak old-spec Indic shaping. (bug 76705)
+- Fix shaping of U+17DD and U+0FC6.
+- Add HB_NO_MERGE_CLUSTERS build option. NOT to be enabled by default
+ for shipping libraries. It's an option for further experimentation
+ right now. When we are sure how to do it properly, we will add
+ public run-time API for the functionality.
+- Build fixes.
+
+
+Overview of changes leading to 0.9.27
+Tuesday, March 18, 2014
+=====================================
+
+- Don't use "register" storage class specifier
+- Wrap definition of free_langs() with HAVE_ATEXIT
+- Add coretext_aat shaper and hb_coretext_face_create() constructor
+- If HAVE_ICU_BUILTIN is defined, use hb-icu Unicode callbacks
+- Add Myanmar test case from OpenType Myanmar spec
+- Only do fallback Hebrew composition if no GPOS 'mark' available
+- Allow bootstrapping without gtk-doc
+- Use AM_MISSING_PROG for ragel and git
+- Typo in ucdn's Makefile.am
+- Improve MemoryBarrier() implementation
+
+
+Overview of changes leading to 0.9.26
+Thursday, January 30, 2014
+=====================================
+
+- Misc fixes.
+- Fix application of 'rtlm' feature.
+- Automatically apply frac/numr/dnom around U+2044 FRACTION SLASH.
+- New header: hb-ot-shape.h
+- Uniscribe: fix scratch-buffer accounting.
+- Reorder Tai Tham SAKOT to after tone-marks.
+- Add Hangul shaper.
+- New files:
+ hb-ot-shape-complex-hangul.cc
+ hb-ot-shape-complex-hebrew.cc
+ hb-ot-shape-complex-tibetan.cc
+- Disable 'cswh' feature in Arabic shaper.
+- Coretext: better handle surrogate pairs.
+- Add HB_TAG_MAX and _HB_SCRIPT_MAX_VALUE.
+
+
Overview of changes leading to 0.9.25
Wednesday, December 4, 2013
=====================================
diff --git a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
index 246c763fd6..79c2a3e2d6 100644
--- a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
+++ b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
@@ -7,8 +7,7 @@ CONFIG += \
load(qt_helper_lib)
-DEFINES += HAVE_CONFIG_H
-HEADERS += $$PWD/src/config.h
+DEFINES += HAVE_OT HAVE_ATEXIT HB_NO_UNICODE_FUNCS HB_DISABLE_DEPRECATED
INCLUDEPATH += $$PWD/include
@@ -39,6 +38,7 @@ HEADERS += \
$$PWD/src/hb-object-private.hh \
$$PWD/src/hb-open-file-private.hh \
$$PWD/src/hb-open-type-private.hh \
+ $$PWD/src/hb-ot-cmap-table.hh \
$$PWD/src/hb-ot-head-table.hh \
$$PWD/src/hb-ot-hhea-table.hh \
$$PWD/src/hb-ot-hmtx-table.hh \
@@ -58,6 +58,7 @@ HEADERS += \
$$PWD/src/hb-blob.h \
$$PWD/src/hb-buffer.h \
$$PWD/src/hb-common.h \
+ $$PWD/src/hb-deprecated.h \
$$PWD/src/hb-face.h \
$$PWD/src/hb-font.h \
$$PWD/src/hb-set.h \
@@ -68,6 +69,7 @@ HEADERS += \
# Open Type
SOURCES += \
+ $$PWD/src/hb-ot-font.cc \
$$PWD/src/hb-ot-layout.cc \
$$PWD/src/hb-ot-map.cc \
$$PWD/src/hb-ot-shape.cc \
@@ -106,6 +108,7 @@ HEADERS += \
HEADERS += \
$$PWD/src/hb-ot.h \
+ $$PWD/src/hb-ot-font.h \
$$PWD/src/hb-ot-layout.h \
$$PWD/src/hb-ot-shape.h \
$$PWD/src/hb-ot-tag.h
diff --git a/src/3rdparty/harfbuzz-ng/include/harfbuzz/hb-ot-font.h b/src/3rdparty/harfbuzz-ng/include/harfbuzz/hb-ot-font.h
new file mode 100644
index 0000000000..146441b33b
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/include/harfbuzz/hb-ot-font.h
@@ -0,0 +1 @@
+#include "../../src/hb-ot-font.h"
diff --git a/src/3rdparty/harfbuzz-ng/src/config.h b/src/3rdparty/harfbuzz-ng/src/config.h
deleted file mode 100644
index 9abb5df7f1..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/config.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef HB_CONFIG_H
-#define HB_CONFIG_H
-
-#define HAVE_OT
-#define HAVE_ATEXIT
-
-#define HB_NO_UNICODE_FUNCS
-
-#define HB_DISABLE_DEPRECATED
-
-// because strdup() is not part of strict Posix, declare it here
-extern "C" char *strdup(const char *src);
-
-#endif /* HB_CONFIG_H */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-atomic-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-atomic-private.hh
index b5d64853ea..60cbcf91be 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-atomic-private.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-atomic-private.hh
@@ -47,18 +47,22 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
-#if defined(__MINGW32__) && !defined(MemoryBarrier)
+/* MinGW has a convoluted history of supporting MemoryBarrier
+ * properly. As such, define a function to wrap the whole
+ * thing. */
static inline void _HBMemoryBarrier (void) {
+#if !defined(MemoryBarrier)
long dummy = 0;
InterlockedExchange (&dummy, 1);
-}
-# define MemoryBarrier _HBMemoryBarrier
+#else
+ MemoryBarrier ();
#endif
+}
typedef LONG hb_atomic_int_t;
#define hb_atomic_int_add(AI, V) InterlockedExchangeAdd (&(AI), (V))
-#define hb_atomic_ptr_get(P) (MemoryBarrier (), (void *) *(P))
+#define hb_atomic_ptr_get(P) (_HBMemoryBarrier (), (void *) *(P))
#define hb_atomic_ptr_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O))
@@ -78,7 +82,7 @@ typedef int32_t hb_atomic_int_t;
#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100)
#define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P))
#else
-#if __ppc64__ || __x86_64__ || __arm64__
+#if __ppc64__ || __x86_64__ || __aarch64__
#define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P))
#else
#define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P))
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-blob.cc b/src/3rdparty/harfbuzz-ng/src/hb-blob.cc
index d6acca0fca..b82b4b2a3a 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-blob.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-blob.cc
@@ -25,7 +25,9 @@
*/
/* http://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html */
+#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 199309L
+#endif
#include "hb-private.hh"
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-blob.h b/src/3rdparty/harfbuzz-ng/src/hb-blob.h
index d3d0f41b11..b2419abfd2 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-blob.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-blob.h
@@ -47,14 +47,13 @@ HB_BEGIN_DECLS
* - Use MODE_READONLY otherse, unless you really really
* really know what you are doing,
*
- * - MODE_WRITABLE is appropriate if you relaly made a
+ * - MODE_WRITABLE is appropriate if you really made a
* copy of data solely for the purpose of passing to
* HarfBuzz and doing that just once (no reuse!),
*
* - If the font is mmap()ed, it's ok to use
- * READONLY_MAY_MAKE_WRITABLE, however, there were
- * design problems with that mode, so HarfBuzz do not
- * really use it anymore. If not sure, use MODE_READONLY.
+ * READONLY_MAY_MAKE_WRITABLE, however, using that mode
+ * correctly is very tricky. Use MODE_READONLY instead.
*/
typedef enum {
HB_MEMORY_MODE_DUPLICATE,
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-buffer-private.hh
index 3a2b9ab481..5eccd3c31f 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer-private.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-private.hh
@@ -52,6 +52,7 @@ struct hb_buffer_t {
hb_unicode_funcs_t *unicode; /* Unicode functions */
hb_segment_properties_t props; /* Script, language, direction */
hb_buffer_flags_t flags; /* BOT / EOT / etc. */
+ hb_codepoint_t replacement; /* U+FFFD or something else. */
/* Buffer contents */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc
index 263bc81dc4..406d69db75 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc
@@ -63,7 +63,7 @@ hb_buffer_serialize_format_t
hb_buffer_serialize_format_from_string (const char *str, int len)
{
/* Upper-case it. */
- return (hb_buffer_serialize_format_t) (hb_tag_from_string (str, len) & ~0x20202020);
+ return (hb_buffer_serialize_format_t) (hb_tag_from_string (str, len) & ~0x20202020u);
}
/**
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
index d6c6fcb8e6..2377ba40da 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
@@ -178,6 +178,7 @@ hb_buffer_t::reset (void)
hb_unicode_funcs_destroy (unicode);
unicode = hb_unicode_funcs_get_default ();
+ replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
clear ();
}
@@ -500,6 +501,10 @@ void
hb_buffer_t::merge_clusters (unsigned int start,
unsigned int end)
{
+#ifdef HB_NO_MERGE_CLUSTERS
+ return;
+#endif
+
if (unlikely (end - start < 2))
return;
@@ -528,6 +533,10 @@ void
hb_buffer_t::merge_out_clusters (unsigned int start,
unsigned int end)
{
+#ifdef HB_NO_MERGE_CLUSTERS
+ return;
+#endif
+
if (unlikely (end - start < 2))
return;
@@ -695,6 +704,7 @@ hb_buffer_get_empty (void)
const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
HB_SEGMENT_PROPERTIES_DEFAULT,
HB_BUFFER_FLAG_DEFAULT,
+ HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
HB_BUFFER_CONTENT_TYPE_INVALID,
true, /* in_error */
@@ -1040,6 +1050,42 @@ hb_buffer_get_flags (hb_buffer_t *buffer)
/**
+ * hb_buffer_set_replacement_codepoint:
+ * @buffer: a buffer.
+ * @replacement:
+ *
+ *
+ *
+ * Since: 1.0
+ **/
+void
+hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer,
+ hb_codepoint_t replacement)
+{
+ if (unlikely (hb_object_is_inert (buffer)))
+ return;
+
+ buffer->replacement = replacement;
+}
+
+/**
+ * hb_buffer_get_replacement_codepoint:
+ * @buffer: a buffer.
+ *
+ *
+ *
+ * Return value:
+ *
+ * Since: 1.0
+ **/
+hb_codepoint_t
+hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer)
+{
+ return buffer->replacement;
+}
+
+
+/**
* hb_buffer_reset:
* @buffer: a buffer.
*
@@ -1282,7 +1328,7 @@ hb_buffer_guess_segment_properties (hb_buffer_t *buffer)
buffer->guess_segment_properties ();
}
-template <typename T>
+template <bool validate, typename T>
static inline void
hb_buffer_add_utf (hb_buffer_t *buffer,
const T *text,
@@ -1290,6 +1336,9 @@ hb_buffer_add_utf (hb_buffer_t *buffer,
unsigned int item_offset,
int item_length)
{
+ typedef hb_utf_t<T, true> utf_t;
+ const hb_codepoint_t replacement = buffer->replacement;
+
assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE ||
(!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
@@ -1297,7 +1346,7 @@ hb_buffer_add_utf (hb_buffer_t *buffer,
return;
if (text_length == -1)
- text_length = hb_utf_strlen (text);
+ text_length = utf_t::strlen (text);
if (item_length == -1)
item_length = text_length - item_offset;
@@ -1320,7 +1369,7 @@ hb_buffer_add_utf (hb_buffer_t *buffer,
while (start < prev && buffer->context_len[0] < buffer->CONTEXT_LENGTH)
{
hb_codepoint_t u;
- prev = hb_utf_prev (prev, start, &u);
+ prev = utf_t::prev (prev, start, &u, replacement);
buffer->context[0][buffer->context_len[0]++] = u;
}
}
@@ -1331,7 +1380,7 @@ hb_buffer_add_utf (hb_buffer_t *buffer,
{
hb_codepoint_t u;
const T *old_next = next;
- next = hb_utf_next (next, end, &u);
+ next = utf_t::next (next, end, &u, replacement);
buffer->add (u, old_next - (const T *) text);
}
@@ -1341,7 +1390,7 @@ hb_buffer_add_utf (hb_buffer_t *buffer,
while (next < end && buffer->context_len[1] < buffer->CONTEXT_LENGTH)
{
hb_codepoint_t u;
- next = hb_utf_next (next, end, &u);
+ next = utf_t::next (next, end, &u, replacement);
buffer->context[1][buffer->context_len[1]++] = u;
}
@@ -1367,7 +1416,7 @@ hb_buffer_add_utf8 (hb_buffer_t *buffer,
unsigned int item_offset,
int item_length)
{
- hb_buffer_add_utf (buffer, (const uint8_t *) text, text_length, item_offset, item_length);
+ hb_buffer_add_utf<true> (buffer, (const uint8_t *) text, text_length, item_offset, item_length);
}
/**
@@ -1389,7 +1438,7 @@ hb_buffer_add_utf16 (hb_buffer_t *buffer,
unsigned int item_offset,
int item_length)
{
- hb_buffer_add_utf (buffer, text, text_length, item_offset, item_length);
+ hb_buffer_add_utf<true> (buffer, text, text_length, item_offset, item_length);
}
/**
@@ -1411,7 +1460,29 @@ hb_buffer_add_utf32 (hb_buffer_t *buffer,
unsigned int item_offset,
int item_length)
{
- hb_buffer_add_utf (buffer, text, text_length, item_offset, item_length);
+ hb_buffer_add_utf<true> (buffer, text, text_length, item_offset, item_length);
+}
+
+/**
+ * hb_buffer_add_codepoints:
+ * @buffer: a buffer.
+ * @text: (array length=text_length):
+ * @text_length:
+ * @item_offset:
+ * @item_length:
+ *
+ *
+ *
+ * Since: 1.0
+ **/
+void
+hb_buffer_add_codepoints (hb_buffer_t *buffer,
+ const hb_codepoint_t *text,
+ int text_length,
+ unsigned int item_offset,
+ int item_length)
+{
+ hb_buffer_add_utf<false> (buffer, text, text_length, item_offset, item_length);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.h b/src/3rdparty/harfbuzz-ng/src/hb-buffer.h
index 3086851b01..7b0c920468 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.h
@@ -186,12 +186,25 @@ hb_buffer_flags_t
hb_buffer_get_flags (hb_buffer_t *buffer);
+
+#define HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT 0xFFFDu
+
+/* Sets codepoint used to replace invalid UTF-8/16/32 entries.
+ * Default is 0xFFFDu. */
+void
+hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer,
+ hb_codepoint_t replacement);
+
+hb_codepoint_t
+hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer);
+
+
/* Resets the buffer. Afterwards it's as if it was just created,
* except that it has a larger buffer allocated perhaps... */
void
hb_buffer_reset (hb_buffer_t *buffer);
-/* Like reset, but does NOT clear unicode_funcs. */
+/* Like reset, but does NOT clear unicode_funcs and replacement_codepoint. */
void
hb_buffer_clear_contents (hb_buffer_t *buffer);
@@ -240,6 +253,14 @@ hb_buffer_add_utf32 (hb_buffer_t *buffer,
unsigned int item_offset,
int item_length);
+/* Like add_utf32 but does NOT check for invalid Unicode codepoints. */
+void
+hb_buffer_add_codepoints (hb_buffer_t *buffer,
+ const hb_codepoint_t *text,
+ int text_length,
+ unsigned int item_offset,
+ int item_length);
+
/* Clears any new items added at the end */
hb_bool_t
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-common.cc b/src/3rdparty/harfbuzz-ng/src/hb-common.cc
index 0fd790bc04..a089e52cd2 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-common.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-common.cc
@@ -234,6 +234,7 @@ struct hb_language_item_t {
static hb_language_item_t *langs;
+#ifdef HAVE_ATEXIT
static inline
void free_langs (void)
{
@@ -244,6 +245,7 @@ void free_langs (void)
langs = next;
}
}
+#endif
static hb_language_item_t *
lang_find_or_insert (const char *key)
@@ -297,9 +299,11 @@ hb_language_from_string (const char *str, int len)
if (len >= 0)
{
+ /* NUL-terminate it. */
len = MIN (len, (int) sizeof (strbuf) - 1);
- str = (char *) memcpy (strbuf, str, len);
+ memcpy (strbuf, str, len);
strbuf[len] = '\0';
+ str = strbuf;
}
hb_language_item_t *item = lang_find_or_insert (str);
@@ -367,7 +371,7 @@ hb_script_from_iso15924_tag (hb_tag_t tag)
return HB_SCRIPT_INVALID;
/* Be lenient, adjust case (one capital letter followed by three small letters) */
- tag = (tag & 0xDFDFDFDF) | 0x00202020;
+ tag = (tag & 0xDFDFDFDFu) | 0x00202020u;
switch (tag) {
@@ -387,7 +391,7 @@ hb_script_from_iso15924_tag (hb_tag_t tag)
}
/* If it looks right, just use the tag as a script */
- if (((uint32_t) tag & 0xE0E0E0E0) == 0x40606060)
+ if (((uint32_t) tag & 0xE0E0E0E0u) == 0x40606060u)
return (hb_script_t) tag;
/* Otherwise, return unknown */
@@ -480,6 +484,14 @@ hb_script_get_horizontal_direction (hb_script_t script)
case HB_SCRIPT_MEROITIC_CURSIVE:
case HB_SCRIPT_MEROITIC_HIEROGLYPHS:
+ /* Unicode-7.0 additions */
+ case HB_SCRIPT_MANICHAEAN:
+ case HB_SCRIPT_MENDE_KIKAKUI:
+ case HB_SCRIPT_NABATAEAN:
+ case HB_SCRIPT_OLD_NORTH_ARABIAN:
+ case HB_SCRIPT_PALMYRENE:
+ case HB_SCRIPT_PSALTER_PAHLAVI:
+
return HB_DIRECTION_RTL;
}
@@ -557,7 +569,7 @@ hb_version_string (void)
}
/**
- * hb_version_check:
+ * hb_version_atleast:
* @major:
* @minor:
* @micro:
@@ -569,9 +581,9 @@ hb_version_string (void)
* Since: 1.0
**/
hb_bool_t
-hb_version_check (unsigned int major,
- unsigned int minor,
- unsigned int micro)
+hb_version_atleast (unsigned int major,
+ unsigned int minor,
+ unsigned int micro)
{
- return HB_VERSION_CHECK (major, minor, micro);
+ return HB_VERSION_ATLEAST (major, minor, micro);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-common.h b/src/3rdparty/harfbuzz-ng/src/hb-common.h
index c8bfd8825a..b24cbb33ba 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-common.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-common.h
@@ -270,17 +270,6 @@ typedef enum
/*6.1*/ HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'),
/*6.1*/ HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'),
- /* No script set. */
- /*---*/ HB_SCRIPT_INVALID = HB_TAG_NONE,
-
- /* Dummy value to ensure any hb_tag_t value can be passed/stored as hb_script_t
- * without risking undefined behavior. */
- /*---*/ _HB_SCRIPT_MAX_VALUE = HB_TAG_MAX
-
-} hb_script_t;
-
-/* These are moved out of hb_script_t because glib-mkenums chokes otherwise. */
-#if 0
/*7.0*/ HB_SCRIPT_BASSA_VAH = HB_TAG ('B','a','s','s'),
/*7.0*/ HB_SCRIPT_CAUCASIAN_ALBANIAN = HB_TAG ('A','g','h','b'),
/*7.0*/ HB_SCRIPT_DUPLOYAN = HB_TAG ('D','u','p','l'),
@@ -292,19 +281,27 @@ typedef enum
/*7.0*/ HB_SCRIPT_MAHAJANI = HB_TAG ('M','a','h','j'),
/*7.0*/ HB_SCRIPT_MANICHAEAN = HB_TAG ('M','a','n','i'),
/*7.0*/ HB_SCRIPT_MENDE_KIKAKUI = HB_TAG ('M','e','n','d'),
- /*7.0*/ HB_SCRIPT_MODI = ???
+ /*7.0*/ HB_SCRIPT_MODI = HB_TAG ('M','o','d','i'),
/*7.0*/ HB_SCRIPT_MRO = HB_TAG ('M','r','o','o'),
/*7.0*/ HB_SCRIPT_NABATAEAN = HB_TAG ('N','b','a','t'),
/*7.0*/ HB_SCRIPT_OLD_NORTH_ARABIAN = HB_TAG ('N','a','r','b'),
/*7.0*/ HB_SCRIPT_OLD_PERMIC = HB_TAG ('P','e','r','m'),
/*7.0*/ HB_SCRIPT_PAHAWH_HMONG = HB_TAG ('H','m','n','g'),
/*7.0*/ HB_SCRIPT_PALMYRENE = HB_TAG ('P','a','l','m'),
- /*7.0*/ HB_SCRIPT_PAU_CIN_HAU = ???
+ /*7.0*/ HB_SCRIPT_PAU_CIN_HAU = HB_TAG ('P','a','u','c'),
/*7.0*/ HB_SCRIPT_PSALTER_PAHLAVI = HB_TAG ('P','h','l','p'),
- /*7.0*/ HB_SCRIPT_SIDDHAM = ???
+ /*7.0*/ HB_SCRIPT_SIDDHAM = HB_TAG ('S','i','d','d'),
/*7.0*/ HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'),
/*7.0*/ HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'),
-#endif
+
+ /* No script set. */
+ /*---*/ HB_SCRIPT_INVALID = HB_TAG_NONE,
+
+ /* Dummy value to ensure any hb_tag_t value can be passed/stored as hb_script_t
+ * without risking undefined behavior. */
+ /*---*/ _HB_SCRIPT_MAX_VALUE = HB_TAG_MAX
+
+} hb_script_t;
/* Script functions */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
index 2507cd1d9f..e2cd2777ed 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
@@ -31,18 +31,12 @@
#include "hb-coretext.h"
-#include "hb-face-private.hh"
-
#ifndef HB_DEBUG_CORETEXT
#define HB_DEBUG_CORETEXT (HB_DEBUG+0)
#endif
-HB_SHAPER_DATA_ENSURE_DECLARE(coretext, face)
-HB_SHAPER_DATA_ENSURE_DECLARE(coretext, font)
-
-
typedef bool (*qt_get_font_table_func_t) (void *user_data, unsigned int tag, unsigned char *buffer, unsigned int *length);
struct FontEngineFaceData {
@@ -56,6 +50,42 @@ struct CoreTextFontEngineData {
};
+static void
+release_table_data (void *user_data)
+{
+ CFDataRef cf_data = reinterpret_cast<CFDataRef> (user_data);
+ CFRelease(cf_data);
+}
+
+static hb_blob_t *
+reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
+{
+ CGFontRef cg_font = reinterpret_cast<CGFontRef> (user_data);
+ CFDataRef cf_data = CGFontCopyTableForTag (cg_font, tag);
+ if (unlikely (!cf_data))
+ return NULL;
+
+ const char *data = reinterpret_cast<const char*> (CFDataGetBytePtr (cf_data));
+ const size_t length = CFDataGetLength (cf_data);
+ if (!data || !length)
+ return NULL;
+
+ return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY,
+ reinterpret_cast<void *> (const_cast<__CFData *> (cf_data)),
+ release_table_data);
+}
+
+hb_face_t *
+hb_coretext_face_create (CGFontRef cg_font)
+{
+ return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), (hb_destroy_func_t) CGFontRelease);
+}
+
+
+HB_SHAPER_DATA_ENSURE_DECLARE(coretext, face)
+HB_SHAPER_DATA_ENSURE_DECLARE(coretext, font)
+
+
/*
* shaper face data
*/
@@ -76,31 +106,33 @@ release_data (void *info, const void *data, size_t size)
hb_coretext_shaper_face_data_t *
_hb_coretext_shaper_face_data_create (hb_face_t *face)
{
- hb_blob_t *mort_blob = face->reference_table (HB_CORETEXT_TAG_MORT);
- /* Umm, we just reference the table to check whether it exists.
- * Maybe add better API for this? */
- if (!hb_blob_get_length (mort_blob))
- {
- hb_blob_destroy (mort_blob);
- mort_blob = face->reference_table (HB_CORETEXT_TAG_MORX);
- if (!hb_blob_get_length (mort_blob))
- {
- hb_blob_destroy (mort_blob);
- return NULL;
- }
- }
- hb_blob_destroy (mort_blob);
-
hb_coretext_shaper_face_data_t *data = (hb_coretext_shaper_face_data_t *) calloc (1, sizeof (hb_coretext_shaper_face_data_t));
if (unlikely (!data))
return NULL;
-
+#if 0
+ if (face->destroy == (hb_destroy_func_t) CGFontRelease)
+ {
+ data->cg_font = CGFontRetain ((CGFontRef) face->user_data);
+ }
+ else
+ {
+ hb_blob_t *blob = hb_face_reference_blob (face);
+ unsigned int blob_length;
+ const char *blob_data = hb_blob_get_data (blob, &blob_length);
+ if (unlikely (!blob_length))
+ DEBUG_MSG (CORETEXT, face, "Face has empty blob");
+
+ CGDataProviderRef provider = CGDataProviderCreateWithData (blob, blob_data, blob_length, &release_data);
+ data->cg_font = CGFontCreateWithDataProvider (provider);
+ CGDataProviderRelease (provider);
+ }
+#else
FontEngineFaceData *fontEngineFaceData = (FontEngineFaceData *) face->user_data;
CoreTextFontEngineData *coreTextFontEngineData = (CoreTextFontEngineData *) fontEngineFaceData->user_data;
data->cg_font = coreTextFontEngineData->cgFont;
if (likely (data->cg_font))
CFRetain (data->cg_font);
-
+#endif
if (unlikely (!data->cg_font)) {
DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed");
free (data);
@@ -144,13 +176,17 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
return NULL;
hb_face_t *face = font->face;
+#if 0
+ hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
+ data->ct_font = CTFontCreateWithGraphicsFont (face_data->cg_font, font->y_scale, NULL, NULL);
+#else
FontEngineFaceData *fontEngineFaceData = (FontEngineFaceData *) face->user_data;
CoreTextFontEngineData *coreTextFontEngineData = (CoreTextFontEngineData *) fontEngineFaceData->user_data;
data->ct_font = coreTextFontEngineData->ctFont;
if (likely (data->ct_font))
CFRetain (data->ct_font);
-
+#endif
if (unlikely (!data->ct_font)) {
DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed");
free (data);
@@ -468,7 +504,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
event->start = false;
event->feature = feature;
}
- feature_events.sort ();
+ feature_events.qsort ();
/* Add a strategic final event. */
{
active_feature_t feature;
@@ -498,14 +534,12 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
if (unlikely (!range))
goto fail_features;
- unsigned int offset = feature_records.len;
-
if (active_features.len)
{
CFMutableArrayRef features_array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
/* TODO sort and resolve conflicting features? */
- /* active_features.sort (); */
+ /* active_features.qsort (); */
for (unsigned int j = 0; j < active_features.len; j++)
{
CFStringRef keys[2] = {
@@ -603,13 +637,13 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
for (unsigned int i = 0; i < buffer->len; i++) {
hb_codepoint_t c = buffer->info[i].codepoint;
buffer->info[i].utf16_index() = chars_len;
- if (likely (c < 0x10000))
+ if (likely (c <= 0xFFFFu))
pchars[chars_len++] = c;
- else if (unlikely (c >= 0x110000))
- pchars[chars_len++] = 0xFFFD;
+ else if (unlikely (c > 0x10FFFFu))
+ pchars[chars_len++] = 0xFFFDu;
else {
- pchars[chars_len++] = 0xD800 + ((c - 0x10000) >> 10);
- pchars[chars_len++] = 0xDC00 + ((c - 0x10000) & ((1 << 10) - 1));
+ pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
+ pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1));
}
}
@@ -635,7 +669,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
hb_codepoint_t c = buffer->info[i].codepoint;
unsigned int cluster = buffer->info[i].cluster;
log_clusters[chars_len++] = cluster;
- if (c >= 0x10000 && c < 0x110000)
+ if (hb_in_range (c, 0x10000u, 0x10FFFFu))
log_clusters[chars_len++] = cluster; /* Surrogates. */
}
@@ -705,10 +739,10 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
for (CFIndex j = range.location; j < range.location + range.length; j++)
{
UniChar ch = CFStringGetCharacterAtIndex (string_ref, j);
- if (hb_in_range<UniChar> (ch, 0xDC00, 0xDFFF) && range.location < j)
+ if (hb_in_range<UniChar> (ch, 0xDC00u, 0xDFFFu) && range.location < j)
{
ch = CFStringGetCharacterAtIndex (string_ref, j - 1);
- if (hb_in_range<UniChar> (ch, 0xD800, 0xDBFF))
+ if (hb_in_range<UniChar> (ch, 0xD800u, 0xDBFFu))
/* This is the second of a surrogate pair. Don't need .notdef
* for this one. */
continue;
@@ -866,3 +900,97 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
return true;
}
+
+
+/*
+ * AAT shaper
+ */
+
+HB_SHAPER_DATA_ENSURE_DECLARE(coretext_aat, face)
+HB_SHAPER_DATA_ENSURE_DECLARE(coretext_aat, font)
+
+
+/*
+ * shaper face data
+ */
+
+struct hb_coretext_aat_shaper_face_data_t {};
+
+hb_coretext_aat_shaper_face_data_t *
+_hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
+{
+ hb_blob_t *mort_blob = face->reference_table (HB_CORETEXT_TAG_MORT);
+ /* Umm, we just reference the table to check whether it exists.
+ * Maybe add better API for this? */
+ if (!hb_blob_get_length (mort_blob))
+ {
+ hb_blob_destroy (mort_blob);
+ mort_blob = face->reference_table (HB_CORETEXT_TAG_MORX);
+ if (!hb_blob_get_length (mort_blob))
+ {
+ hb_blob_destroy (mort_blob);
+ return NULL;
+ }
+ }
+ hb_blob_destroy (mort_blob);
+
+ return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : NULL;
+}
+
+void
+_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_shaper_face_data_t *data HB_UNUSED)
+{
+}
+
+
+/*
+ * shaper font data
+ */
+
+struct hb_coretext_aat_shaper_font_data_t {};
+
+hb_coretext_aat_shaper_font_data_t *
+_hb_coretext_aat_shaper_font_data_create (hb_font_t *font)
+{
+ return hb_coretext_shaper_font_data_ensure (font) ? (hb_coretext_aat_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : NULL;
+}
+
+void
+_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_shaper_font_data_t *data HB_UNUSED)
+{
+}
+
+
+/*
+ * shaper shape_plan data
+ */
+
+struct hb_coretext_aat_shaper_shape_plan_data_t {};
+
+hb_coretext_aat_shaper_shape_plan_data_t *
+_hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
+ const hb_feature_t *user_features HB_UNUSED,
+ unsigned int num_user_features HB_UNUSED)
+{
+ return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+}
+
+void
+_hb_coretext_aat_shaper_shape_plan_data_destroy (hb_coretext_aat_shaper_shape_plan_data_t *data HB_UNUSED)
+{
+}
+
+
+/*
+ * shaper
+ */
+
+hb_bool_t
+_hb_coretext_aat_shape (hb_shape_plan_t *shape_plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features)
+{
+ return _hb_coretext_shape (shape_plan, font, buffer, features, num_features);
+}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-coretext.h b/src/3rdparty/harfbuzz-ng/src/hb-coretext.h
index aa4bf69a52..25267bc978 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-coretext.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-coretext.h
@@ -30,7 +30,7 @@
#include "hb.h"
#include <TargetConditionals.h>
-#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
+#if TARGET_OS_IPHONE
# include <CoreText/CoreText.h>
# include <CoreGraphics/CoreGraphics.h>
#else
@@ -44,6 +44,10 @@ HB_BEGIN_DECLS
#define HB_CORETEXT_TAG_MORX HB_TAG('m','o','r','x')
+hb_face_t *
+hb_coretext_face_create (CGFontRef cg_font);
+
+
CGFontRef
hb_coretext_face_get_cg_font (hb_face_t *face);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-file-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-file-private.hh
index 250504ae20..57db59db84 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-open-file-private.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-open-file-private.hh
@@ -110,9 +110,9 @@ typedef struct OffsetTable
protected:
Tag sfnt_version; /* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
USHORT numTables; /* Number of tables. */
- USHORT searchRange; /* (Maximum power of 2 <= numTables) x 16 */
- USHORT entrySelector; /* Log2(maximum power of 2 <= numTables). */
- USHORT rangeShift; /* NumTables x 16-searchRange. */
+ USHORT searchRangeZ; /* (Maximum power of 2 <= numTables) x 16 */
+ USHORT entrySelectorZ; /* Log2(maximum power of 2 <= numTables). */
+ USHORT rangeShiftZ; /* NumTables x 16-searchRange. */
TableRecord tables[VAR]; /* TableRecord entries. numTables items */
public:
DEFINE_SIZE_ARRAY (12, tables);
@@ -138,8 +138,8 @@ struct TTCHeaderVersion1
protected:
Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */
FixedVersion version; /* Version of the TTC Header (1.0),
- * 0x00010000 */
- LongOffsetLongArrayOf<OffsetTable>
+ * 0x00010000u */
+ ArrayOf<OffsetTo<OffsetTable, ULONG>, ULONG>
table; /* Array of offsets to the OffsetTable for each font
* from the beginning of the file */
public:
@@ -184,7 +184,7 @@ struct TTCHeader
struct {
Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */
FixedVersion version; /* Version of the TTC Header (1.0 or 2.0),
- * 0x00010000 or 0x00020000 */
+ * 0x00010000u or 0x00020000u */
} header;
TTCHeaderVersion1 version1;
} u;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh
index 558103a8ec..046df97659 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh
@@ -42,36 +42,36 @@ namespace OT {
/* Cast to struct T, reference to reference */
template<typename Type, typename TObject>
-inline const Type& CastR(const TObject &X)
+static inline const Type& CastR(const TObject &X)
{ return reinterpret_cast<const Type&> (X); }
template<typename Type, typename TObject>
-inline Type& CastR(TObject &X)
+static inline Type& CastR(TObject &X)
{ return reinterpret_cast<Type&> (X); }
/* Cast to struct T, pointer to pointer */
template<typename Type, typename TObject>
-inline const Type* CastP(const TObject *X)
+static inline const Type* CastP(const TObject *X)
{ return reinterpret_cast<const Type*> (X); }
template<typename Type, typename TObject>
-inline Type* CastP(TObject *X)
+static inline Type* CastP(TObject *X)
{ return reinterpret_cast<Type*> (X); }
/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
* location pointed to by P plus Ofs bytes. */
template<typename Type>
-inline const Type& StructAtOffset(const void *P, unsigned int offset)
+static inline const Type& StructAtOffset(const void *P, unsigned int offset)
{ return * reinterpret_cast<const Type*> ((const char *) P + offset); }
template<typename Type>
-inline Type& StructAtOffset(void *P, unsigned int offset)
+static inline Type& StructAtOffset(void *P, unsigned int offset)
{ return * reinterpret_cast<Type*> ((char *) P + offset); }
/* StructAfter<T>(X) returns the struct T& that is placed after X.
* Works with X of variable size also. X must implement get_size() */
template<typename Type, typename TObject>
-inline const Type& StructAfter(const TObject &X)
+static inline const Type& StructAfter(const TObject &X)
{ return StructAtOffset<Type>(&X, X.get_size()); }
template<typename Type, typename TObject>
-inline Type& StructAfter(TObject &X)
+static inline Type& StructAfter(TObject &X)
{ return StructAtOffset<Type>(&X, X.get_size()); }
@@ -132,7 +132,7 @@ inline Type& StructAfter(TObject &X)
/* Global nul-content Null pool. Enlarge as necessary. */
/* TODO This really should be a extern HB_INTERNAL and defined somewhere... */
-static const void *_NullPool[64 / sizeof (void *)];
+static const void *_NullPool[(256+8) / sizeof (void *)];
/* Generic nul-content Null objects. */
template <typename Type>
@@ -145,7 +145,7 @@ static inline const Type& Null (void) {
#define DEFINE_NULL_DATA(Type, data) \
static const char _Null##Type[sizeof (Type) + 1] = data; /* +1 is for nul-termination in data */ \
template <> \
-inline const Type& Null<Type> (void) { \
+/*static*/ inline const Type& Null<Type> (void) { \
return *CastP<Type> (_Null##Type); \
} /* The following line really exists such that we end in a place needing semicolon */ \
ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type))
@@ -266,6 +266,15 @@ struct hb_sanitize_context_t
return TRACE_RETURN (this->writable);
}
+ template <typename Type, typename ValueType>
+ inline bool try_set (Type *obj, const ValueType &v) {
+ if (this->may_edit (obj, obj->static_size)) {
+ obj->set (v);
+ return true;
+ }
+ return false;
+ }
+
mutable unsigned int debug_depth;
const char *start, *end;
bool writable;
@@ -572,6 +581,7 @@ struct IntType
DEFINE_SIZE_STATIC (Size);
};
+typedef uint8_t BYTE; /* 8-bit unsigned integer. */
typedef IntType<uint16_t, 2> USHORT; /* 16-bit unsigned integer. */
typedef IntType<int16_t, 2> SHORT; /* 16-bit signed integer. */
typedef IntType<uint32_t, 4> ULONG; /* 32-bit unsigned integer. */
@@ -616,24 +626,17 @@ typedef USHORT GlyphID;
/* Script/language-system/feature index */
struct Index : USHORT {
- static const unsigned int NOT_FOUND_INDEX = 0xFFFF;
+ static const unsigned int NOT_FOUND_INDEX = 0xFFFFu;
};
DEFINE_NULL_DATA (Index, "\xff\xff");
-/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */
-struct Offset : USHORT
+/* Offset, Null offset = 0 */
+template <typename Type=USHORT>
+struct Offset : Type
{
inline bool is_null (void) const { return 0 == *this; }
public:
- DEFINE_SIZE_STATIC (2);
-};
-
-/* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */
-struct LongOffset : ULONG
-{
- inline bool is_null (void) const { return 0 == *this; }
- public:
- DEFINE_SIZE_STATIC (4);
+ DEFINE_SIZE_STATIC (sizeof(Type));
};
@@ -682,12 +685,12 @@ struct FixedVersion
/*
- * Template subclasses of Offset and LongOffset that do the dereferencing.
+ * Template subclasses of Offset that do the dereferencing.
* Use: (base+offset)
*/
-template <typename OffsetType, typename Type>
-struct GenericOffsetTo : OffsetType
+template <typename Type, typename OffsetType=USHORT>
+struct OffsetTo : Offset<OffsetType>
{
inline const Type& operator () (const void *base) const
{
@@ -721,40 +724,25 @@ struct GenericOffsetTo : OffsetType
return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c));
}
- inline bool try_set (hb_sanitize_context_t *c, const OffsetType &v) {
- if (c->may_edit (this, this->static_size)) {
- this->set (v);
- return true;
- }
- return false;
- }
/* Set the offset to Null */
inline bool neuter (hb_sanitize_context_t *c) {
- if (c->may_edit (this, this->static_size)) {
- this->set (0); /* 0 is Null offset */
- return true;
- }
- return false;
+ return c->try_set (this, 0);
}
+ DEFINE_SIZE_STATIC (sizeof(OffsetType));
};
template <typename Base, typename OffsetType, typename Type>
-inline const Type& operator + (const Base &base, const GenericOffsetTo<OffsetType, Type> &offset) { return offset (base); }
+static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); }
template <typename Base, typename OffsetType, typename Type>
-inline Type& operator + (Base &base, GenericOffsetTo<OffsetType, Type> &offset) { return offset (base); }
-
-template <typename Type>
-struct OffsetTo : GenericOffsetTo<Offset, Type> {};
-
-template <typename Type>
-struct LongOffsetTo : GenericOffsetTo<LongOffset, Type> {};
+static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset) { return offset (base); }
/*
* Array Types
*/
-template <typename LenType, typename Type>
-struct GenericArrayOf
+/* An array with a number of elements. */
+template <typename Type, typename LenType=USHORT>
+struct ArrayOf
{
const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
{
@@ -837,6 +825,16 @@ struct GenericArrayOf
return TRACE_RETURN (true);
}
+ template <typename SearchType>
+ inline int lsearch (const SearchType &x) const
+ {
+ unsigned int count = len;
+ for (unsigned int i = 0; i < count; i++)
+ if (!this->array[i].cmp (x))
+ return i;
+ return -1;
+ }
+
private:
inline bool sanitize_shallow (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
@@ -850,26 +848,10 @@ struct GenericArrayOf
DEFINE_SIZE_ARRAY (sizeof (LenType), array);
};
-/* An array with a USHORT number of elements. */
-template <typename Type>
-struct ArrayOf : GenericArrayOf<USHORT, Type> {};
-
-/* An array with a ULONG number of elements. */
-template <typename Type>
-struct LongArrayOf : GenericArrayOf<ULONG, Type> {};
-
/* Array of Offset's */
template <typename Type>
struct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {};
-/* Array of LongOffset's */
-template <typename Type>
-struct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {};
-
-/* LongArray of LongOffset's */
-template <typename Type>
-struct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {};
-
/* Array of offsets relative to the beginning of the array itself. */
template <typename Type>
struct OffsetListOf : OffsetArrayOf<Type>
@@ -892,9 +874,8 @@ struct OffsetListOf : OffsetArrayOf<Type>
};
-/* An array with a USHORT number of elements,
- * starting at second element. */
-template <typename Type>
+/* An array starting at second element. */
+template <typename Type, typename LenType=USHORT>
struct HeadlessArrayOf
{
inline const Type& operator [] (unsigned int i) const
@@ -941,19 +922,19 @@ struct HeadlessArrayOf
return TRACE_RETURN (true);
}
- USHORT len;
+ LenType len;
Type array[VAR];
public:
- DEFINE_SIZE_ARRAY (sizeof (USHORT), array);
+ DEFINE_SIZE_ARRAY (sizeof (LenType), array);
};
/* An array with sorted elements. Supports binary searching. */
-template <typename Type>
-struct SortedArrayOf : ArrayOf<Type> {
-
+template <typename Type, typename LenType=USHORT>
+struct SortedArrayOf : ArrayOf<Type, LenType>
+{
template <typename SearchType>
- inline int search (const SearchType &x) const
+ inline int bsearch (const SearchType &x) const
{
/* Hand-coded bsearch here since this is in the hot inner loop. */
int min = 0, max = (int) this->len - 1;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh
new file mode 100644
index 0000000000..d53141157d
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh
@@ -0,0 +1,517 @@
+/*
+ * Copyright © 2014 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_CMAP_TABLE_HH
+#define HB_OT_CMAP_TABLE_HH
+
+#include "hb-open-type-private.hh"
+
+
+namespace OT {
+
+
+/*
+ * cmap -- Character To Glyph Index Mapping Table
+ */
+
+#define HB_OT_TAG_cmap HB_TAG('c','m','a','p')
+
+
+struct CmapSubtableFormat0
+{
+ inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+ {
+ hb_codepoint_t gid = codepoint < 256 ? glyphIdArray[codepoint] : 0;
+ if (!gid)
+ return false;
+ *glyph = gid;
+ return true;
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) {
+ TRACE_SANITIZE (this);
+ return TRACE_RETURN (c->check_struct (this));
+ }
+
+ protected:
+ USHORT format; /* Format number is set to 0. */
+ USHORT lengthZ; /* Byte length of this subtable. */
+ USHORT languageZ; /* Ignore. */
+ BYTE glyphIdArray[256];/* An array that maps character
+ * code to glyph index values. */
+ public:
+ DEFINE_SIZE_STATIC (6 + 256);
+};
+
+struct CmapSubtableFormat4
+{
+ inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+ {
+ unsigned int segCount;
+ const USHORT *endCount;
+ const USHORT *startCount;
+ const USHORT *idDelta;
+ const USHORT *idRangeOffset;
+ const USHORT *glyphIdArray;
+ unsigned int glyphIdArrayLength;
+
+ segCount = this->segCountX2 / 2;
+ endCount = this->values;
+ startCount = endCount + segCount + 1;
+ idDelta = startCount + segCount;
+ idRangeOffset = idDelta + segCount;
+ glyphIdArray = idRangeOffset + segCount;
+ glyphIdArrayLength = (this->length - 16 - 8 * segCount) / 2;
+
+ /* Custom two-array bsearch. */
+ int min = 0, max = (int) segCount - 1;
+ unsigned int i;
+ while (min <= max)
+ {
+ int mid = (min + max) / 2;
+ if (codepoint < startCount[mid])
+ max = mid - 1;
+ else if (codepoint > endCount[mid])
+ min = mid + 1;
+ else
+ {
+ i = mid;
+ goto found;
+ }
+ }
+ return false;
+
+ found:
+ hb_codepoint_t gid;
+ unsigned int rangeOffset = idRangeOffset[i];
+ if (rangeOffset == 0)
+ gid = codepoint + idDelta[i];
+ else
+ {
+ /* Somebody has been smoking... */
+ unsigned int index = rangeOffset / 2 + (codepoint - startCount[i]) + i - segCount;
+ if (unlikely (index >= glyphIdArrayLength))
+ return false;
+ gid = glyphIdArray[index];
+ if (unlikely (!gid))
+ return false;
+ gid += idDelta[i];
+ }
+
+ *glyph = gid & 0xFFFFu;
+ return true;
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c)
+ {
+ TRACE_SANITIZE (this);
+ if (unlikely (!c->check_struct (this)))
+ return TRACE_RETURN (false);
+
+ if (unlikely (!c->check_range (this, length)))
+ {
+ /* Some broken fonts have too long of a "length" value.
+ * If that is the case, just change the value to truncate
+ * the subtable at the end of the blob. */
+ uint16_t new_length = (uint16_t) MIN ((uintptr_t) 65535,
+ (uintptr_t) (c->end -
+ (char *) this));
+ if (!c->try_set (&length, new_length))
+ return TRACE_RETURN (false);
+ }
+
+ return TRACE_RETURN (16 + 4 * (unsigned int) segCountX2 <= length);
+ }
+
+ protected:
+ USHORT format; /* Format number is set to 4. */
+ USHORT length; /* This is the length in bytes of the
+ * subtable. */
+ USHORT languageZ; /* Ignore. */
+ USHORT segCountX2; /* 2 x segCount. */
+ USHORT searchRangeZ; /* 2 * (2**floor(log2(segCount))) */
+ USHORT entrySelectorZ; /* log2(searchRange/2) */
+ USHORT rangeShiftZ; /* 2 x segCount - searchRange */
+
+ USHORT values[VAR];
+#if 0
+ USHORT endCount[segCount]; /* End characterCode for each segment,
+ * last=0xFFFFu. */
+ USHORT reservedPad; /* Set to 0. */
+ USHORT startCount[segCount]; /* Start character code for each segment. */
+ SHORT idDelta[segCount]; /* Delta for all character codes in segment. */
+ USHORT idRangeOffset[segCount];/* Offsets into glyphIdArray or 0 */
+ USHORT glyphIdArray[VAR]; /* Glyph index array (arbitrary length) */
+#endif
+
+ public:
+ DEFINE_SIZE_ARRAY (14, values);
+};
+
+struct CmapSubtableLongGroup
+{
+ friend struct CmapSubtableFormat12;
+ friend struct CmapSubtableFormat13;
+
+ int cmp (hb_codepoint_t codepoint) const
+ {
+ if (codepoint < startCharCode) return -1;
+ if (codepoint > endCharCode) return +1;
+ return 0;
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) {
+ TRACE_SANITIZE (this);
+ return TRACE_RETURN (c->check_struct (this));
+ }
+
+ private:
+ ULONG startCharCode; /* First character code in this group. */
+ ULONG endCharCode; /* Last character code in this group. */
+ ULONG glyphID; /* Glyph index; interpretation depends on
+ * subtable format. */
+ public:
+ DEFINE_SIZE_STATIC (12);
+};
+
+template <typename UINT>
+struct CmapSubtableTrimmed
+{
+ inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+ {
+ /* Rely on our implicit array bound-checking. */
+ hb_codepoint_t gid = glyphIdArray[codepoint - startCharCode];
+ if (!gid)
+ return false;
+ *glyph = gid;
+ return true;
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) {
+ TRACE_SANITIZE (this);
+ return TRACE_RETURN (c->check_struct (this) && glyphIdArray.sanitize (c));
+ }
+
+ protected:
+ UINT formatReserved; /* Subtable format and (maybe) padding. */
+ UINT lengthZ; /* Byte length of this subtable. */
+ UINT languageZ; /* Ignore. */
+ UINT startCharCode; /* First character code covered. */
+ ArrayOf<GlyphID, UINT>
+ glyphIdArray; /* Array of glyph index values for character
+ * codes in the range. */
+ public:
+ DEFINE_SIZE_ARRAY (5 * sizeof (UINT), glyphIdArray);
+};
+
+struct CmapSubtableFormat6 : CmapSubtableTrimmed<USHORT> {};
+struct CmapSubtableFormat10 : CmapSubtableTrimmed<ULONG > {};
+
+template <typename T>
+struct CmapSubtableLongSegmented
+{
+ inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+ {
+ int i = groups.bsearch (codepoint);
+ if (i == -1)
+ return false;
+ *glyph = T::group_get_glyph (groups[i], codepoint);
+ return true;
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) {
+ TRACE_SANITIZE (this);
+ return TRACE_RETURN (c->check_struct (this) && groups.sanitize (c));
+ }
+
+ protected:
+ USHORT format; /* Subtable format; set to 12. */
+ USHORT reservedZ; /* Reserved; set to 0. */
+ ULONG lengthZ; /* Byte length of this subtable. */
+ ULONG languageZ; /* Ignore. */
+ SortedArrayOf<CmapSubtableLongGroup, ULONG>
+ groups; /* Groupings. */
+ public:
+ DEFINE_SIZE_ARRAY (16, groups);
+};
+
+struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
+{
+ static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
+ hb_codepoint_t u)
+ { return group.glyphID + (u - group.startCharCode); }
+};
+
+struct CmapSubtableFormat13 : CmapSubtableLongSegmented<CmapSubtableFormat13>
+{
+ static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
+ hb_codepoint_t u HB_UNUSED)
+ { return group.glyphID; }
+};
+
+typedef enum
+{
+ GLYPH_VARIANT_NOT_FOUND = 0,
+ GLYPH_VARIANT_FOUND = 1,
+ GLYPH_VARIANT_USE_DEFAULT = 2
+} glyph_variant_t;
+
+struct UnicodeValueRange
+{
+ inline int cmp (const hb_codepoint_t &codepoint) const
+ {
+ if (codepoint < startUnicodeValue) return -1;
+ if (codepoint > startUnicodeValue + additionalCount) return +1;
+ return 0;
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) {
+ TRACE_SANITIZE (this);
+ return TRACE_RETURN (c->check_struct (this));
+ }
+
+ UINT24 startUnicodeValue; /* First value in this range. */
+ BYTE additionalCount; /* Number of additional values in this
+ * range. */
+ public:
+ DEFINE_SIZE_STATIC (4);
+};
+
+typedef SortedArrayOf<UnicodeValueRange, ULONG> DefaultUVS;
+
+struct UVSMapping
+{
+ inline int cmp (const hb_codepoint_t &codepoint) const
+ {
+ return unicodeValue.cmp (codepoint);
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) {
+ TRACE_SANITIZE (this);
+ return TRACE_RETURN (c->check_struct (this));
+ }
+
+ UINT24 unicodeValue; /* Base Unicode value of the UVS */
+ GlyphID glyphID; /* Glyph ID of the UVS */
+ public:
+ DEFINE_SIZE_STATIC (5);
+};
+
+typedef SortedArrayOf<UVSMapping, ULONG> NonDefaultUVS;
+
+struct VariationSelectorRecord
+{
+ inline glyph_variant_t get_glyph (hb_codepoint_t codepoint,
+ hb_codepoint_t *glyph,
+ const void *base) const
+ {
+ int i;
+ const DefaultUVS &defaults = base+defaultUVS;
+ i = defaults.bsearch (codepoint);
+ if (i != -1)
+ return GLYPH_VARIANT_USE_DEFAULT;
+ const NonDefaultUVS &nonDefaults = base+nonDefaultUVS;
+ i = nonDefaults.bsearch (codepoint);
+ if (i != -1)
+ {
+ *glyph = nonDefaults[i].glyphID;
+ return GLYPH_VARIANT_FOUND;
+ }
+ return GLYPH_VARIANT_NOT_FOUND;
+ }
+
+ inline int cmp (const hb_codepoint_t &variation_selector) const
+ {
+ return varSelector.cmp (variation_selector);
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c, void *base) {
+ TRACE_SANITIZE (this);
+ return TRACE_RETURN (c->check_struct (this) &&
+ defaultUVS.sanitize (c, base) &&
+ nonDefaultUVS.sanitize (c, base));
+ }
+
+ UINT24 varSelector; /* Variation selector. */
+ OffsetTo<DefaultUVS, ULONG>
+ defaultUVS; /* Offset to Default UVS Table. May be 0. */
+ OffsetTo<NonDefaultUVS, ULONG>
+ nonDefaultUVS; /* Offset to Non-Default UVS Table. May be 0. */
+ public:
+ DEFINE_SIZE_STATIC (11);
+};
+
+struct CmapSubtableFormat14
+{
+ inline glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
+ hb_codepoint_t variation_selector,
+ hb_codepoint_t *glyph) const
+ {
+ return record[record.bsearch(variation_selector)].get_glyph (codepoint, glyph, this);
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) {
+ TRACE_SANITIZE (this);
+ return TRACE_RETURN (c->check_struct (this) &&
+ record.sanitize (c, this));
+ }
+
+ protected:
+ USHORT format; /* Format number is set to 0. */
+ ULONG lengthZ; /* Byte length of this subtable. */
+ SortedArrayOf<VariationSelectorRecord, ULONG>
+ record; /* Variation selector records; sorted
+ * in increasing order of `varSelector'. */
+ public:
+ DEFINE_SIZE_ARRAY (10, record);
+};
+
+struct CmapSubtable
+{
+ /* Note: We intentionally do NOT implement subtable formats 2 and 8. */
+
+ inline bool get_glyph (hb_codepoint_t codepoint,
+ hb_codepoint_t *glyph) const
+ {
+ switch (u.format) {
+ case 0: return u.format0 .get_glyph(codepoint, glyph);
+ case 4: return u.format4 .get_glyph(codepoint, glyph);
+ case 6: return u.format6 .get_glyph(codepoint, glyph);
+ case 10: return u.format10.get_glyph(codepoint, glyph);
+ case 12: return u.format12.get_glyph(codepoint, glyph);
+ case 13: return u.format13.get_glyph(codepoint, glyph);
+ case 14:
+ default: return false;
+ }
+ }
+
+ inline glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
+ hb_codepoint_t variation_selector,
+ hb_codepoint_t *glyph) const
+ {
+ switch (u.format) {
+ case 14: return u.format14.get_glyph_variant(codepoint, variation_selector, glyph);
+ default: return GLYPH_VARIANT_NOT_FOUND;
+ }
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) {
+ TRACE_SANITIZE (this);
+ if (!u.format.sanitize (c)) return TRACE_RETURN (false);
+ switch (u.format) {
+ case 0: return TRACE_RETURN (u.format0 .sanitize (c));
+ case 4: return TRACE_RETURN (u.format4 .sanitize (c));
+ case 6: return TRACE_RETURN (u.format6 .sanitize (c));
+ case 10: return TRACE_RETURN (u.format10.sanitize (c));
+ case 12: return TRACE_RETURN (u.format12.sanitize (c));
+ case 13: return TRACE_RETURN (u.format13.sanitize (c));
+ case 14: return TRACE_RETURN (u.format14.sanitize (c));
+ default:return TRACE_RETURN (true);
+ }
+ }
+
+ protected:
+ union {
+ USHORT format; /* Format identifier */
+ CmapSubtableFormat0 format0;
+ CmapSubtableFormat4 format4;
+ CmapSubtableFormat6 format6;
+ CmapSubtableFormat10 format10;
+ CmapSubtableFormat12 format12;
+ CmapSubtableFormat13 format13;
+ CmapSubtableFormat14 format14;
+ } u;
+ public:
+ DEFINE_SIZE_UNION (2, format);
+};
+
+
+struct EncodingRecord
+{
+ inline int cmp (const EncodingRecord &other) const
+ {
+ int ret;
+ ret = platformID.cmp (other.platformID);
+ if (ret) return ret;
+ ret = encodingID.cmp (other.encodingID);
+ if (ret) return ret;
+ return 0;
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c, void *base) {
+ TRACE_SANITIZE (this);
+ return TRACE_RETURN (c->check_struct (this) &&
+ subtable.sanitize (c, base));
+ }
+
+ USHORT platformID; /* Platform ID. */
+ USHORT encodingID; /* Platform-specific encoding ID. */
+ OffsetTo<CmapSubtable, ULONG>
+ subtable; /* Byte offset from beginning of table to the subtable for this encoding. */
+ public:
+ DEFINE_SIZE_STATIC (8);
+};
+
+struct cmap
+{
+ static const hb_tag_t tableTag = HB_OT_TAG_cmap;
+
+ inline const CmapSubtable *find_subtable (unsigned int platform_id,
+ unsigned int encoding_id) const
+ {
+ EncodingRecord key;
+ key.platformID.set (platform_id);
+ key.encodingID.set (encoding_id);
+
+ /* Note: We can use bsearch, but since it has no performance
+ * implications, we use lsearch and as such accept fonts with
+ * unsorted subtable list. */
+ int result = encodingRecord./*bsearch*/lsearch (key);
+ if (result == -1 || !encodingRecord[result].subtable)
+ return NULL;
+
+ return &(this+encodingRecord[result].subtable);
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) {
+ TRACE_SANITIZE (this);
+ return TRACE_RETURN (c->check_struct (this) &&
+ likely (version == 0) &&
+ encodingRecord.sanitize (c, this));
+ }
+
+ USHORT version; /* Table version number (0). */
+ SortedArrayOf<EncodingRecord>
+ encodingRecord; /* Encoding tables. */
+ public:
+ DEFINE_SIZE_ARRAY (4, encodingRecord);
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_CMAP_TABLE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc
new file mode 100644
index 0000000000..c9890c5922
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc
@@ -0,0 +1,289 @@
+/*
+ * Copyright © 2011,2014 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
+ */
+
+#include "hb-private.hh"
+
+#include "hb-ot.h"
+
+#include "hb-font-private.hh"
+
+#include "hb-ot-cmap-table.hh"
+#include "hb-ot-hhea-table.hh"
+#include "hb-ot-hmtx-table.hh"
+
+
+
+struct hb_ot_font_t
+{
+ unsigned int num_glyphs;
+ unsigned int num_hmetrics;
+ const OT::hmtx *hmtx;
+ hb_blob_t *hmtx_blob;
+
+ const OT::CmapSubtable *cmap;
+ const OT::CmapSubtable *cmap_uvs;
+ hb_blob_t *cmap_blob;
+};
+
+
+static hb_ot_font_t *
+_hb_ot_font_create (hb_font_t *font)
+{
+ hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t));
+
+ if (unlikely (!ot_font))
+ return NULL;
+
+ ot_font->num_glyphs = font->face->get_num_glyphs ();
+
+ {
+ hb_blob_t *hhea_blob = OT::Sanitizer<OT::hhea>::sanitize (font->face->reference_table (HB_OT_TAG_hhea));
+ const OT::hhea *hhea = OT::Sanitizer<OT::hhea>::lock_instance (hhea_blob);
+ ot_font->num_hmetrics = hhea->numberOfHMetrics;
+ hb_blob_destroy (hhea_blob);
+ }
+ ot_font->hmtx_blob = OT::Sanitizer<OT::hmtx>::sanitize (font->face->reference_table (HB_OT_TAG_hmtx));
+ if (unlikely (!ot_font->num_hmetrics ||
+ 2 * (ot_font->num_hmetrics + ot_font->num_glyphs) < hb_blob_get_length (ot_font->hmtx_blob)))
+ {
+ hb_blob_destroy (ot_font->hmtx_blob);
+ free (ot_font);
+ return NULL;
+ }
+ ot_font->hmtx = OT::Sanitizer<OT::hmtx>::lock_instance (ot_font->hmtx_blob);
+
+ ot_font->cmap_blob = OT::Sanitizer<OT::cmap>::sanitize (font->face->reference_table (HB_OT_TAG_cmap));
+ const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (ot_font->cmap_blob);
+ const OT::CmapSubtable *subtable = NULL;
+ const OT::CmapSubtable *subtable_uvs = NULL;
+
+ /* 32-bit subtables. */
+ if (!subtable) subtable = cmap->find_subtable (0, 6);
+ if (!subtable) subtable = cmap->find_subtable (0, 4);
+ if (!subtable) subtable = cmap->find_subtable (3, 10);
+ /* 16-bit subtables. */
+ if (!subtable) subtable = cmap->find_subtable (0, 3);
+ if (!subtable) subtable = cmap->find_subtable (3, 1);
+ /* Meh. */
+ if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
+
+ /* UVS subtable. */
+ if (!subtable_uvs) subtable_uvs = cmap->find_subtable (0, 5);
+ /* Meh. */
+ if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtable);
+
+ ot_font->cmap = subtable;
+ ot_font->cmap_uvs = subtable_uvs;
+
+ return ot_font;
+}
+
+static void
+_hb_ot_font_destroy (hb_ot_font_t *ot_font)
+{
+ hb_blob_destroy (ot_font->cmap_blob);
+ hb_blob_destroy (ot_font->hmtx_blob);
+
+ free (ot_font);
+}
+
+
+static hb_bool_t
+hb_ot_get_glyph (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t unicode,
+ hb_codepoint_t variation_selector,
+ hb_codepoint_t *glyph,
+ void *user_data HB_UNUSED)
+
+{
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+
+ if (unlikely (variation_selector))
+ {
+ switch (ot_font->cmap_uvs->get_glyph_variant (unicode,
+ variation_selector,
+ glyph))
+ {
+ case OT::GLYPH_VARIANT_NOT_FOUND: return false;
+ case OT::GLYPH_VARIANT_FOUND: return true;
+ case OT::GLYPH_VARIANT_USE_DEFAULT: break;
+ }
+ }
+
+ return ot_font->cmap->get_glyph (unicode, glyph);
+}
+
+static hb_position_t
+hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t glyph,
+ void *user_data HB_UNUSED)
+{
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+
+ if (unlikely (glyph >= ot_font->num_glyphs))
+ return 0; /* Maybe better to return notdef's advance instead? */
+
+ if (glyph >= ot_font->num_hmetrics)
+ glyph = ot_font->num_hmetrics - 1;
+
+ return font->em_scale_x (ot_font->hmtx->longHorMetric[glyph].advanceWidth);
+}
+
+static hb_position_t
+hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t glyph,
+ void *user_data HB_UNUSED)
+{
+ /* TODO */
+ return 0;
+}
+
+static hb_bool_t
+hb_ot_get_glyph_h_origin (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph HB_UNUSED,
+ hb_position_t *x HB_UNUSED,
+ hb_position_t *y HB_UNUSED,
+ void *user_data HB_UNUSED)
+{
+ /* We always work in the horizontal coordinates. */
+ return true;
+}
+
+static hb_bool_t
+hb_ot_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_position_t *x,
+ hb_position_t *y,
+ void *user_data HB_UNUSED)
+{
+ /* TODO */
+ return false;
+}
+
+static hb_position_t
+hb_ot_get_glyph_h_kerning (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t left_glyph,
+ hb_codepoint_t right_glyph,
+ void *user_data HB_UNUSED)
+{
+ /* TODO */
+ return 0;
+}
+
+static hb_position_t
+hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t top_glyph HB_UNUSED,
+ hb_codepoint_t bottom_glyph HB_UNUSED,
+ void *user_data HB_UNUSED)
+{
+ return 0;
+}
+
+static hb_bool_t
+hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents,
+ void *user_data HB_UNUSED)
+{
+ /* TODO */
+ return false;
+}
+
+static hb_bool_t
+hb_ot_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t glyph,
+ unsigned int point_index,
+ hb_position_t *x,
+ hb_position_t *y,
+ void *user_data HB_UNUSED)
+{
+ /* TODO */
+ return false;
+}
+
+static hb_bool_t
+hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t glyph,
+ char *name, unsigned int size,
+ void *user_data HB_UNUSED)
+{
+ /* TODO */
+ return false;
+}
+
+static hb_bool_t
+hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ const char *name, int len, /* -1 means nul-terminated */
+ hb_codepoint_t *glyph,
+ void *user_data HB_UNUSED)
+{
+ /* TODO */
+ return false;
+}
+
+
+static hb_font_funcs_t *
+_hb_ot_get_font_funcs (void)
+{
+ static const hb_font_funcs_t ot_ffuncs = {
+ HB_OBJECT_HEADER_STATIC,
+
+ true, /* immutable */
+
+ {
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_ot_get_##name,
+ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+ }
+ };
+
+ return const_cast<hb_font_funcs_t *> (&ot_ffuncs);
+}
+
+
+void
+hb_ot_font_set_funcs (hb_font_t *font)
+{
+ hb_ot_font_t *ot_font = _hb_ot_font_create (font);
+ if (unlikely (!ot_font))
+ return;
+
+ hb_font_set_funcs (font,
+ _hb_ot_get_font_funcs (),
+ ot_font,
+ (hb_destroy_func_t) _hb_ot_font_destroy);
+}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.h b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.h
new file mode 100644
index 0000000000..7a8c04ac33
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2014 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
+ */
+
+#ifndef HB_OT_FONT_H
+#define HB_OT_FONT_H
+
+#include "hb.h"
+
+HB_BEGIN_DECLS
+
+
+void
+hb_ot_font_set_funcs (hb_font_t *font);
+
+
+HB_END_DECLS
+
+#endif /* HB_OT_FONT_H */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh
index 0285f0cf31..ec4e8c9d45 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh
@@ -58,12 +58,12 @@ struct head
protected:
FixedVersion version; /* Version of the head table--currently
- * 0x00010000 for version 1.0. */
+ * 0x00010000u for version 1.0. */
FixedVersion fontRevision; /* Set by font manufacturer. */
ULONG checkSumAdjustment; /* To compute: set it to 0, sum the
* entire font as ULONG, then store
- * 0xB1B0AFBA - sum. */
- ULONG magicNumber; /* Set to 0x5F0F3CF5. */
+ * 0xB1B0AFBAu - sum. */
+ ULONG magicNumber; /* Set to 0x5F0F3CF5u. */
USHORT flags; /* Bit 0: Baseline for font at y=0;
* Bit 1: Left sidebearing point at x=0;
* Bit 2: Instructions may depend on point size;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh
index 611de8a666..d433200165 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh
@@ -49,8 +49,8 @@ struct hhea
return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1));
}
- protected:
- FixedVersion version; /* 0x00010000 for version 1.0. */
+ public:
+ FixedVersion version; /* 0x00010000u for version 1.0. */
FWORD ascender; /* Typographic ascent. <a
* href="http://developer.apple.com/fonts/TTRefMan/RM06/Chap6hhea.html">
* (Distance from baseline of highest
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh
index d107cf990a..e918e3b3f4 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh
@@ -59,7 +59,7 @@ struct hmtx
return TRACE_RETURN (true);
}
- protected:
+ public:
LongHorMetric longHorMetric[VAR]; /* Paired advance width and left side
* bearing values for each glyph. The
* value numOfHMetrics comes from
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh
index 02d0d0f87c..abd063c896 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh
@@ -103,7 +103,8 @@ struct RecordArrayOf : SortedArrayOf<Record<Type> > {
}
inline bool find_index (hb_tag_t tag, unsigned int *index) const
{
- int i = this->search (tag);
+ /* If we want to allow non-sorted data, we can lsearch(). */
+ int i = this->/*lsearch*/bsearch (tag);
if (i != -1) {
if (index) *index = i;
return true;
@@ -189,10 +190,10 @@ struct LangSys
unsigned int *feature_indexes /* OUT */) const
{ return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
- inline bool has_required_feature (void) const { return reqFeatureIndex != 0xffff; }
+ inline bool has_required_feature (void) const { return reqFeatureIndex != 0xFFFFu; }
inline unsigned int get_required_feature_index (void) const
{
- if (reqFeatureIndex == 0xffff)
+ if (reqFeatureIndex == 0xFFFFu)
return Index::NOT_FOUND_INDEX;
return reqFeatureIndex;;
}
@@ -203,11 +204,11 @@ struct LangSys
return TRACE_RETURN (c->check_struct (this) && featureIndex.sanitize (c));
}
- Offset lookupOrder; /* = Null (reserved for an offset to a
+ Offset<> lookupOrderZ; /* = Null (reserved for an offset to a
* reordering table) */
USHORT reqFeatureIndex;/* Index of a feature required for this
* language system--if no required features
- * = 0xFFFF */
+ * = 0xFFFFu */
IndexArray featureIndex; /* Array of indices into the FeatureList */
public:
DEFINE_SIZE_ARRAY (6, featureIndex);
@@ -447,9 +448,9 @@ struct FeatureParams
TRACE_SANITIZE (this);
if (tag == HB_TAG ('s','i','z','e'))
return TRACE_RETURN (u.size.sanitize (c));
- if ((tag & 0xFFFF0000) == HB_TAG ('s','s','\0','\0')) /* ssXX */
+ if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
return TRACE_RETURN (u.stylisticSet.sanitize (c));
- if ((tag & 0xFFFF0000) == HB_TAG ('c','v','\0','\0')) /* cvXX */
+ if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
return TRACE_RETURN (u.characterVariants.sanitize (c));
return TRACE_RETURN (true);
}
@@ -501,11 +502,11 @@ struct Feature
* Adobe tools, only the 'size' feature had FeatureParams defined.
*/
- Offset orig_offset = featureParams;
+ OffsetTo<FeatureParams> orig_offset = featureParams;
if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
return TRACE_RETURN (false);
- if (likely (!orig_offset))
+ if (likely (orig_offset.is_null ()))
return TRACE_RETURN (true);
if (featureParams == 0 && closure &&
@@ -513,13 +514,13 @@ struct Feature
closure->list_base && closure->list_base < this)
{
unsigned int new_offset_int = (unsigned int) orig_offset -
- ((char *) this - (char *) closure->list_base);
+ (((char *) this) - ((char *) closure->list_base));
- Offset new_offset;
+ OffsetTo<FeatureParams> new_offset;
/* Check that it did not overflow. */
new_offset.set (new_offset_int);
if (new_offset == new_offset_int &&
- featureParams.try_set (c, new_offset) &&
+ c->try_set (&featureParams, new_offset) &&
!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
return TRACE_RETURN (false);
}
@@ -584,7 +585,7 @@ struct Lookup
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
lookupType.set (lookup_type);
- lookupFlag.set (lookup_props & 0xFFFF);
+ lookupFlag.set (lookup_props & 0xFFFFu);
if (unlikely (!subTable.serialize (c, num_subtables))) return TRACE_RETURN (false);
if (lookupFlag & LookupFlag::UseMarkFilteringSet)
{
@@ -608,7 +609,7 @@ struct Lookup
USHORT lookupType; /* Different enumerations for GSUB and GPOS */
USHORT lookupFlag; /* Lookup qualifiers */
- ArrayOf<Offset>
+ ArrayOf<Offset<> >
subTable; /* Array of SubTables */
USHORT markFilteringSetX[VAR]; /* Index (base 0) into GDEF mark glyph sets
* structure. This field is only present if bit
@@ -631,7 +632,7 @@ struct CoverageFormat1
private:
inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
{
- int i = glyphArray.search (glyph_id);
+ int i = glyphArray.bsearch (glyph_id);
ASSERT_STATIC (((unsigned int) -1) == NOT_COVERED);
return i;
}
@@ -696,7 +697,7 @@ struct CoverageFormat2
private:
inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
{
- int i = rangeRecord.search (glyph_id);
+ int i = rangeRecord.bsearch (glyph_id);
if (i != -1) {
const RangeRecord &range = rangeRecord[i];
return (unsigned int) range.value + (glyph_id - range.start);
@@ -992,7 +993,7 @@ struct ClassDefFormat2
private:
inline unsigned int get_class (hb_codepoint_t glyph_id) const
{
- int i = rangeRecord.search (glyph_id);
+ int i = rangeRecord.bsearch (glyph_id);
if (i != -1)
return rangeRecord[i].value;
return 0;
@@ -1130,7 +1131,7 @@ struct Device
unsigned int byte = deltaValue[s >> (4 - f)];
unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
- unsigned int mask = (0xFFFF >> (16 - (1 << f)));
+ unsigned int mask = (0xFFFFu >> (16 - (1 << f)));
int delta = bits & mask;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh
index 389cbb9e39..84a5e797c6 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh
@@ -282,7 +282,7 @@ struct MarkGlyphSetsFormat1
protected:
USHORT format; /* Format identifier--format = 1 */
- LongOffsetArrayOf<Coverage>
+ ArrayOf<OffsetTo<Coverage, ULONG> >
coverage; /* Array of long offsets to mark set
* coverage tables */
public:
@@ -360,9 +360,9 @@ struct GDEF
hb_position_t *caret_array /* OUT */) const
{ return (this+ligCaretList).get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array); }
- inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002 && markGlyphSetsDef[0] != 0; }
+ inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef[0] != 0; }
inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
- { return version.to_int () >= 0x00010002 && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); }
+ { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); }
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
@@ -372,7 +372,7 @@ struct GDEF
attachList.sanitize (c, this) &&
ligCaretList.sanitize (c, this) &&
markAttachClassDef.sanitize (c, this) &&
- (version.to_int () < 0x00010002 || markGlyphSetsDef[0].sanitize (c, this)));
+ (version.to_int () < 0x00010002u || markGlyphSetsDef[0].sanitize (c, this)));
}
@@ -400,7 +400,7 @@ struct GDEF
protected:
FixedVersion version; /* Version of the GDEF table--currently
- * 0x00010002 */
+ * 0x00010002u */
OffsetTo<ClassDef>
glyphClassDef; /* Offset to class definition table
* for glyph type--from beginning of
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh
index 7c0a4ea666..d8e3e6e11d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh
@@ -49,18 +49,18 @@ typedef Value ValueRecord[VAR];
struct ValueFormat : USHORT
{
enum Flags {
- xPlacement = 0x0001, /* Includes horizontal adjustment for placement */
- yPlacement = 0x0002, /* Includes vertical adjustment for placement */
- xAdvance = 0x0004, /* Includes horizontal adjustment for advance */
- yAdvance = 0x0008, /* Includes vertical adjustment for advance */
- xPlaDevice = 0x0010, /* Includes horizontal Device table for placement */
- yPlaDevice = 0x0020, /* Includes vertical Device table for placement */
- xAdvDevice = 0x0040, /* Includes horizontal Device table for advance */
- yAdvDevice = 0x0080, /* Includes vertical Device table for advance */
- ignored = 0x0F00, /* Was used in TrueType Open for MM fonts */
- reserved = 0xF000, /* For future use */
-
- devices = 0x00F0 /* Mask for having any Device table */
+ xPlacement = 0x0001u, /* Includes horizontal adjustment for placement */
+ yPlacement = 0x0002u, /* Includes vertical adjustment for placement */
+ xAdvance = 0x0004u, /* Includes horizontal adjustment for advance */
+ yAdvance = 0x0008u, /* Includes vertical adjustment for advance */
+ xPlaDevice = 0x0010u, /* Includes horizontal Device table for placement */
+ yPlaDevice = 0x0020u, /* Includes vertical Device table for placement */
+ xAdvDevice = 0x0040u, /* Includes horizontal Device table for advance */
+ yAdvDevice = 0x0080u, /* Includes vertical Device table for advance */
+ ignored = 0x0F00u, /* Was used in TrueType Open for MM fonts */
+ reserved = 0xF000u, /* For future use */
+
+ devices = 0x00F0u /* Mask for having any Device table */
};
/* All fields are options. Only those available advance the value pointer. */
@@ -1608,14 +1608,14 @@ GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
/* Out-of-class implementation for methods recursing */
template <typename context_t>
-inline typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
+/*static*/ inline typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
{
const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
const PosLookup &l = gpos.get_lookup (lookup_index);
return l.dispatch (c);
}
-inline bool PosLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index)
+/*static*/ inline bool PosLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index)
{
const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
const PosLookup &l = gpos.get_lookup (lookup_index);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh
index 76b4f33c70..e1939735de 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh
@@ -44,7 +44,7 @@ struct SingleSubstFormat1
for (iter.init (this+coverage); iter.more (); iter.next ()) {
hb_codepoint_t glyph_id = iter.get_glyph ();
if (c->glyphs->has (glyph_id))
- c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFF);
+ c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
}
}
@@ -55,7 +55,7 @@ struct SingleSubstFormat1
for (iter.init (this+coverage); iter.more (); iter.next ()) {
hb_codepoint_t glyph_id = iter.get_glyph ();
c->input->add (glyph_id);
- c->output->add ((glyph_id + deltaGlyphID) & 0xFFFF);
+ c->output->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
}
}
@@ -79,7 +79,7 @@ struct SingleSubstFormat1
/* According to the Adobe Annotated OpenType Suite, result is always
* limited to 16bit. */
- glyph_id = (glyph_id + deltaGlyphID) & 0xFFFF;
+ glyph_id = (glyph_id + deltaGlyphID) & 0xFFFFu;
c->replace_glyph (glyph_id);
return TRACE_RETURN (true);
@@ -270,23 +270,34 @@ struct Sequence
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY (this);
- if (unlikely (!substitute.len)) return TRACE_RETURN (false);
-
- unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
- HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
unsigned int count = substitute.len;
- if (count == 1) /* Special-case to make it in-place. */
+
+ /* TODO:
+ * Testing shows that Uniscribe actually allows zero-len susbstitute,
+ * which essentially deletes a glyph. We don't allow for now. It
+ * can be confusing to the client since the cluster from the deleted
+ * glyph won't be merged with any output cluster... Also, currently
+ * buffer->move_to() makes assumptions about this too. Perhaps fix
+ * in the future after figuring out what to do with the clusters.
+ */
+ if (unlikely (!count)) return TRACE_RETURN (false);
+
+ /* Special-case to make it in-place and not consider this
+ * as a "multiplied" substitution. */
+ if (unlikely (count == 1))
{
c->replace_glyph (substitute.array[0]);
+ return TRACE_RETURN (true);
}
- else
- {
- for (unsigned int i = 0; i < count; i++) {
- _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
- c->output_glyph (substitute.array[i], klass);
- }
- c->buffer->skip_glyph ();
+
+ unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
+ HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
+
+ for (unsigned int i = 0; i < count; i++) {
+ _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
+ c->output_glyph_for_component (substitute.array[i], klass);
}
+ c->buffer->skip_glyph ();
return TRACE_RETURN (true);
}
@@ -624,7 +635,16 @@ struct Ligature
{
TRACE_APPLY (this);
unsigned int count = component.len;
- if (unlikely (count < 1)) return TRACE_RETURN (false);
+
+ if (unlikely (!count)) return TRACE_RETURN (false);
+
+ /* Special-case to make it in-place and not consider this
+ * as a "ligated" substitution. */
+ if (unlikely (count == 1))
+ {
+ c->replace_glyph (ligGlyph);
+ return TRACE_RETURN (true);
+ }
bool is_mark_ligature = false;
unsigned int total_component_count = 0;
@@ -1338,7 +1358,7 @@ GSUB::substitute_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSE
/* Out-of-class implementation for methods recursing */
-inline bool ExtensionSubst::is_reverse (void) const
+/*static*/ inline bool ExtensionSubst::is_reverse (void) const
{
unsigned int type = get_type ();
if (unlikely (type == SubstLookupSubTable::Extension))
@@ -1347,14 +1367,14 @@ inline bool ExtensionSubst::is_reverse (void) const
}
template <typename context_t>
-inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
+/*static*/ inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
{
const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
const SubstLookup &l = gsub.get_lookup (lookup_index);
return l.dispatch (c);
}
-inline bool SubstLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index)
+/*static*/ inline bool SubstLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index)
{
const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
const SubstLookup &l = gsub.get_lookup (lookup_index);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh
index bdd773e36b..546ff4b0fd 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh
@@ -349,11 +349,7 @@ struct hb_apply_context_t
may_skip (const hb_apply_context_t *c,
const hb_glyph_info_t &info) const
{
- unsigned int property;
-
- property = _hb_glyph_info_get_glyph_props (&info);
-
- if (!c->match_properties (info.codepoint, property, lookup_props))
+ if (!c->check_glyph_property (&info, lookup_props))
return SKIP_YES;
if (unlikely (_hb_glyph_info_is_default_ignorable (&info) &&
@@ -487,7 +483,6 @@ struct hb_apply_context_t
const hb_glyph_info_t &info = c->buffer->out_info[idx];
matcher_t::may_skip_t skip = matcher.may_skip (c, info);
-
if (unlikely (skip == matcher_t::SKIP_YES))
continue;
@@ -538,10 +533,12 @@ struct hb_apply_context_t
}
inline bool
- match_properties (hb_codepoint_t glyph,
- unsigned int glyph_props,
- unsigned int lookup_props) const
+ check_glyph_property (const hb_glyph_info_t *info,
+ unsigned int lookup_props) const
{
+ hb_codepoint_t glyph = info->codepoint;
+ unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info);
+
/* Not covered, if, for example, glyph class is ligature and
* lookup_props includes LookupFlags::IgnoreLigatures
*/
@@ -554,26 +551,27 @@ struct hb_apply_context_t
return true;
}
- inline bool
- check_glyph_property (hb_glyph_info_t *info,
- unsigned int lookup_props) const
- {
- unsigned int property;
-
- property = _hb_glyph_info_get_glyph_props (info);
-
- return match_properties (info->codepoint, property, lookup_props);
- }
-
inline void _set_glyph_props (hb_codepoint_t glyph_index,
unsigned int class_guess = 0,
- bool ligature = false) const
+ bool ligature = false,
+ bool component = false) const
{
unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) &
HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
if (ligature)
+ {
add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
+ /* In the only place that the MULTIPLIED bit is used, Uniscribe
+ * seems to only care about the "last" transformation between
+ * Ligature and Multiple substitions. Ie. if you ligate, expand,
+ * and ligate again, it forgives the multiplication and acts as
+ * if only ligation happened. As such, clear MULTIPLIED bit.
+ */
+ add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
+ }
+ if (component)
+ add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
if (likely (has_glyph_classes))
_hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index));
else if (class_guess)
@@ -596,10 +594,10 @@ struct hb_apply_context_t
_set_glyph_props (glyph_index, class_guess, true);
buffer->replace_glyph (glyph_index);
}
- inline void output_glyph (hb_codepoint_t glyph_index,
- unsigned int class_guess) const
+ inline void output_glyph_for_component (hb_codepoint_t glyph_index,
+ unsigned int class_guess) const
{
- _set_glyph_props (glyph_index, class_guess);
+ _set_glyph_props (glyph_index, class_guess, false, true);
buffer->output_glyph (glyph_index);
}
};
@@ -882,6 +880,7 @@ static inline void ligate_input (hb_apply_context_t *c,
break;
}
}
+ TRACE_RETURN (true);
}
static inline bool match_backtrack (hb_apply_context_t *c,
@@ -994,7 +993,9 @@ static inline bool apply_lookup (hb_apply_context_t *c,
/* Recursed lookup changed buffer len. Adjust. */
- /* end can't go back past the current match position. */
+ /* end can't go back past the current match position.
+ * Note: this is only true because we do NOT allow MultipleSubst
+ * with zero sequence len. */
end = MAX ((int) match_positions[idx] + 1, int (end) + delta);
unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
@@ -2253,8 +2254,8 @@ struct GSUBGPOS
inline unsigned int get_feature_count (void) const
{ return (this+featureList).len; }
- inline const Tag& get_feature_tag (unsigned int i) const
- { return (this+featureList).get_tag (i); }
+ inline hb_tag_t get_feature_tag (unsigned int i) const
+ { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_tag (i); }
inline unsigned int get_feature_tags (unsigned int start_offset,
unsigned int *feature_count /* IN/OUT */,
hb_tag_t *feature_tags /* OUT */) const
@@ -2279,7 +2280,7 @@ struct GSUBGPOS
protected:
FixedVersion version; /* Version of the GSUB/GPOS table--initially set
- * to 0x00010000 */
+ * to 0x00010000u */
OffsetTo<ScriptList>
scriptList; /* ScriptList table */
OffsetTo<FeatureList>
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh
index 79eb859566..67a6df5b42 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh
@@ -214,7 +214,7 @@ struct JSTF
protected:
FixedVersion version; /* Version of the JSTF table--initially set
- * to 0x00010000 */
+ * to 0x00010000u */
RecordArrayOf<JstfScript>
scriptList; /* Array of JstfScripts--listed
* alphabetically by ScriptTag */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-private.hh
index 0a0a54b25d..9b06300800 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-private.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-private.hh
@@ -50,9 +50,11 @@ typedef enum
/* The following are used internally; not derived from GDEF. */
HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED = 0x10u,
HB_OT_LAYOUT_GLYPH_PROPS_LIGATED = 0x20u,
+ HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED = 0x40u,
HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
- HB_OT_LAYOUT_GLYPH_PROPS_LIGATED
+ HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
+ HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED
} hb_ot_layout_glyph_class_mask_t;
@@ -182,62 +184,62 @@ enum {
MASK0_GEN_CAT = 0x1Fu
};
-inline void
+static inline void
_hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_unicode_funcs_t *unicode)
{
/* XXX This shouldn't be inlined, or at least not while is_default_ignorable() is inline. */
info->unicode_props0() = ((unsigned int) unicode->general_category (info->codepoint)) |
(unicode->is_default_ignorable (info->codepoint) ? MASK0_IGNORABLE : 0) |
- (info->codepoint == 0x200C ? MASK0_ZWNJ : 0) |
- (info->codepoint == 0x200D ? MASK0_ZWJ : 0);
+ (info->codepoint == 0x200Cu ? MASK0_ZWNJ : 0) |
+ (info->codepoint == 0x200Du ? MASK0_ZWJ : 0);
info->unicode_props1() = unicode->modified_combining_class (info->codepoint);
}
-inline void
+static inline void
_hb_glyph_info_set_general_category (hb_glyph_info_t *info,
hb_unicode_general_category_t gen_cat)
{
info->unicode_props0() = (unsigned int) gen_cat | ((info->unicode_props0()) & ~MASK0_GEN_CAT);
}
-inline hb_unicode_general_category_t
+static inline hb_unicode_general_category_t
_hb_glyph_info_get_general_category (const hb_glyph_info_t *info)
{
return (hb_unicode_general_category_t) (info->unicode_props0() & MASK0_GEN_CAT);
}
-inline void
+static inline void
_hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info,
unsigned int modified_class)
{
info->unicode_props1() = modified_class;
}
-inline unsigned int
+static inline unsigned int
_hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
{
return info->unicode_props1();
}
-inline hb_bool_t
+static inline hb_bool_t
_hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
{
return !!(info->unicode_props0() & MASK0_IGNORABLE);
}
-inline hb_bool_t
+static inline hb_bool_t
_hb_glyph_info_is_zwnj (const hb_glyph_info_t *info)
{
return !!(info->unicode_props0() & MASK0_ZWNJ);
}
-inline hb_bool_t
+static inline hb_bool_t
_hb_glyph_info_is_zwj (const hb_glyph_info_t *info)
{
return !!(info->unicode_props0() & MASK0_ZWJ);
}
-inline void
+static inline void
_hb_glyph_info_flip_joiners (hb_glyph_info_t *info)
{
info->unicode_props0() ^= MASK0_ZWNJ | MASK0_ZWJ;
@@ -339,31 +341,31 @@ _hb_allocate_lig_id (hb_buffer_t *buffer) {
/* glyph_props: */
-inline void
+static inline void
_hb_glyph_info_set_glyph_props (hb_glyph_info_t *info, unsigned int props)
{
info->glyph_props() = props;
}
-inline unsigned int
+static inline unsigned int
_hb_glyph_info_get_glyph_props (const hb_glyph_info_t *info)
{
return info->glyph_props();
}
-inline bool
+static inline bool
_hb_glyph_info_is_base_glyph (const hb_glyph_info_t *info)
{
return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH);
}
-inline bool
+static inline bool
_hb_glyph_info_is_ligature (const hb_glyph_info_t *info)
{
return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE);
}
-inline bool
+static inline bool
_hb_glyph_info_is_mark (const hb_glyph_info_t *info)
{
return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
@@ -381,23 +383,43 @@ _hb_glyph_info_ligated (const hb_glyph_info_t *info)
return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED);
}
+static inline bool
+_hb_glyph_info_multiplied (const hb_glyph_info_t *info)
+{
+ return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
+}
+
+static inline bool
+_hb_glyph_info_ligated_and_didnt_multiply (const hb_glyph_info_t *info)
+{
+ return _hb_glyph_info_ligated (info) && !_hb_glyph_info_multiplied (info);
+}
+
+static inline void
+_hb_glyph_info_clear_ligated_and_multiplied (hb_glyph_info_t *info)
+{
+ info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
+ HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
+}
+
+
/* Allocation / deallocation. */
-inline void
+static inline void
_hb_buffer_allocate_unicode_vars (hb_buffer_t *buffer)
{
HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props0);
HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props1);
}
-inline void
+static inline void
_hb_buffer_deallocate_unicode_vars (hb_buffer_t *buffer)
{
HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props0);
HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props1);
}
-inline void
+static inline void
_hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer)
{
HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props);
@@ -405,7 +427,7 @@ _hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer)
HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
}
-inline void
+static inline void
_hb_buffer_deallocate_gsubgpos_vars (hb_buffer_t *buffer)
{
HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
index 183726e63c..661d90ea0d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
@@ -327,9 +327,28 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face,
unsigned int language_index,
unsigned int *feature_index)
{
- const OT::LangSys &l = get_gsubgpos_table (face, table_tag).get_script (script_index).get_lang_sys (language_index);
+ return hb_ot_layout_language_get_required_feature (face,
+ table_tag,
+ script_index,
+ language_index,
+ feature_index,
+ NULL);
+}
+
+hb_bool_t
+hb_ot_layout_language_get_required_feature (hb_face_t *face,
+ hb_tag_t table_tag,
+ unsigned int script_index,
+ unsigned int language_index,
+ unsigned int *feature_index,
+ hb_tag_t *feature_tag)
+{
+ const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
+ const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
- if (feature_index) *feature_index = l.get_required_feature_index ();
+ unsigned int index = l.get_required_feature_index ();
+ if (feature_index) *feature_index = index;
+ if (feature_tag) *feature_tag = g.get_feature_tag (index);
return l.has_required_feature ();
}
@@ -468,11 +487,12 @@ _hb_ot_layout_collect_lookups_features (hb_face_t *face,
if (!features)
{
unsigned int required_feature_index;
- if (hb_ot_layout_language_get_required_feature_index (face,
- table_tag,
- script_index,
- language_index,
- &required_feature_index))
+ if (hb_ot_layout_language_get_required_feature (face,
+ table_tag,
+ script_index,
+ language_index,
+ &required_feature_index,
+ NULL))
_hb_ot_layout_collect_lookups_lookups (face,
table_tag,
required_feature_index,
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h
index d90eff374d..949678ac42 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h
@@ -92,9 +92,9 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font,
* GSUB/GPOS feature query and enumeration interface
*/
-#define HB_OT_LAYOUT_NO_SCRIPT_INDEX ((unsigned int) 0xFFFF)
-#define HB_OT_LAYOUT_NO_FEATURE_INDEX ((unsigned int) 0xFFFF)
-#define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX ((unsigned int) 0xFFFF)
+#define HB_OT_LAYOUT_NO_SCRIPT_INDEX 0xFFFFu
+#define HB_OT_LAYOUT_NO_FEATURE_INDEX 0xFFFFu
+#define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX 0xFFFFu
unsigned int
hb_ot_layout_table_get_script_tags (hb_face_t *face,
@@ -146,6 +146,14 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face,
unsigned int language_index,
unsigned int *feature_index);
+hb_bool_t
+hb_ot_layout_language_get_required_feature (hb_face_t *face,
+ hb_tag_t table_tag,
+ unsigned int script_index,
+ unsigned int language_index,
+ unsigned int *feature_index,
+ hb_tag_t *feature_tag);
+
unsigned int
hb_ot_layout_language_get_feature_indexes (hb_face_t *face,
hb_tag_t table_tag,
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-map-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-map-private.hh
index 0e718a6f1f..86b7e9fafe 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-map-private.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-map-private.hh
@@ -153,26 +153,26 @@ struct hb_ot_map_t
};
enum hb_ot_map_feature_flags_t {
- F_NONE = 0x0000,
- F_GLOBAL = 0x0001,
- F_HAS_FALLBACK = 0x0002,
- F_MANUAL_ZWJ = 0x0004
+ F_NONE = 0x0000u,
+ F_GLOBAL = 0x0001u,
+ F_HAS_FALLBACK = 0x0002u,
+ F_MANUAL_ZWJ = 0x0004u
};
/* Macro version for where const is desired. */
#define F_COMBINE(l,r) (hb_ot_map_feature_flags_t ((unsigned int) (l) | (unsigned int) (r)))
-inline hb_ot_map_feature_flags_t
+static inline hb_ot_map_feature_flags_t
operator | (hb_ot_map_feature_flags_t l, hb_ot_map_feature_flags_t r)
{ return hb_ot_map_feature_flags_t ((unsigned int) l | (unsigned int) r); }
-inline hb_ot_map_feature_flags_t
+static inline hb_ot_map_feature_flags_t
operator & (hb_ot_map_feature_flags_t l, hb_ot_map_feature_flags_t r)
{ return hb_ot_map_feature_flags_t ((unsigned int) l & (unsigned int) r); }
-inline hb_ot_map_feature_flags_t
+static inline hb_ot_map_feature_flags_t
operator ~ (hb_ot_map_feature_flags_t r)
{ return hb_ot_map_feature_flags_t (~(unsigned int) r); }
-inline hb_ot_map_feature_flags_t&
+static inline hb_ot_map_feature_flags_t&
operator |= (hb_ot_map_feature_flags_t &l, hb_ot_map_feature_flags_t r)
{ l = l | r; return l; }
-inline hb_ot_map_feature_flags_t&
+static inline hb_ot_map_feature_flags_t&
operator &= (hb_ot_map_feature_flags_t& l, hb_ot_map_feature_flags_t r)
{ l = l & r; return l; }
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc
index 559193c1ba..4985eb22b2 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc
@@ -99,6 +99,7 @@ void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value,
{
feature_info_t *info = feature_infos.push();
if (unlikely (!info)) return;
+ if (unlikely (!tag)) return;
info->tag = tag;
info->seq = feature_infos.len;
info->max_value = value;
@@ -131,9 +132,25 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m)
{
m.global_mask = 1;
- for (unsigned int table_index = 0; table_index < 2; table_index++) {
+ unsigned int required_feature_index[2];
+ hb_tag_t required_feature_tag[2];
+ /* We default to applying required feature in stage 0. If the required
+ * feature has a tag that is known to the shaper, we apply required feature
+ * in the stage for that tag.
+ */
+ unsigned int required_feature_stage[2] = {0, 0};
+
+ for (unsigned int table_index = 0; table_index < 2; table_index++)
+ {
m.chosen_script[table_index] = chosen_script[table_index];
m.found_script[table_index] = found_script[table_index];
+
+ hb_ot_layout_language_get_required_feature (face,
+ table_tags[table_index],
+ script_index[table_index],
+ language_index[table_index],
+ &required_feature_index[table_index],
+ &required_feature_tag[table_index]);
}
if (!feature_infos.len)
@@ -141,7 +158,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m)
/* Sort features and merge duplicates */
{
- feature_infos.sort ();
+ feature_infos.qsort ();
unsigned int j = 0;
for (unsigned int i = 1; i < feature_infos.len; i++)
if (feature_infos[i].tag != feature_infos[j].tag)
@@ -166,7 +183,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m)
/* Allocate bits now */
unsigned int next_bit = 1;
- for (unsigned int i = 0; i < feature_infos.len; i++) {
+ for (unsigned int i = 0; i < feature_infos.len; i++)
+ {
const feature_info_t *info = &feature_infos[i];
unsigned int bits_needed;
@@ -184,12 +202,20 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m)
hb_bool_t found = false;
unsigned int feature_index[2];
for (unsigned int table_index = 0; table_index < 2; table_index++)
+ {
+ if (required_feature_tag[table_index] == info->tag)
+ {
+ required_feature_stage[table_index] = info->stage[table_index];
+ found = true;
+ continue;
+ }
found |= hb_ot_layout_language_find_feature (face,
table_tags[table_index],
script_index[table_index],
language_index[table_index],
info->tag,
&feature_index[table_index]);
+ }
if (!found && !(info->flags & F_HAS_FALLBACK))
continue;
@@ -224,23 +250,21 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m)
add_gsub_pause (NULL);
add_gpos_pause (NULL);
- for (unsigned int table_index = 0; table_index < 2; table_index++) {
- hb_tag_t table_tag = table_tags[table_index];
-
+ for (unsigned int table_index = 0; table_index < 2; table_index++)
+ {
/* Collect lookup indices for features */
- unsigned int required_feature_index;
- if (hb_ot_layout_language_get_required_feature_index (face,
- table_tag,
- script_index[table_index],
- language_index[table_index],
- &required_feature_index))
- m.add_lookups (face, table_index, required_feature_index, 1, true);
-
unsigned int stage_index = 0;
unsigned int last_num_lookups = 0;
for (unsigned stage = 0; stage < current_stage[table_index]; stage++)
{
+ if (required_feature_index[table_index] != HB_OT_LAYOUT_NO_FEATURE_INDEX &&
+ required_feature_stage[table_index] == stage)
+ m.add_lookups (face, table_index,
+ required_feature_index[table_index],
+ 1 /* mask */,
+ true /* auto_zwj */);
+
for (unsigned i = 0; i < m.features.len; i++)
if (m.features[i].stage[table_index] == stage)
m.add_lookups (face, table_index,
@@ -251,7 +275,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m)
/* Sort lookups and merge duplicates */
if (last_num_lookups < m.lookups[table_index].len)
{
- m.lookups[table_index].sort (last_num_lookups, m.lookups[table_index].len);
+ m.lookups[table_index].qsort (last_num_lookups, m.lookups[table_index].len);
unsigned int j = last_num_lookups;
for (unsigned int i = j + 1; i < m.lookups[table_index].len; i++)
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh
index e6d255579c..b1f832852d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh
@@ -50,13 +50,13 @@ struct maxp
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) &&
- likely (version.major == 1 || (version.major == 0 && version.minor == 0x5000)));
+ likely (version.major == 1 || (version.major == 0 && version.minor == 0x5000u)));
}
/* We only implement version 0.5 as none of the extra fields in version 1.0 are useful. */
protected:
FixedVersion version; /* Version of the maxp table (0.5 or 1.0),
- * 0x00005000 or 0x00010000. */
+ * 0x00005000u or 0x00010000u. */
USHORT numGlyphs; /* The number of glyphs in the font. */
public:
DEFINE_SIZE_STATIC (6);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh
index 07dc0565ca..31d9fac7e2 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh
@@ -121,7 +121,7 @@ struct name
/* We only implement format 0 for now. */
USHORT format; /* Format selector (=0/1). */
USHORT count; /* Number of name records. */
- Offset stringOffset; /* Offset to start of string storage (from start of table). */
+ Offset<> stringOffset; /* Offset to start of string storage (from start of table). */
NameRecord nameRecord[VAR]; /* The name records where count is the number of records. */
public:
DEFINE_SIZE_ARRAY (6, nameRecord);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh
index 6b2b87e3f2..2d8488e151 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh
@@ -71,7 +71,7 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS
!hb_font_get_glyph (font, u, 0, &u_glyph) ||
!hb_font_get_glyph (font, s, 0, &s_glyph) ||
u_glyph == s_glyph ||
- u_glyph > 0xFFFF || s_glyph > 0xFFFF)
+ u_glyph > 0xFFFFu || s_glyph > 0xFFFFu)
continue;
glyphs[num_glyphs].set (u_glyph);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh
index 730a275bf0..d41d6ce598 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh
@@ -2,12 +2,14 @@
/*
* The following table is generated by running:
*
- * ./gen-arabic-table.py ArabicShaping.txt UnicodeData.txt
+ * ./gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt
*
* on files with these headers:
*
- * # ArabicShaping-6.2.0.txt
- * # Date: 2012-05-15, 21:05:00 GMT [KW]
+ * # ArabicShaping-7.0.0.txt
+ * # Date: 2014-02-14, 21:00:00 GMT [RP, KW, LI]
+ * # Blocks-7.0.0.txt
+ * # Date: 2014-04-03, 23:23:00 GMT [RP, KW]
* UnicodeData.txt does not have a header.
*/
@@ -15,903 +17,342 @@
#define HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH
+#define X JOINING_TYPE_X
+#define R JOINING_TYPE_R
+#define U JOINING_TYPE_U
+#define A JOINING_GROUP_ALAPH
+#define DR JOINING_GROUP_DALATH_RISH
+#define L JOINING_TYPE_L
+#define C JOINING_TYPE_C
+#define D JOINING_TYPE_D
+
static const uint8_t joining_table[] =
{
- /* Arabic Characters */
-
- JOINING_TYPE_U, /* 0600; ARABIC NUMBER SIGN; U; No_Joining_Group */
- JOINING_TYPE_U, /* 0601; ARABIC SIGN SANAH; U; No_Joining_Group */
- JOINING_TYPE_U, /* 0602; ARABIC FOOTNOTE MARKER; U; No_Joining_Group */
- JOINING_TYPE_U, /* 0603; ARABIC SIGN SAFHA; U; No_Joining_Group */
- JOINING_TYPE_U, /* 0604; ARABIC SIGN SAMVAT; U; No_Joining_Group */
- JOINING_TYPE_X, /* 0605 */
- JOINING_TYPE_X, /* 0606 */
- JOINING_TYPE_X, /* 0607 */
- JOINING_TYPE_U, /* 0608; ARABIC RAY; U; No_Joining_Group */
- JOINING_TYPE_X, /* 0609 */
- JOINING_TYPE_X, /* 060A */
- JOINING_TYPE_U, /* 060B; AFGHANI SIGN; U; No_Joining_Group */
- JOINING_TYPE_X, /* 060C */
- JOINING_TYPE_X, /* 060D */
- JOINING_TYPE_X, /* 060E */
- JOINING_TYPE_X, /* 060F */
- JOINING_TYPE_X, /* 0610 */
- JOINING_TYPE_X, /* 0611 */
- JOINING_TYPE_X, /* 0612 */
- JOINING_TYPE_X, /* 0613 */
- JOINING_TYPE_X, /* 0614 */
- JOINING_TYPE_X, /* 0615 */
- JOINING_TYPE_X, /* 0616 */
- JOINING_TYPE_X, /* 0617 */
- JOINING_TYPE_X, /* 0618 */
- JOINING_TYPE_X, /* 0619 */
- JOINING_TYPE_X, /* 061A */
- JOINING_TYPE_X, /* 061B */
- JOINING_TYPE_X, /* 061C */
- JOINING_TYPE_X, /* 061D */
- JOINING_TYPE_X, /* 061E */
- JOINING_TYPE_X, /* 061F */
- JOINING_TYPE_D, /* 0620; DOTLESS YEH WITH SEPARATE RING BELOW; D; YEH */
- JOINING_TYPE_U, /* 0621; HAMZA; U; No_Joining_Group */
- JOINING_TYPE_R, /* 0622; ALEF WITH MADDA ABOVE; R; ALEF */
- JOINING_TYPE_R, /* 0623; ALEF WITH HAMZA ABOVE; R; ALEF */
- JOINING_TYPE_R, /* 0624; WAW WITH HAMZA ABOVE; R; WAW */
- JOINING_TYPE_R, /* 0625; ALEF WITH HAMZA BELOW; R; ALEF */
- JOINING_TYPE_D, /* 0626; DOTLESS YEH WITH HAMZA ABOVE; D; YEH */
- JOINING_TYPE_R, /* 0627; ALEF; R; ALEF */
- JOINING_TYPE_D, /* 0628; BEH; D; BEH */
- JOINING_TYPE_R, /* 0629; TEH MARBUTA; R; TEH MARBUTA */
- JOINING_TYPE_D, /* 062A; DOTLESS BEH WITH 2 DOTS ABOVE; D; BEH */
- JOINING_TYPE_D, /* 062B; DOTLESS BEH WITH 3 DOTS ABOVE; D; BEH */
- JOINING_TYPE_D, /* 062C; HAH WITH DOT BELOW; D; HAH */
- JOINING_TYPE_D, /* 062D; HAH; D; HAH */
- JOINING_TYPE_D, /* 062E; HAH WITH DOT ABOVE; D; HAH */
- JOINING_TYPE_R, /* 062F; DAL; R; DAL */
- JOINING_TYPE_R, /* 0630; DAL WITH DOT ABOVE; R; DAL */
- JOINING_TYPE_R, /* 0631; REH; R; REH */
- JOINING_TYPE_R, /* 0632; REH WITH DOT ABOVE; R; REH */
- JOINING_TYPE_D, /* 0633; SEEN; D; SEEN */
- JOINING_TYPE_D, /* 0634; SEEN WITH 3 DOTS ABOVE; D; SEEN */
- JOINING_TYPE_D, /* 0635; SAD; D; SAD */
- JOINING_TYPE_D, /* 0636; SAD WITH DOT ABOVE; D; SAD */
- JOINING_TYPE_D, /* 0637; TAH; D; TAH */
- JOINING_TYPE_D, /* 0638; TAH WITH DOT ABOVE; D; TAH */
- JOINING_TYPE_D, /* 0639; AIN; D; AIN */
- JOINING_TYPE_D, /* 063A; AIN WITH DOT ABOVE; D; AIN */
- JOINING_TYPE_D, /* 063B; KEHEH WITH 2 DOTS ABOVE; D; GAF */
- JOINING_TYPE_D, /* 063C; KEHEH WITH 3 DOTS BELOW; D; GAF */
- JOINING_TYPE_D, /* 063D; FARSI YEH WITH INVERTED V ABOVE; D; FARSI YEH */
- JOINING_TYPE_D, /* 063E; FARSI YEH WITH 2 DOTS ABOVE; D; FARSI YEH */
- JOINING_TYPE_D, /* 063F; FARSI YEH WITH 3 DOTS ABOVE; D; FARSI YEH */
- JOINING_TYPE_C, /* 0640; TATWEEL; C; No_Joining_Group */
- JOINING_TYPE_D, /* 0641; FEH; D; FEH */
- JOINING_TYPE_D, /* 0642; QAF; D; QAF */
- JOINING_TYPE_D, /* 0643; KAF; D; KAF */
- JOINING_TYPE_D, /* 0644; LAM; D; LAM */
- JOINING_TYPE_D, /* 0645; MEEM; D; MEEM */
- JOINING_TYPE_D, /* 0646; NOON; D; NOON */
- JOINING_TYPE_D, /* 0647; HEH; D; HEH */
- JOINING_TYPE_R, /* 0648; WAW; R; WAW */
- JOINING_TYPE_D, /* 0649; DOTLESS YEH; D; YEH */
- JOINING_TYPE_D, /* 064A; YEH; D; YEH */
- JOINING_TYPE_X, /* 064B */
- JOINING_TYPE_X, /* 064C */
- JOINING_TYPE_X, /* 064D */
- JOINING_TYPE_X, /* 064E */
- JOINING_TYPE_X, /* 064F */
- JOINING_TYPE_X, /* 0650 */
- JOINING_TYPE_X, /* 0651 */
- JOINING_TYPE_X, /* 0652 */
- JOINING_TYPE_X, /* 0653 */
- JOINING_TYPE_X, /* 0654 */
- JOINING_TYPE_X, /* 0655 */
- JOINING_TYPE_X, /* 0656 */
- JOINING_TYPE_X, /* 0657 */
- JOINING_TYPE_X, /* 0658 */
- JOINING_TYPE_X, /* 0659 */
- JOINING_TYPE_X, /* 065A */
- JOINING_TYPE_X, /* 065B */
- JOINING_TYPE_X, /* 065C */
- JOINING_TYPE_X, /* 065D */
- JOINING_TYPE_X, /* 065E */
- JOINING_TYPE_X, /* 065F */
- JOINING_TYPE_X, /* 0660 */
- JOINING_TYPE_X, /* 0661 */
- JOINING_TYPE_X, /* 0662 */
- JOINING_TYPE_X, /* 0663 */
- JOINING_TYPE_X, /* 0664 */
- JOINING_TYPE_X, /* 0665 */
- JOINING_TYPE_X, /* 0666 */
- JOINING_TYPE_X, /* 0667 */
- JOINING_TYPE_X, /* 0668 */
- JOINING_TYPE_X, /* 0669 */
- JOINING_TYPE_X, /* 066A */
- JOINING_TYPE_X, /* 066B */
- JOINING_TYPE_X, /* 066C */
- JOINING_TYPE_X, /* 066D */
- JOINING_TYPE_D, /* 066E; DOTLESS BEH; D; BEH */
- JOINING_TYPE_D, /* 066F; DOTLESS QAF; D; QAF */
- JOINING_TYPE_X, /* 0670 */
- JOINING_TYPE_R, /* 0671; ALEF WITH WASLA ABOVE; R; ALEF */
- JOINING_TYPE_R, /* 0672; ALEF WITH WAVY HAMZA ABOVE; R; ALEF */
- JOINING_TYPE_R, /* 0673; ALEF WITH WAVY HAMZA BELOW; R; ALEF */
- JOINING_TYPE_U, /* 0674; HIGH HAMZA; U; No_Joining_Group */
- JOINING_TYPE_R, /* 0675; HIGH HAMZA ALEF; R; ALEF */
- JOINING_TYPE_R, /* 0676; HIGH HAMZA WAW; R; WAW */
- JOINING_TYPE_R, /* 0677; HIGH HAMZA WAW WITH DAMMA ABOVE; R; WAW */
- JOINING_TYPE_D, /* 0678; HIGH HAMZA DOTLESS YEH; D; YEH */
- JOINING_TYPE_D, /* 0679; DOTLESS BEH WITH TAH ABOVE; D; BEH */
- JOINING_TYPE_D, /* 067A; DOTLESS BEH WITH VERTICAL 2 DOTS ABOVE; D; BEH */
- JOINING_TYPE_D, /* 067B; DOTLESS BEH WITH VERTICAL 2 DOTS BELOW; D; BEH */
- JOINING_TYPE_D, /* 067C; DOTLESS BEH WITH ATTACHED RING BELOW AND 2 DOTS ABOVE; D; BEH */
- JOINING_TYPE_D, /* 067D; DOTLESS BEH WITH INVERTED 3 DOTS ABOVE; D; BEH */
- JOINING_TYPE_D, /* 067E; DOTLESS BEH WITH 3 DOTS BELOW; D; BEH */
- JOINING_TYPE_D, /* 067F; DOTLESS BEH WITH 4 DOTS ABOVE; D; BEH */
- JOINING_TYPE_D, /* 0680; DOTLESS BEH WITH 4 DOTS BELOW; D; BEH */
- JOINING_TYPE_D, /* 0681; HAH WITH HAMZA ABOVE; D; HAH */
- JOINING_TYPE_D, /* 0682; HAH WITH VERTICAL 2 DOTS ABOVE; D; HAH */
- JOINING_TYPE_D, /* 0683; HAH WITH 2 DOTS BELOW; D; HAH */
- JOINING_TYPE_D, /* 0684; HAH WITH VERTICAL 2 DOTS BELOW; D; HAH */
- JOINING_TYPE_D, /* 0685; HAH WITH 3 DOTS ABOVE; D; HAH */
- JOINING_TYPE_D, /* 0686; HAH WITH 3 DOTS BELOW; D; HAH */
- JOINING_TYPE_D, /* 0687; HAH WITH 4 DOTS BELOW; D; HAH */
- JOINING_TYPE_R, /* 0688; DAL WITH TAH ABOVE; R; DAL */
- JOINING_TYPE_R, /* 0689; DAL WITH ATTACHED RING BELOW; R; DAL */
- JOINING_TYPE_R, /* 068A; DAL WITH DOT BELOW; R; DAL */
- JOINING_TYPE_R, /* 068B; DAL WITH DOT BELOW AND TAH ABOVE; R; DAL */
- JOINING_TYPE_R, /* 068C; DAL WITH 2 DOTS ABOVE; R; DAL */
- JOINING_TYPE_R, /* 068D; DAL WITH 2 DOTS BELOW; R; DAL */
- JOINING_TYPE_R, /* 068E; DAL WITH 3 DOTS ABOVE; R; DAL */
- JOINING_TYPE_R, /* 068F; DAL WITH INVERTED 3 DOTS ABOVE; R; DAL */
- JOINING_TYPE_R, /* 0690; DAL WITH 4 DOTS ABOVE; R; DAL */
- JOINING_TYPE_R, /* 0691; REH WITH TAH ABOVE; R; REH */
- JOINING_TYPE_R, /* 0692; REH WITH V ABOVE; R; REH */
- JOINING_TYPE_R, /* 0693; REH WITH ATTACHED RING BELOW; R; REH */
- JOINING_TYPE_R, /* 0694; REH WITH DOT BELOW; R; REH */
- JOINING_TYPE_R, /* 0695; REH WITH V BELOW; R; REH */
- JOINING_TYPE_R, /* 0696; REH WITH DOT BELOW AND DOT WITHIN; R; REH */
- JOINING_TYPE_R, /* 0697; REH WITH 2 DOTS ABOVE; R; REH */
- JOINING_TYPE_R, /* 0698; REH WITH 3 DOTS ABOVE; R; REH */
- JOINING_TYPE_R, /* 0699; REH WITH 4 DOTS ABOVE; R; REH */
- JOINING_TYPE_D, /* 069A; SEEN WITH DOT BELOW AND DOT ABOVE; D; SEEN */
- JOINING_TYPE_D, /* 069B; SEEN WITH 3 DOTS BELOW; D; SEEN */
- JOINING_TYPE_D, /* 069C; SEEN WITH 3 DOTS BELOW AND 3 DOTS ABOVE; D; SEEN */
- JOINING_TYPE_D, /* 069D; SAD WITH 2 DOTS BELOW; D; SAD */
- JOINING_TYPE_D, /* 069E; SAD WITH 3 DOTS ABOVE; D; SAD */
- JOINING_TYPE_D, /* 069F; TAH WITH 3 DOTS ABOVE; D; TAH */
- JOINING_TYPE_D, /* 06A0; AIN WITH 3 DOTS ABOVE; D; AIN */
- JOINING_TYPE_D, /* 06A1; DOTLESS FEH; D; FEH */
- JOINING_TYPE_D, /* 06A2; DOTLESS FEH WITH DOT BELOW; D; FEH */
- JOINING_TYPE_D, /* 06A3; FEH WITH DOT BELOW; D; FEH */
- JOINING_TYPE_D, /* 06A4; DOTLESS FEH WITH 3 DOTS ABOVE; D; FEH */
- JOINING_TYPE_D, /* 06A5; DOTLESS FEH WITH 3 DOTS BELOW; D; FEH */
- JOINING_TYPE_D, /* 06A6; DOTLESS FEH WITH 4 DOTS ABOVE; D; FEH */
- JOINING_TYPE_D, /* 06A7; DOTLESS QAF WITH DOT ABOVE; D; QAF */
- JOINING_TYPE_D, /* 06A8; DOTLESS QAF WITH 3 DOTS ABOVE; D; QAF */
- JOINING_TYPE_D, /* 06A9; KEHEH; D; GAF */
- JOINING_TYPE_D, /* 06AA; SWASH KAF; D; SWASH KAF */
- JOINING_TYPE_D, /* 06AB; KEHEH WITH ATTACHED RING BELOW; D; GAF */
- JOINING_TYPE_D, /* 06AC; KAF WITH DOT ABOVE; D; KAF */
- JOINING_TYPE_D, /* 06AD; KAF WITH 3 DOTS ABOVE; D; KAF */
- JOINING_TYPE_D, /* 06AE; KAF WITH 3 DOTS BELOW; D; KAF */
- JOINING_TYPE_D, /* 06AF; GAF; D; GAF */
- JOINING_TYPE_D, /* 06B0; GAF WITH ATTACHED RING BELOW; D; GAF */
- JOINING_TYPE_D, /* 06B1; GAF WITH 2 DOTS ABOVE; D; GAF */
- JOINING_TYPE_D, /* 06B2; GAF WITH 2 DOTS BELOW; D; GAF */
- JOINING_TYPE_D, /* 06B3; GAF WITH VERTICAL 2 DOTS BELOW; D; GAF */
- JOINING_TYPE_D, /* 06B4; GAF WITH 3 DOTS ABOVE; D; GAF */
- JOINING_TYPE_D, /* 06B5; LAM WITH V ABOVE; D; LAM */
- JOINING_TYPE_D, /* 06B6; LAM WITH DOT ABOVE; D; LAM */
- JOINING_TYPE_D, /* 06B7; LAM WITH 3 DOTS ABOVE; D; LAM */
- JOINING_TYPE_D, /* 06B8; LAM WITH 3 DOTS BELOW; D; LAM */
- JOINING_TYPE_D, /* 06B9; NOON WITH DOT BELOW; D; NOON */
- JOINING_TYPE_D, /* 06BA; DOTLESS NOON; D; NOON */
- JOINING_TYPE_D, /* 06BB; DOTLESS NOON WITH TAH ABOVE; D; NOON */
- JOINING_TYPE_D, /* 06BC; NOON WITH ATTACHED RING BELOW; D; NOON */
- JOINING_TYPE_D, /* 06BD; NYA; D; NYA */
- JOINING_TYPE_D, /* 06BE; KNOTTED HEH; D; KNOTTED HEH */
- JOINING_TYPE_D, /* 06BF; HAH WITH 3 DOTS BELOW AND DOT ABOVE; D; HAH */
- JOINING_TYPE_R, /* 06C0; DOTLESS TEH MARBUTA WITH HAMZA ABOVE; R; TEH MARBUTA */
- JOINING_TYPE_D, /* 06C1; HEH GOAL; D; HEH GOAL */
- JOINING_TYPE_D, /* 06C2; HEH GOAL WITH HAMZA ABOVE; D; HEH GOAL */
- JOINING_TYPE_R, /* 06C3; TEH MARBUTA GOAL; R; TEH MARBUTA GOAL */
- JOINING_TYPE_R, /* 06C4; WAW WITH ATTACHED RING WITHIN; R; WAW */
- JOINING_TYPE_R, /* 06C5; WAW WITH BAR; R; WAW */
- JOINING_TYPE_R, /* 06C6; WAW WITH V ABOVE; R; WAW */
- JOINING_TYPE_R, /* 06C7; WAW WITH DAMMA ABOVE; R; WAW */
- JOINING_TYPE_R, /* 06C8; WAW WITH ALEF ABOVE; R; WAW */
- JOINING_TYPE_R, /* 06C9; WAW WITH INVERTED V ABOVE; R; WAW */
- JOINING_TYPE_R, /* 06CA; WAW WITH 2 DOTS ABOVE; R; WAW */
- JOINING_TYPE_R, /* 06CB; WAW WITH 3 DOTS ABOVE; R; WAW */
- JOINING_TYPE_D, /* 06CC; FARSI YEH; D; FARSI YEH */
- JOINING_TYPE_R, /* 06CD; YEH WITH TAIL; R; YEH WITH TAIL */
- JOINING_TYPE_D, /* 06CE; FARSI YEH WITH V ABOVE; D; FARSI YEH */
- JOINING_TYPE_R, /* 06CF; WAW WITH DOT ABOVE; R; WAW */
- JOINING_TYPE_D, /* 06D0; DOTLESS YEH WITH VERTICAL 2 DOTS BELOW; D; YEH */
- JOINING_TYPE_D, /* 06D1; DOTLESS YEH WITH 3 DOTS BELOW; D; YEH */
- JOINING_TYPE_R, /* 06D2; YEH BARREE; R; YEH BARREE */
- JOINING_TYPE_R, /* 06D3; YEH BARREE WITH HAMZA ABOVE; R; YEH BARREE */
- JOINING_TYPE_X, /* 06D4 */
- JOINING_TYPE_R, /* 06D5; DOTLESS TEH MARBUTA; R; TEH MARBUTA */
- JOINING_TYPE_X, /* 06D6 */
- JOINING_TYPE_X, /* 06D7 */
- JOINING_TYPE_X, /* 06D8 */
- JOINING_TYPE_X, /* 06D9 */
- JOINING_TYPE_X, /* 06DA */
- JOINING_TYPE_X, /* 06DB */
- JOINING_TYPE_X, /* 06DC */
- JOINING_TYPE_U, /* 06DD; ARABIC END OF AYAH; U; No_Joining_Group */
- JOINING_TYPE_X, /* 06DE */
- JOINING_TYPE_X, /* 06DF */
- JOINING_TYPE_X, /* 06E0 */
- JOINING_TYPE_X, /* 06E1 */
- JOINING_TYPE_X, /* 06E2 */
- JOINING_TYPE_X, /* 06E3 */
- JOINING_TYPE_X, /* 06E4 */
- JOINING_TYPE_X, /* 06E5 */
- JOINING_TYPE_X, /* 06E6 */
- JOINING_TYPE_X, /* 06E7 */
- JOINING_TYPE_X, /* 06E8 */
- JOINING_TYPE_X, /* 06E9 */
- JOINING_TYPE_X, /* 06EA */
- JOINING_TYPE_X, /* 06EB */
- JOINING_TYPE_X, /* 06EC */
- JOINING_TYPE_X, /* 06ED */
- JOINING_TYPE_R, /* 06EE; DAL WITH INVERTED V ABOVE; R; DAL */
- JOINING_TYPE_R, /* 06EF; REH WITH INVERTED V ABOVE; R; REH */
- JOINING_TYPE_X, /* 06F0 */
- JOINING_TYPE_X, /* 06F1 */
- JOINING_TYPE_X, /* 06F2 */
- JOINING_TYPE_X, /* 06F3 */
- JOINING_TYPE_X, /* 06F4 */
- JOINING_TYPE_X, /* 06F5 */
- JOINING_TYPE_X, /* 06F6 */
- JOINING_TYPE_X, /* 06F7 */
- JOINING_TYPE_X, /* 06F8 */
- JOINING_TYPE_X, /* 06F9 */
- JOINING_TYPE_D, /* 06FA; SEEN WITH DOT BELOW AND 3 DOTS ABOVE; D; SEEN */
- JOINING_TYPE_D, /* 06FB; SAD WITH DOT BELOW AND DOT ABOVE; D; SAD */
- JOINING_TYPE_D, /* 06FC; AIN WITH DOT BELOW AND DOT ABOVE; D; AIN */
- JOINING_TYPE_X, /* 06FD */
- JOINING_TYPE_X, /* 06FE */
- JOINING_TYPE_D, /* 06FF; KNOTTED HEH WITH INVERTED V ABOVE; D; KNOTTED HEH */
-
- /* Syriac Characters */
-
- JOINING_TYPE_X, /* 0700 */
- JOINING_TYPE_X, /* 0701 */
- JOINING_TYPE_X, /* 0702 */
- JOINING_TYPE_X, /* 0703 */
- JOINING_TYPE_X, /* 0704 */
- JOINING_TYPE_X, /* 0705 */
- JOINING_TYPE_X, /* 0706 */
- JOINING_TYPE_X, /* 0707 */
- JOINING_TYPE_X, /* 0708 */
- JOINING_TYPE_X, /* 0709 */
- JOINING_TYPE_X, /* 070A */
- JOINING_TYPE_X, /* 070B */
- JOINING_TYPE_X, /* 070C */
- JOINING_TYPE_X, /* 070D */
- JOINING_TYPE_X, /* 070E */
- JOINING_TYPE_X, /* 070F */
- JOINING_GROUP_ALAPH, /* 0710; ALAPH; R; ALAPH */
- JOINING_TYPE_X, /* 0711 */
- JOINING_TYPE_D, /* 0712; BETH; D; BETH */
- JOINING_TYPE_D, /* 0713; GAMAL; D; GAMAL */
- JOINING_TYPE_D, /* 0714; GAMAL GARSHUNI; D; GAMAL */
- JOINING_GROUP_DALATH_RISH, /* 0715; DALATH; R; DALATH RISH */
- JOINING_GROUP_DALATH_RISH, /* 0716; DOTLESS DALATH RISH; R; DALATH RISH */
- JOINING_TYPE_R, /* 0717; HE; R; HE */
- JOINING_TYPE_R, /* 0718; WAW; R; SYRIAC WAW */
- JOINING_TYPE_R, /* 0719; ZAIN; R; ZAIN */
- JOINING_TYPE_D, /* 071A; HETH; D; HETH */
- JOINING_TYPE_D, /* 071B; TETH; D; TETH */
- JOINING_TYPE_D, /* 071C; TETH GARSHUNI; D; TETH */
- JOINING_TYPE_D, /* 071D; YUDH; D; YUDH */
- JOINING_TYPE_R, /* 071E; YUDH HE; R; YUDH HE */
- JOINING_TYPE_D, /* 071F; KAPH; D; KAPH */
- JOINING_TYPE_D, /* 0720; LAMADH; D; LAMADH */
- JOINING_TYPE_D, /* 0721; MIM; D; MIM */
- JOINING_TYPE_D, /* 0722; NUN; D; NUN */
- JOINING_TYPE_D, /* 0723; SEMKATH; D; SEMKATH */
- JOINING_TYPE_D, /* 0724; FINAL SEMKATH; D; FINAL SEMKATH */
- JOINING_TYPE_D, /* 0725; E; D; E */
- JOINING_TYPE_D, /* 0726; PE; D; PE */
- JOINING_TYPE_D, /* 0727; REVERSED PE; D; REVERSED PE */
- JOINING_TYPE_R, /* 0728; SADHE; R; SADHE */
- JOINING_TYPE_D, /* 0729; QAPH; D; QAPH */
- JOINING_GROUP_DALATH_RISH, /* 072A; RISH; R; DALATH RISH */
- JOINING_TYPE_D, /* 072B; SHIN; D; SHIN */
- JOINING_TYPE_R, /* 072C; TAW; R; TAW */
- JOINING_TYPE_D, /* 072D; PERSIAN BHETH; D; BETH */
- JOINING_TYPE_D, /* 072E; PERSIAN GHAMAL; D; GAMAL */
- JOINING_GROUP_DALATH_RISH, /* 072F; PERSIAN DHALATH; R; DALATH RISH */
- JOINING_TYPE_X, /* 0730 */
- JOINING_TYPE_X, /* 0731 */
- JOINING_TYPE_X, /* 0732 */
- JOINING_TYPE_X, /* 0733 */
- JOINING_TYPE_X, /* 0734 */
- JOINING_TYPE_X, /* 0735 */
- JOINING_TYPE_X, /* 0736 */
- JOINING_TYPE_X, /* 0737 */
- JOINING_TYPE_X, /* 0738 */
- JOINING_TYPE_X, /* 0739 */
- JOINING_TYPE_X, /* 073A */
- JOINING_TYPE_X, /* 073B */
- JOINING_TYPE_X, /* 073C */
- JOINING_TYPE_X, /* 073D */
- JOINING_TYPE_X, /* 073E */
- JOINING_TYPE_X, /* 073F */
- JOINING_TYPE_X, /* 0740 */
- JOINING_TYPE_X, /* 0741 */
- JOINING_TYPE_X, /* 0742 */
- JOINING_TYPE_X, /* 0743 */
- JOINING_TYPE_X, /* 0744 */
- JOINING_TYPE_X, /* 0745 */
- JOINING_TYPE_X, /* 0746 */
- JOINING_TYPE_X, /* 0747 */
- JOINING_TYPE_X, /* 0748 */
- JOINING_TYPE_X, /* 0749 */
- JOINING_TYPE_X, /* 074A */
- JOINING_TYPE_X, /* 074B */
- JOINING_TYPE_X, /* 074C */
- JOINING_TYPE_R, /* 074D; SOGDIAN ZHAIN; R; ZHAIN */
- JOINING_TYPE_D, /* 074E; SOGDIAN KHAPH; D; KHAPH */
- JOINING_TYPE_D, /* 074F; SOGDIAN FE; D; FE */
-
- /* Arabic Supplement Characters */
-
- JOINING_TYPE_D, /* 0750; DOTLESS BEH WITH HORIZONTAL 3 DOTS BELOW; D; BEH */
- JOINING_TYPE_D, /* 0751; BEH WITH 3 DOTS ABOVE; D; BEH */
- JOINING_TYPE_D, /* 0752; DOTLESS BEH WITH INVERTED 3 DOTS BELOW; D; BEH */
- JOINING_TYPE_D, /* 0753; DOTLESS BEH WITH INVERTED 3 DOTS BELOW AND 2 DOTS ABOVE; D; BEH */
- JOINING_TYPE_D, /* 0754; DOTLESS BEH WITH 2 DOTS BELOW AND DOT ABOVE; D; BEH */
- JOINING_TYPE_D, /* 0755; DOTLESS BEH WITH INVERTED V BELOW; D; BEH */
- JOINING_TYPE_D, /* 0756; DOTLESS BEH WITH V ABOVE; D; BEH */
- JOINING_TYPE_D, /* 0757; HAH WITH 2 DOTS ABOVE; D; HAH */
- JOINING_TYPE_D, /* 0758; HAH WITH INVERTED 3 DOTS BELOW; D; HAH */
- JOINING_TYPE_R, /* 0759; DAL WITH VERTICAL 2 DOTS BELOW AND TAH ABOVE; R; DAL */
- JOINING_TYPE_R, /* 075A; DAL WITH INVERTED V BELOW; R; DAL */
- JOINING_TYPE_R, /* 075B; REH WITH BAR; R; REH */
- JOINING_TYPE_D, /* 075C; SEEN WITH 4 DOTS ABOVE; D; SEEN */
- JOINING_TYPE_D, /* 075D; AIN WITH 2 DOTS ABOVE; D; AIN */
- JOINING_TYPE_D, /* 075E; AIN WITH INVERTED 3 DOTS ABOVE; D; AIN */
- JOINING_TYPE_D, /* 075F; AIN WITH VERTICAL 2 DOTS ABOVE; D; AIN */
- JOINING_TYPE_D, /* 0760; DOTLESS FEH WITH 2 DOTS BELOW; D; FEH */
- JOINING_TYPE_D, /* 0761; DOTLESS FEH WITH INVERTED 3 DOTS BELOW; D; FEH */
- JOINING_TYPE_D, /* 0762; KEHEH WITH DOT ABOVE; D; GAF */
- JOINING_TYPE_D, /* 0763; KEHEH WITH 3 DOTS ABOVE; D; GAF */
- JOINING_TYPE_D, /* 0764; KEHEH WITH INVERTED 3 DOTS BELOW; D; GAF */
- JOINING_TYPE_D, /* 0765; MEEM WITH DOT ABOVE; D; MEEM */
- JOINING_TYPE_D, /* 0766; MEEM WITH DOT BELOW; D; MEEM */
- JOINING_TYPE_D, /* 0767; NOON WITH 2 DOTS BELOW; D; NOON */
- JOINING_TYPE_D, /* 0768; NOON WITH TAH ABOVE; D; NOON */
- JOINING_TYPE_D, /* 0769; NOON WITH V ABOVE; D; NOON */
- JOINING_TYPE_D, /* 076A; LAM WITH BAR; D; LAM */
- JOINING_TYPE_R, /* 076B; REH WITH VERTICAL 2 DOTS ABOVE; R; REH */
- JOINING_TYPE_R, /* 076C; REH WITH HAMZA ABOVE; R; REH */
- JOINING_TYPE_D, /* 076D; SEEN WITH VERTICAL 2 DOTS ABOVE; D; SEEN */
- JOINING_TYPE_D, /* 076E; HAH WITH TAH BELOW; D; HAH */
- JOINING_TYPE_D, /* 076F; HAH WITH TAH AND 2 DOTS BELOW; D; HAH */
- JOINING_TYPE_D, /* 0770; SEEN WITH 2 DOTS AND TAH ABOVE; D; SEEN */
- JOINING_TYPE_R, /* 0771; REH WITH 2 DOTS AND TAH ABOVE; R; REH */
- JOINING_TYPE_D, /* 0772; HAH WITH TAH ABOVE; D; HAH */
- JOINING_TYPE_R, /* 0773; ALEF WITH DIGIT TWO ABOVE; R; ALEF */
- JOINING_TYPE_R, /* 0774; ALEF WITH DIGIT THREE ABOVE; R; ALEF */
- JOINING_TYPE_D, /* 0775; FARSI YEH WITH DIGIT TWO ABOVE; D; FARSI YEH */
- JOINING_TYPE_D, /* 0776; FARSI YEH WITH DIGIT THREE ABOVE; D; FARSI YEH */
- JOINING_TYPE_D, /* 0777; DOTLESS YEH WITH DIGIT FOUR BELOW; D; YEH */
- JOINING_TYPE_R, /* 0778; WAW WITH DIGIT TWO ABOVE; R; WAW */
- JOINING_TYPE_R, /* 0779; WAW WITH DIGIT THREE ABOVE; R; WAW */
- JOINING_TYPE_D, /* 077A; BURUSHASKI YEH BARREE WITH DIGIT TWO ABOVE; D; BURUSHASKI YEH BARREE */
- JOINING_TYPE_D, /* 077B; BURUSHASKI YEH BARREE WITH DIGIT THREE ABOVE; D; BURUSHASKI YEH BARREE */
- JOINING_TYPE_D, /* 077C; HAH WITH DIGIT FOUR BELOW; D; HAH */
- JOINING_TYPE_D, /* 077D; SEEN WITH DIGIT FOUR ABOVE; D; SEEN */
- JOINING_TYPE_D, /* 077E; SEEN WITH INVERTED V ABOVE; D; SEEN */
- JOINING_TYPE_D, /* 077F; KAF WITH 2 DOTS ABOVE; D; KAF */
-
- /* N'Ko Characters */
-
- JOINING_TYPE_X, /* 0780 */
- JOINING_TYPE_X, /* 0781 */
- JOINING_TYPE_X, /* 0782 */
- JOINING_TYPE_X, /* 0783 */
- JOINING_TYPE_X, /* 0784 */
- JOINING_TYPE_X, /* 0785 */
- JOINING_TYPE_X, /* 0786 */
- JOINING_TYPE_X, /* 0787 */
- JOINING_TYPE_X, /* 0788 */
- JOINING_TYPE_X, /* 0789 */
- JOINING_TYPE_X, /* 078A */
- JOINING_TYPE_X, /* 078B */
- JOINING_TYPE_X, /* 078C */
- JOINING_TYPE_X, /* 078D */
- JOINING_TYPE_X, /* 078E */
- JOINING_TYPE_X, /* 078F */
- JOINING_TYPE_X, /* 0790 */
- JOINING_TYPE_X, /* 0791 */
- JOINING_TYPE_X, /* 0792 */
- JOINING_TYPE_X, /* 0793 */
- JOINING_TYPE_X, /* 0794 */
- JOINING_TYPE_X, /* 0795 */
- JOINING_TYPE_X, /* 0796 */
- JOINING_TYPE_X, /* 0797 */
- JOINING_TYPE_X, /* 0798 */
- JOINING_TYPE_X, /* 0799 */
- JOINING_TYPE_X, /* 079A */
- JOINING_TYPE_X, /* 079B */
- JOINING_TYPE_X, /* 079C */
- JOINING_TYPE_X, /* 079D */
- JOINING_TYPE_X, /* 079E */
- JOINING_TYPE_X, /* 079F */
- JOINING_TYPE_X, /* 07A0 */
- JOINING_TYPE_X, /* 07A1 */
- JOINING_TYPE_X, /* 07A2 */
- JOINING_TYPE_X, /* 07A3 */
- JOINING_TYPE_X, /* 07A4 */
- JOINING_TYPE_X, /* 07A5 */
- JOINING_TYPE_X, /* 07A6 */
- JOINING_TYPE_X, /* 07A7 */
- JOINING_TYPE_X, /* 07A8 */
- JOINING_TYPE_X, /* 07A9 */
- JOINING_TYPE_X, /* 07AA */
- JOINING_TYPE_X, /* 07AB */
- JOINING_TYPE_X, /* 07AC */
- JOINING_TYPE_X, /* 07AD */
- JOINING_TYPE_X, /* 07AE */
- JOINING_TYPE_X, /* 07AF */
- JOINING_TYPE_X, /* 07B0 */
- JOINING_TYPE_X, /* 07B1 */
- JOINING_TYPE_X, /* 07B2 */
- JOINING_TYPE_X, /* 07B3 */
- JOINING_TYPE_X, /* 07B4 */
- JOINING_TYPE_X, /* 07B5 */
- JOINING_TYPE_X, /* 07B6 */
- JOINING_TYPE_X, /* 07B7 */
- JOINING_TYPE_X, /* 07B8 */
- JOINING_TYPE_X, /* 07B9 */
- JOINING_TYPE_X, /* 07BA */
- JOINING_TYPE_X, /* 07BB */
- JOINING_TYPE_X, /* 07BC */
- JOINING_TYPE_X, /* 07BD */
- JOINING_TYPE_X, /* 07BE */
- JOINING_TYPE_X, /* 07BF */
- JOINING_TYPE_X, /* 07C0 */
- JOINING_TYPE_X, /* 07C1 */
- JOINING_TYPE_X, /* 07C2 */
- JOINING_TYPE_X, /* 07C3 */
- JOINING_TYPE_X, /* 07C4 */
- JOINING_TYPE_X, /* 07C5 */
- JOINING_TYPE_X, /* 07C6 */
- JOINING_TYPE_X, /* 07C7 */
- JOINING_TYPE_X, /* 07C8 */
- JOINING_TYPE_X, /* 07C9 */
- JOINING_TYPE_D, /* 07CA; NKO A; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07CB; NKO EE; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07CC; NKO I; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07CD; NKO E; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07CE; NKO U; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07CF; NKO OO; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07D0; NKO O; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07D1; NKO DAGBASINNA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07D2; NKO N; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07D3; NKO BA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07D4; NKO PA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07D5; NKO TA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07D6; NKO JA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07D7; NKO CHA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07D8; NKO DA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07D9; NKO RA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07DA; NKO RRA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07DB; NKO SA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07DC; NKO GBA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07DD; NKO FA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07DE; NKO KA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07DF; NKO LA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07E0; NKO NA WOLOSO; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07E1; NKO MA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07E2; NKO NYA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07E3; NKO NA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07E4; NKO HA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07E5; NKO WA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07E6; NKO YA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07E7; NKO NYA WOLOSO; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07E8; NKO JONA JA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07E9; NKO JONA CHA; D; No_Joining_Group */
- JOINING_TYPE_D, /* 07EA; NKO JONA RA; D; No_Joining_Group */
- JOINING_TYPE_X, /* 07EB */
- JOINING_TYPE_X, /* 07EC */
- JOINING_TYPE_X, /* 07ED */
- JOINING_TYPE_X, /* 07EE */
- JOINING_TYPE_X, /* 07EF */
- JOINING_TYPE_X, /* 07F0 */
- JOINING_TYPE_X, /* 07F1 */
- JOINING_TYPE_X, /* 07F2 */
- JOINING_TYPE_X, /* 07F3 */
- JOINING_TYPE_X, /* 07F4 */
- JOINING_TYPE_X, /* 07F5 */
- JOINING_TYPE_X, /* 07F6 */
- JOINING_TYPE_X, /* 07F7 */
- JOINING_TYPE_X, /* 07F8 */
- JOINING_TYPE_X, /* 07F9 */
- JOINING_TYPE_C, /* 07FA; NKO LAJANYALAN; C; No_Joining_Group */
-
- /* Mandaic Characters */
-
- JOINING_TYPE_X, /* 07FB */
- JOINING_TYPE_X, /* 07FC */
- JOINING_TYPE_X, /* 07FD */
- JOINING_TYPE_X, /* 07FE */
- JOINING_TYPE_X, /* 07FF */
- JOINING_TYPE_X, /* 0800 */
- JOINING_TYPE_X, /* 0801 */
- JOINING_TYPE_X, /* 0802 */
- JOINING_TYPE_X, /* 0803 */
- JOINING_TYPE_X, /* 0804 */
- JOINING_TYPE_X, /* 0805 */
- JOINING_TYPE_X, /* 0806 */
- JOINING_TYPE_X, /* 0807 */
- JOINING_TYPE_X, /* 0808 */
- JOINING_TYPE_X, /* 0809 */
- JOINING_TYPE_X, /* 080A */
- JOINING_TYPE_X, /* 080B */
- JOINING_TYPE_X, /* 080C */
- JOINING_TYPE_X, /* 080D */
- JOINING_TYPE_X, /* 080E */
- JOINING_TYPE_X, /* 080F */
- JOINING_TYPE_X, /* 0810 */
- JOINING_TYPE_X, /* 0811 */
- JOINING_TYPE_X, /* 0812 */
- JOINING_TYPE_X, /* 0813 */
- JOINING_TYPE_X, /* 0814 */
- JOINING_TYPE_X, /* 0815 */
- JOINING_TYPE_X, /* 0816 */
- JOINING_TYPE_X, /* 0817 */
- JOINING_TYPE_X, /* 0818 */
- JOINING_TYPE_X, /* 0819 */
- JOINING_TYPE_X, /* 081A */
- JOINING_TYPE_X, /* 081B */
- JOINING_TYPE_X, /* 081C */
- JOINING_TYPE_X, /* 081D */
- JOINING_TYPE_X, /* 081E */
- JOINING_TYPE_X, /* 081F */
- JOINING_TYPE_X, /* 0820 */
- JOINING_TYPE_X, /* 0821 */
- JOINING_TYPE_X, /* 0822 */
- JOINING_TYPE_X, /* 0823 */
- JOINING_TYPE_X, /* 0824 */
- JOINING_TYPE_X, /* 0825 */
- JOINING_TYPE_X, /* 0826 */
- JOINING_TYPE_X, /* 0827 */
- JOINING_TYPE_X, /* 0828 */
- JOINING_TYPE_X, /* 0829 */
- JOINING_TYPE_X, /* 082A */
- JOINING_TYPE_X, /* 082B */
- JOINING_TYPE_X, /* 082C */
- JOINING_TYPE_X, /* 082D */
- JOINING_TYPE_X, /* 082E */
- JOINING_TYPE_X, /* 082F */
- JOINING_TYPE_X, /* 0830 */
- JOINING_TYPE_X, /* 0831 */
- JOINING_TYPE_X, /* 0832 */
- JOINING_TYPE_X, /* 0833 */
- JOINING_TYPE_X, /* 0834 */
- JOINING_TYPE_X, /* 0835 */
- JOINING_TYPE_X, /* 0836 */
- JOINING_TYPE_X, /* 0837 */
- JOINING_TYPE_X, /* 0838 */
- JOINING_TYPE_X, /* 0839 */
- JOINING_TYPE_X, /* 083A */
- JOINING_TYPE_X, /* 083B */
- JOINING_TYPE_X, /* 083C */
- JOINING_TYPE_X, /* 083D */
- JOINING_TYPE_X, /* 083E */
- JOINING_TYPE_X, /* 083F */
- JOINING_TYPE_R, /* 0840; MANDAIC HALQA; R; No_Joining_Group */
- JOINING_TYPE_D, /* 0841; MANDAIC AB; D; No_Joining_Group */
- JOINING_TYPE_D, /* 0842; MANDAIC AG; D; No_Joining_Group */
- JOINING_TYPE_D, /* 0843; MANDAIC AD; D; No_Joining_Group */
- JOINING_TYPE_D, /* 0844; MANDAIC AH; D; No_Joining_Group */
- JOINING_TYPE_D, /* 0845; MANDAIC USHENNA; D; No_Joining_Group */
- JOINING_TYPE_R, /* 0846; MANDAIC AZ; R; No_Joining_Group */
- JOINING_TYPE_D, /* 0847; MANDAIC IT; D; No_Joining_Group */
- JOINING_TYPE_D, /* 0848; MANDAIC ATT; D; No_Joining_Group */
- JOINING_TYPE_R, /* 0849; MANDAIC AKSA; R; No_Joining_Group */
- JOINING_TYPE_D, /* 084A; MANDAIC AK; D; No_Joining_Group */
- JOINING_TYPE_D, /* 084B; MANDAIC AL; D; No_Joining_Group */
- JOINING_TYPE_D, /* 084C; MANDAIC AM; D; No_Joining_Group */
- JOINING_TYPE_D, /* 084D; MANDAIC AN; D; No_Joining_Group */
- JOINING_TYPE_D, /* 084E; MANDAIC AS; D; No_Joining_Group */
- JOINING_TYPE_R, /* 084F; MANDAIC IN; R; No_Joining_Group */
- JOINING_TYPE_D, /* 0850; MANDAIC AP; D; No_Joining_Group */
- JOINING_TYPE_D, /* 0851; MANDAIC ASZ; D; No_Joining_Group */
- JOINING_TYPE_D, /* 0852; MANDAIC AQ; D; No_Joining_Group */
- JOINING_TYPE_D, /* 0853; MANDAIC AR; D; No_Joining_Group */
- JOINING_TYPE_R, /* 0854; MANDAIC ASH; R; No_Joining_Group */
- JOINING_TYPE_D, /* 0855; MANDAIC AT; D; No_Joining_Group */
- JOINING_TYPE_U, /* 0856; MANDAIC DUSHENNA; U; No_Joining_Group */
- JOINING_TYPE_U, /* 0857; MANDAIC KAD; U; No_Joining_Group */
- JOINING_TYPE_U, /* 0858; MANDAIC AIN; U; No_Joining_Group */
-
- /* Arabic Extended-A Characters */
-
- JOINING_TYPE_X, /* 0859 */
- JOINING_TYPE_X, /* 085A */
- JOINING_TYPE_X, /* 085B */
- JOINING_TYPE_X, /* 085C */
- JOINING_TYPE_X, /* 085D */
- JOINING_TYPE_X, /* 085E */
- JOINING_TYPE_X, /* 085F */
- JOINING_TYPE_X, /* 0860 */
- JOINING_TYPE_X, /* 0861 */
- JOINING_TYPE_X, /* 0862 */
- JOINING_TYPE_X, /* 0863 */
- JOINING_TYPE_X, /* 0864 */
- JOINING_TYPE_X, /* 0865 */
- JOINING_TYPE_X, /* 0866 */
- JOINING_TYPE_X, /* 0867 */
- JOINING_TYPE_X, /* 0868 */
- JOINING_TYPE_X, /* 0869 */
- JOINING_TYPE_X, /* 086A */
- JOINING_TYPE_X, /* 086B */
- JOINING_TYPE_X, /* 086C */
- JOINING_TYPE_X, /* 086D */
- JOINING_TYPE_X, /* 086E */
- JOINING_TYPE_X, /* 086F */
- JOINING_TYPE_X, /* 0870 */
- JOINING_TYPE_X, /* 0871 */
- JOINING_TYPE_X, /* 0872 */
- JOINING_TYPE_X, /* 0873 */
- JOINING_TYPE_X, /* 0874 */
- JOINING_TYPE_X, /* 0875 */
- JOINING_TYPE_X, /* 0876 */
- JOINING_TYPE_X, /* 0877 */
- JOINING_TYPE_X, /* 0878 */
- JOINING_TYPE_X, /* 0879 */
- JOINING_TYPE_X, /* 087A */
- JOINING_TYPE_X, /* 087B */
- JOINING_TYPE_X, /* 087C */
- JOINING_TYPE_X, /* 087D */
- JOINING_TYPE_X, /* 087E */
- JOINING_TYPE_X, /* 087F */
- JOINING_TYPE_X, /* 0880 */
- JOINING_TYPE_X, /* 0881 */
- JOINING_TYPE_X, /* 0882 */
- JOINING_TYPE_X, /* 0883 */
- JOINING_TYPE_X, /* 0884 */
- JOINING_TYPE_X, /* 0885 */
- JOINING_TYPE_X, /* 0886 */
- JOINING_TYPE_X, /* 0887 */
- JOINING_TYPE_X, /* 0888 */
- JOINING_TYPE_X, /* 0889 */
- JOINING_TYPE_X, /* 088A */
- JOINING_TYPE_X, /* 088B */
- JOINING_TYPE_X, /* 088C */
- JOINING_TYPE_X, /* 088D */
- JOINING_TYPE_X, /* 088E */
- JOINING_TYPE_X, /* 088F */
- JOINING_TYPE_X, /* 0890 */
- JOINING_TYPE_X, /* 0891 */
- JOINING_TYPE_X, /* 0892 */
- JOINING_TYPE_X, /* 0893 */
- JOINING_TYPE_X, /* 0894 */
- JOINING_TYPE_X, /* 0895 */
- JOINING_TYPE_X, /* 0896 */
- JOINING_TYPE_X, /* 0897 */
- JOINING_TYPE_X, /* 0898 */
- JOINING_TYPE_X, /* 0899 */
- JOINING_TYPE_X, /* 089A */
- JOINING_TYPE_X, /* 089B */
- JOINING_TYPE_X, /* 089C */
- JOINING_TYPE_X, /* 089D */
- JOINING_TYPE_X, /* 089E */
- JOINING_TYPE_X, /* 089F */
- JOINING_TYPE_D, /* 08A0; DOTLESS BEH WITH V BELOW; D; BEH */
- JOINING_TYPE_X, /* 08A1 */
- JOINING_TYPE_D, /* 08A2; HAH WITH DOT BELOW AND 2 DOTS ABOVE; D; HAH */
- JOINING_TYPE_D, /* 08A3; TAH WITH 2 DOTS ABOVE; D; TAH */
- JOINING_TYPE_D, /* 08A4; DOTLESS FEH WITH DOT BELOW AND 3 DOTS ABOVE; D; FEH */
- JOINING_TYPE_D, /* 08A5; QAF WITH DOT BELOW; D; QAF */
- JOINING_TYPE_D, /* 08A6; LAM WITH DOUBLE BAR; D; LAM */
- JOINING_TYPE_D, /* 08A7; MEEM WITH 3 DOTS ABOVE; D; MEEM */
- JOINING_TYPE_D, /* 08A8; YEH WITH HAMZA ABOVE; D; YEH */
- JOINING_TYPE_D, /* 08A9; YEH WITH DOT ABOVE; D; YEH */
- JOINING_TYPE_R, /* 08AA; REH WITH LOOP; R; REH */
- JOINING_TYPE_R, /* 08AB; WAW WITH DOT WITHIN; R; WAW */
- JOINING_TYPE_R, /* 08AC; ROHINGYA YEH; R; ROHINGYA YEH */
+#define joining_offset_0x0600u 0
-};
+ /* Arabic */
+
+ /* 0600 */ U,U,U,U,U,U,X,X,U,X,X,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+ /* 0620 */ D,U,R,R,R,R,D,R,D,R,D,D,D,D,D,R,R,R,R,D,D,D,D,D,D,D,D,D,D,D,D,D,
+ /* 0640 */ C,D,D,D,D,D,D,D,R,D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+ /* 0660 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,D,D,X,R,R,R,U,R,R,R,D,D,D,D,D,D,D,D,
+ /* 0680 */ D,D,D,D,D,D,D,D,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,D,D,D,D,D,D,
+ /* 06A0 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+ /* 06C0 */ R,D,D,R,R,R,R,R,R,R,R,R,D,R,D,R,D,D,R,R,X,R,X,X,X,X,X,X,X,U,X,X,
+ /* 06E0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,R,R,X,X,X,X,X,X,X,X,X,X,D,D,D,X,X,D,
+
+ /* Syriac */
+
+ /* 0700 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,A,X,D,D,D,DR,DR,R,R,R,D,D,D,D,R,D,
+ /* 0720 */ D,D,D,D,D,D,D,D,R,D,DR,D,R,D,D,DR,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+ /* 0740 */ X,X,X,X,X,X,X,X,X,X,X,X,X,R,D,D,
+
+ /* Arabic Supplement */
+
+ /* 0740 */ D,D,D,D,D,D,D,D,D,R,R,R,D,D,D,D,
+ /* 0760 */ D,D,D,D,D,D,D,D,D,D,D,R,R,D,D,D,D,R,D,R,R,D,D,D,R,R,D,D,D,D,D,D,
+
+ /* FILLER */
+
+ /* 0780 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+ /* 07A0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+
+ /* NKo */
+
+ /* 07C0 */ X,X,X,X,X,X,X,X,X,X,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+ /* 07E0 */ D,D,D,D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,C,X,X,X,X,X,
+
+ /* FILLER */
+
+ /* 0800 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+ /* 0820 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+
+ /* Mandaic */
+
+ /* 0840 */ R,D,D,D,D,D,R,D,D,R,D,D,D,D,D,R,D,D,D,D,R,D,U,U,U,X,X,X,X,X,X,X,
+ /* 0860 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+ /* 0880 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+
+ /* Arabic Extended-A */
+
+ /* 08A0 */ D,D,D,D,D,D,D,D,D,D,R,R,R,U,R,D,D,R,R,
+
+#define joining_offset_0x1806u 691
+
+ /* Mongolian */
+
+ /* 1800 */ U,D,X,X,C,X,X,X,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+ /* 1820 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+ /* 1840 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+ /* 1860 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,X,
+ /* 1880 */ U,U,U,U,U,U,U,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+ /* 18A0 */ D,D,D,D,D,D,D,D,D,X,D,
+
+#define joining_offset_0x200cu 856
+
+ /* General Punctuation */
+
+ /* 2000 */ U,C,
+
+#define joining_offset_0x2066u 858
+
+ /* General Punctuation */
+
+ /* 2060 */ U,U,U,U,
+
+#define joining_offset_0xa840u 862
+
+ /* Phags-pa */
+
+ /* A840 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+ /* A860 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,L,U,
+
+#define joining_offset_0x10ac0u 914
+
+ /* Manichaean */
+
+ /* 10AC0 */ D,D,D,D,D,R,U,R,U,R,R,U,U,L,R,R,R,R,R,D,D,D,D,L,D,D,D,D,D,R,D,D,
+ /* 10AE0 */ D,R,U,U,R,X,X,X,X,X,X,D,D,D,D,R,
+
+#define joining_offset_0x10b80u 962
+
+ /* Psalter Pahlavi */
+
+ /* 10B80 */ D,R,D,R,R,R,D,D,D,R,D,D,R,D,R,R,D,R,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+ /* 10BA0 */ X,X,X,X,X,X,X,X,X,R,R,R,R,D,D,U,
+
+}; /* Table items: 1010; occupancy: 57% */
+
+
+static unsigned int
+joining_type (hb_codepoint_t u)
+{
+ switch (u >> 12)
+ {
+ case 0x0u:
+ if (hb_in_range (u, 0x0600u, 0x08B2u)) return joining_table[u - 0x0600u + joining_offset_0x0600u];
+ break;
+
+ case 0x1u:
+ if (hb_in_range (u, 0x1806u, 0x18AAu)) return joining_table[u - 0x1806u + joining_offset_0x1806u];
+ break;
+
+ case 0x2u:
+ if (hb_in_range (u, 0x200Cu, 0x200Du)) return joining_table[u - 0x200Cu + joining_offset_0x200cu];
+ if (hb_in_range (u, 0x2066u, 0x2069u)) return joining_table[u - 0x2066u + joining_offset_0x2066u];
+ break;
+
+ case 0xAu:
+ if (hb_in_range (u, 0xA840u, 0xA873u)) return joining_table[u - 0xA840u + joining_offset_0xa840u];
+ break;
+
+ case 0x10u:
+ if (hb_in_range (u, 0x10AC0u, 0x10AEFu)) return joining_table[u - 0x10AC0u + joining_offset_0x10ac0u];
+ if (hb_in_range (u, 0x10B80u, 0x10BAFu)) return joining_table[u - 0x10B80u + joining_offset_0x10b80u];
+ break;
+
+ default:
+ break;
+ }
+ return X;
+}
-#define JOINING_TABLE_FIRST 0x0600
-#define JOINING_TABLE_LAST 0x08AC
+#undef X
+#undef R
+#undef U
+#undef A
+#undef DR
+#undef L
+#undef C
+#undef D
static const uint16_t shaping_table[][4] =
{
- {0x0000, 0x0000, 0x0000, 0xFE80}, /* U+0621 ARABIC LETTER HAMZA ISOLATED FORM */
- {0x0000, 0x0000, 0xFE82, 0xFE81}, /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */
- {0x0000, 0x0000, 0xFE84, 0xFE83}, /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */
- {0x0000, 0x0000, 0xFE86, 0xFE85}, /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */
- {0x0000, 0x0000, 0xFE88, 0xFE87}, /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */
- {0xFE8B, 0xFE8C, 0xFE8A, 0xFE89}, /* U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE */
- {0x0000, 0x0000, 0xFE8E, 0xFE8D}, /* U+0627 ARABIC LETTER ALEF */
- {0xFE91, 0xFE92, 0xFE90, 0xFE8F}, /* U+0628 ARABIC LETTER BEH */
- {0x0000, 0x0000, 0xFE94, 0xFE93}, /* U+0629 ARABIC LETTER TEH MARBUTA */
- {0xFE97, 0xFE98, 0xFE96, 0xFE95}, /* U+062A ARABIC LETTER TEH */
- {0xFE9B, 0xFE9C, 0xFE9A, 0xFE99}, /* U+062B ARABIC LETTER THEH */
- {0xFE9F, 0xFEA0, 0xFE9E, 0xFE9D}, /* U+062C ARABIC LETTER JEEM */
- {0xFEA3, 0xFEA4, 0xFEA2, 0xFEA1}, /* U+062D ARABIC LETTER HAH */
- {0xFEA7, 0xFEA8, 0xFEA6, 0xFEA5}, /* U+062E ARABIC LETTER KHAH */
- {0x0000, 0x0000, 0xFEAA, 0xFEA9}, /* U+062F ARABIC LETTER DAL */
- {0x0000, 0x0000, 0xFEAC, 0xFEAB}, /* U+0630 ARABIC LETTER THAL */
- {0x0000, 0x0000, 0xFEAE, 0xFEAD}, /* U+0631 ARABIC LETTER REH */
- {0x0000, 0x0000, 0xFEB0, 0xFEAF}, /* U+0632 ARABIC LETTER ZAIN */
- {0xFEB3, 0xFEB4, 0xFEB2, 0xFEB1}, /* U+0633 ARABIC LETTER SEEN */
- {0xFEB7, 0xFEB8, 0xFEB6, 0xFEB5}, /* U+0634 ARABIC LETTER SHEEN */
- {0xFEBB, 0xFEBC, 0xFEBA, 0xFEB9}, /* U+0635 ARABIC LETTER SAD */
- {0xFEBF, 0xFEC0, 0xFEBE, 0xFEBD}, /* U+0636 ARABIC LETTER DAD */
- {0xFEC3, 0xFEC4, 0xFEC2, 0xFEC1}, /* U+0637 ARABIC LETTER TAH */
- {0xFEC7, 0xFEC8, 0xFEC6, 0xFEC5}, /* U+0638 ARABIC LETTER ZAH */
- {0xFECB, 0xFECC, 0xFECA, 0xFEC9}, /* U+0639 ARABIC LETTER AIN */
- {0xFECF, 0xFED0, 0xFECE, 0xFECD}, /* U+063A ARABIC LETTER GHAIN */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+063B */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+063C */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+063D */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+063E */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+063F */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0640 */
- {0xFED3, 0xFED4, 0xFED2, 0xFED1}, /* U+0641 ARABIC LETTER FEH */
- {0xFED7, 0xFED8, 0xFED6, 0xFED5}, /* U+0642 ARABIC LETTER QAF */
- {0xFEDB, 0xFEDC, 0xFEDA, 0xFED9}, /* U+0643 ARABIC LETTER KAF */
- {0xFEDF, 0xFEE0, 0xFEDE, 0xFEDD}, /* U+0644 ARABIC LETTER LAM */
- {0xFEE3, 0xFEE4, 0xFEE2, 0xFEE1}, /* U+0645 ARABIC LETTER MEEM */
- {0xFEE7, 0xFEE8, 0xFEE6, 0xFEE5}, /* U+0646 ARABIC LETTER NOON */
- {0xFEEB, 0xFEEC, 0xFEEA, 0xFEE9}, /* U+0647 ARABIC LETTER HEH */
- {0x0000, 0x0000, 0xFEEE, 0xFEED}, /* U+0648 ARABIC LETTER WAW */
- {0xFBE8, 0xFBE9, 0xFEF0, 0xFEEF}, /* U+0649 ARABIC LETTER */
- {0xFEF3, 0xFEF4, 0xFEF2, 0xFEF1}, /* U+064A ARABIC LETTER YEH */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+064B */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+064C */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+064D */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+064E */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+064F */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0650 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0651 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0652 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0653 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0654 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0655 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0656 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0657 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0658 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0659 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+065A */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+065B */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+065C */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+065D */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+065E */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+065F */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0660 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0661 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0662 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0663 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0664 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0665 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0666 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0667 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0668 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0669 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+066A */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+066B */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+066C */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+066D */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+066E */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+066F */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0670 */
- {0x0000, 0x0000, 0xFB51, 0xFB50}, /* U+0671 ARABIC LETTER ALEF WASLA */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0672 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0673 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0674 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0675 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0676 */
- {0x0000, 0x0000, 0x0000, 0xFBDD}, /* U+0677 ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0678 */
- {0xFB68, 0xFB69, 0xFB67, 0xFB66}, /* U+0679 ARABIC LETTER TTEH */
- {0xFB60, 0xFB61, 0xFB5F, 0xFB5E}, /* U+067A ARABIC LETTER TTEHEH */
- {0xFB54, 0xFB55, 0xFB53, 0xFB52}, /* U+067B ARABIC LETTER BEEH */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+067C */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+067D */
- {0xFB58, 0xFB59, 0xFB57, 0xFB56}, /* U+067E ARABIC LETTER PEH */
- {0xFB64, 0xFB65, 0xFB63, 0xFB62}, /* U+067F ARABIC LETTER TEHEH */
- {0xFB5C, 0xFB5D, 0xFB5B, 0xFB5A}, /* U+0680 ARABIC LETTER BEHEH */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0681 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0682 */
- {0xFB78, 0xFB79, 0xFB77, 0xFB76}, /* U+0683 ARABIC LETTER NYEH */
- {0xFB74, 0xFB75, 0xFB73, 0xFB72}, /* U+0684 ARABIC LETTER DYEH */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0685 */
- {0xFB7C, 0xFB7D, 0xFB7B, 0xFB7A}, /* U+0686 ARABIC LETTER TCHEH */
- {0xFB80, 0xFB81, 0xFB7F, 0xFB7E}, /* U+0687 ARABIC LETTER TCHEHEH */
- {0x0000, 0x0000, 0xFB89, 0xFB88}, /* U+0688 ARABIC LETTER DDAL */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0689 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+068A */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+068B */
- {0x0000, 0x0000, 0xFB85, 0xFB84}, /* U+068C ARABIC LETTER DAHAL */
- {0x0000, 0x0000, 0xFB83, 0xFB82}, /* U+068D ARABIC LETTER DDAHAL */
- {0x0000, 0x0000, 0xFB87, 0xFB86}, /* U+068E ARABIC LETTER DUL */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+068F */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0690 */
- {0x0000, 0x0000, 0xFB8D, 0xFB8C}, /* U+0691 ARABIC LETTER RREH */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0692 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0693 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0694 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0695 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0696 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0697 */
- {0x0000, 0x0000, 0xFB8B, 0xFB8A}, /* U+0698 ARABIC LETTER JEH */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0699 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+069A */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+069B */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+069C */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+069D */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+069E */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+069F */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A0 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A1 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A2 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A3 */
- {0xFB6C, 0xFB6D, 0xFB6B, 0xFB6A}, /* U+06A4 ARABIC LETTER VEH */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A5 */
- {0xFB70, 0xFB71, 0xFB6F, 0xFB6E}, /* U+06A6 ARABIC LETTER PEHEH */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A7 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A8 */
- {0xFB90, 0xFB91, 0xFB8F, 0xFB8E}, /* U+06A9 ARABIC LETTER KEHEH */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06AA */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06AB */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06AC */
- {0xFBD5, 0xFBD6, 0xFBD4, 0xFBD3}, /* U+06AD ARABIC LETTER NG */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06AE */
- {0xFB94, 0xFB95, 0xFB93, 0xFB92}, /* U+06AF ARABIC LETTER GAF */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B0 */
- {0xFB9C, 0xFB9D, 0xFB9B, 0xFB9A}, /* U+06B1 ARABIC LETTER NGOEH */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B2 */
- {0xFB98, 0xFB99, 0xFB97, 0xFB96}, /* U+06B3 ARABIC LETTER GUEH */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B4 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B5 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B6 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B7 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B8 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B9 */
- {0x0000, 0x0000, 0xFB9F, 0xFB9E}, /* U+06BA ARABIC LETTER NOON GHUNNA */
- {0xFBA2, 0xFBA3, 0xFBA1, 0xFBA0}, /* U+06BB ARABIC LETTER RNOON */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06BC */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06BD */
- {0xFBAC, 0xFBAD, 0xFBAB, 0xFBAA}, /* U+06BE ARABIC LETTER HEH DOACHASHMEE */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06BF */
- {0x0000, 0x0000, 0xFBA5, 0xFBA4}, /* U+06C0 ARABIC LETTER HEH WITH YEH ABOVE */
- {0xFBA8, 0xFBA9, 0xFBA7, 0xFBA6}, /* U+06C1 ARABIC LETTER HEH GOAL */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06C2 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06C3 */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06C4 */
- {0x0000, 0x0000, 0xFBE1, 0xFBE0}, /* U+06C5 ARABIC LETTER KIRGHIZ OE */
- {0x0000, 0x0000, 0xFBDA, 0xFBD9}, /* U+06C6 ARABIC LETTER OE */
- {0x0000, 0x0000, 0xFBD8, 0xFBD7}, /* U+06C7 ARABIC LETTER U */
- {0x0000, 0x0000, 0xFBDC, 0xFBDB}, /* U+06C8 ARABIC LETTER YU */
- {0x0000, 0x0000, 0xFBE3, 0xFBE2}, /* U+06C9 ARABIC LETTER KIRGHIZ YU */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06CA */
- {0x0000, 0x0000, 0xFBDF, 0xFBDE}, /* U+06CB ARABIC LETTER VE */
- {0xFBFE, 0xFBFF, 0xFBFD, 0xFBFC}, /* U+06CC ARABIC LETTER FARSI YEH */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06CD */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06CE */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06CF */
- {0xFBE6, 0xFBE7, 0xFBE5, 0xFBE4}, /* U+06D0 ARABIC LETTER E */
- {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06D1 */
- {0x0000, 0x0000, 0xFBAF, 0xFBAE}, /* U+06D2 ARABIC LETTER YEH BARREE */
- {0x0000, 0x0000, 0xFBB1, 0xFBB0}, /* U+06D3 ARABIC LETTER YEH BARREE WITH HAMZA ABOVE */
+ {0x0000u, 0x0000u, 0x0000u, 0xFE80u}, /* U+0621 ARABIC LETTER HAMZA ISOLATED FORM */
+ {0x0000u, 0x0000u, 0xFE82u, 0xFE81u}, /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */
+ {0x0000u, 0x0000u, 0xFE84u, 0xFE83u}, /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */
+ {0x0000u, 0x0000u, 0xFE86u, 0xFE85u}, /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */
+ {0x0000u, 0x0000u, 0xFE88u, 0xFE87u}, /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */
+ {0xFE8Bu, 0xFE8Cu, 0xFE8Au, 0xFE89u}, /* U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE */
+ {0x0000u, 0x0000u, 0xFE8Eu, 0xFE8Du}, /* U+0627 ARABIC LETTER ALEF */
+ {0xFE91u, 0xFE92u, 0xFE90u, 0xFE8Fu}, /* U+0628 ARABIC LETTER BEH */
+ {0x0000u, 0x0000u, 0xFE94u, 0xFE93u}, /* U+0629 ARABIC LETTER TEH MARBUTA */
+ {0xFE97u, 0xFE98u, 0xFE96u, 0xFE95u}, /* U+062A ARABIC LETTER TEH */
+ {0xFE9Bu, 0xFE9Cu, 0xFE9Au, 0xFE99u}, /* U+062B ARABIC LETTER THEH */
+ {0xFE9Fu, 0xFEA0u, 0xFE9Eu, 0xFE9Du}, /* U+062C ARABIC LETTER JEEM */
+ {0xFEA3u, 0xFEA4u, 0xFEA2u, 0xFEA1u}, /* U+062D ARABIC LETTER HAH */
+ {0xFEA7u, 0xFEA8u, 0xFEA6u, 0xFEA5u}, /* U+062E ARABIC LETTER KHAH */
+ {0x0000u, 0x0000u, 0xFEAAu, 0xFEA9u}, /* U+062F ARABIC LETTER DAL */
+ {0x0000u, 0x0000u, 0xFEACu, 0xFEABu}, /* U+0630 ARABIC LETTER THAL */
+ {0x0000u, 0x0000u, 0xFEAEu, 0xFEADu}, /* U+0631 ARABIC LETTER REH */
+ {0x0000u, 0x0000u, 0xFEB0u, 0xFEAFu}, /* U+0632 ARABIC LETTER ZAIN */
+ {0xFEB3u, 0xFEB4u, 0xFEB2u, 0xFEB1u}, /* U+0633 ARABIC LETTER SEEN */
+ {0xFEB7u, 0xFEB8u, 0xFEB6u, 0xFEB5u}, /* U+0634 ARABIC LETTER SHEEN */
+ {0xFEBBu, 0xFEBCu, 0xFEBAu, 0xFEB9u}, /* U+0635 ARABIC LETTER SAD */
+ {0xFEBFu, 0xFEC0u, 0xFEBEu, 0xFEBDu}, /* U+0636 ARABIC LETTER DAD */
+ {0xFEC3u, 0xFEC4u, 0xFEC2u, 0xFEC1u}, /* U+0637 ARABIC LETTER TAH */
+ {0xFEC7u, 0xFEC8u, 0xFEC6u, 0xFEC5u}, /* U+0638 ARABIC LETTER ZAH */
+ {0xFECBu, 0xFECCu, 0xFECAu, 0xFEC9u}, /* U+0639 ARABIC LETTER AIN */
+ {0xFECFu, 0xFED0u, 0xFECEu, 0xFECDu}, /* U+063A ARABIC LETTER GHAIN */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063B */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063C */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063D */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063E */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063F */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0640 */
+ {0xFED3u, 0xFED4u, 0xFED2u, 0xFED1u}, /* U+0641 ARABIC LETTER FEH */
+ {0xFED7u, 0xFED8u, 0xFED6u, 0xFED5u}, /* U+0642 ARABIC LETTER QAF */
+ {0xFEDBu, 0xFEDCu, 0xFEDAu, 0xFED9u}, /* U+0643 ARABIC LETTER KAF */
+ {0xFEDFu, 0xFEE0u, 0xFEDEu, 0xFEDDu}, /* U+0644 ARABIC LETTER LAM */
+ {0xFEE3u, 0xFEE4u, 0xFEE2u, 0xFEE1u}, /* U+0645 ARABIC LETTER MEEM */
+ {0xFEE7u, 0xFEE8u, 0xFEE6u, 0xFEE5u}, /* U+0646 ARABIC LETTER NOON */
+ {0xFEEBu, 0xFEECu, 0xFEEAu, 0xFEE9u}, /* U+0647 ARABIC LETTER HEH */
+ {0x0000u, 0x0000u, 0xFEEEu, 0xFEEDu}, /* U+0648 ARABIC LETTER WAW */
+ {0xFBE8u, 0xFBE9u, 0xFEF0u, 0xFEEFu}, /* U+0649 ARABIC LETTER */
+ {0xFEF3u, 0xFEF4u, 0xFEF2u, 0xFEF1u}, /* U+064A ARABIC LETTER YEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064B */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064C */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064D */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064E */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064F */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0650 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0651 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0652 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0653 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0654 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0655 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0656 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0657 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0658 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0659 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065A */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065B */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065C */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065D */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065E */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065F */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0660 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0661 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0662 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0663 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0664 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0665 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0666 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0667 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0668 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0669 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066A */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066B */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066C */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066D */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066E */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066F */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0670 */
+ {0x0000u, 0x0000u, 0xFB51u, 0xFB50u}, /* U+0671 ARABIC LETTER ALEF WASLA */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0672 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0673 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0674 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0675 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0676 */
+ {0x0000u, 0x0000u, 0x0000u, 0xFBDDu}, /* U+0677 ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0678 */
+ {0xFB68u, 0xFB69u, 0xFB67u, 0xFB66u}, /* U+0679 ARABIC LETTER TTEH */
+ {0xFB60u, 0xFB61u, 0xFB5Fu, 0xFB5Eu}, /* U+067A ARABIC LETTER TTEHEH */
+ {0xFB54u, 0xFB55u, 0xFB53u, 0xFB52u}, /* U+067B ARABIC LETTER BEEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+067C */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+067D */
+ {0xFB58u, 0xFB59u, 0xFB57u, 0xFB56u}, /* U+067E ARABIC LETTER PEH */
+ {0xFB64u, 0xFB65u, 0xFB63u, 0xFB62u}, /* U+067F ARABIC LETTER TEHEH */
+ {0xFB5Cu, 0xFB5Du, 0xFB5Bu, 0xFB5Au}, /* U+0680 ARABIC LETTER BEHEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0681 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0682 */
+ {0xFB78u, 0xFB79u, 0xFB77u, 0xFB76u}, /* U+0683 ARABIC LETTER NYEH */
+ {0xFB74u, 0xFB75u, 0xFB73u, 0xFB72u}, /* U+0684 ARABIC LETTER DYEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0685 */
+ {0xFB7Cu, 0xFB7Du, 0xFB7Bu, 0xFB7Au}, /* U+0686 ARABIC LETTER TCHEH */
+ {0xFB80u, 0xFB81u, 0xFB7Fu, 0xFB7Eu}, /* U+0687 ARABIC LETTER TCHEHEH */
+ {0x0000u, 0x0000u, 0xFB89u, 0xFB88u}, /* U+0688 ARABIC LETTER DDAL */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0689 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+068A */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+068B */
+ {0x0000u, 0x0000u, 0xFB85u, 0xFB84u}, /* U+068C ARABIC LETTER DAHAL */
+ {0x0000u, 0x0000u, 0xFB83u, 0xFB82u}, /* U+068D ARABIC LETTER DDAHAL */
+ {0x0000u, 0x0000u, 0xFB87u, 0xFB86u}, /* U+068E ARABIC LETTER DUL */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+068F */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0690 */
+ {0x0000u, 0x0000u, 0xFB8Du, 0xFB8Cu}, /* U+0691 ARABIC LETTER RREH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0692 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0693 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0694 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0695 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0696 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0697 */
+ {0x0000u, 0x0000u, 0xFB8Bu, 0xFB8Au}, /* U+0698 ARABIC LETTER JEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0699 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069A */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069B */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069C */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069D */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069E */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069F */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A0 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A1 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A2 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A3 */
+ {0xFB6Cu, 0xFB6Du, 0xFB6Bu, 0xFB6Au}, /* U+06A4 ARABIC LETTER VEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A5 */
+ {0xFB70u, 0xFB71u, 0xFB6Fu, 0xFB6Eu}, /* U+06A6 ARABIC LETTER PEHEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A7 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A8 */
+ {0xFB90u, 0xFB91u, 0xFB8Fu, 0xFB8Eu}, /* U+06A9 ARABIC LETTER KEHEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06AA */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06AB */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06AC */
+ {0xFBD5u, 0xFBD6u, 0xFBD4u, 0xFBD3u}, /* U+06AD ARABIC LETTER NG */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06AE */
+ {0xFB94u, 0xFB95u, 0xFB93u, 0xFB92u}, /* U+06AF ARABIC LETTER GAF */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B0 */
+ {0xFB9Cu, 0xFB9Du, 0xFB9Bu, 0xFB9Au}, /* U+06B1 ARABIC LETTER NGOEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B2 */
+ {0xFB98u, 0xFB99u, 0xFB97u, 0xFB96u}, /* U+06B3 ARABIC LETTER GUEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B4 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B5 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B6 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B7 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B8 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B9 */
+ {0x0000u, 0x0000u, 0xFB9Fu, 0xFB9Eu}, /* U+06BA ARABIC LETTER NOON GHUNNA */
+ {0xFBA2u, 0xFBA3u, 0xFBA1u, 0xFBA0u}, /* U+06BB ARABIC LETTER RNOON */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06BC */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06BD */
+ {0xFBACu, 0xFBADu, 0xFBABu, 0xFBAAu}, /* U+06BE ARABIC LETTER HEH DOACHASHMEE */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06BF */
+ {0x0000u, 0x0000u, 0xFBA5u, 0xFBA4u}, /* U+06C0 ARABIC LETTER HEH WITH YEH ABOVE */
+ {0xFBA8u, 0xFBA9u, 0xFBA7u, 0xFBA6u}, /* U+06C1 ARABIC LETTER HEH GOAL */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06C2 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06C3 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06C4 */
+ {0x0000u, 0x0000u, 0xFBE1u, 0xFBE0u}, /* U+06C5 ARABIC LETTER KIRGHIZ OE */
+ {0x0000u, 0x0000u, 0xFBDAu, 0xFBD9u}, /* U+06C6 ARABIC LETTER OE */
+ {0x0000u, 0x0000u, 0xFBD8u, 0xFBD7u}, /* U+06C7 ARABIC LETTER U */
+ {0x0000u, 0x0000u, 0xFBDCu, 0xFBDBu}, /* U+06C8 ARABIC LETTER YU */
+ {0x0000u, 0x0000u, 0xFBE3u, 0xFBE2u}, /* U+06C9 ARABIC LETTER KIRGHIZ YU */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06CA */
+ {0x0000u, 0x0000u, 0xFBDFu, 0xFBDEu}, /* U+06CB ARABIC LETTER VE */
+ {0xFBFEu, 0xFBFFu, 0xFBFDu, 0xFBFCu}, /* U+06CC ARABIC LETTER FARSI YEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06CD */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06CE */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06CF */
+ {0xFBE6u, 0xFBE7u, 0xFBE5u, 0xFBE4u}, /* U+06D0 ARABIC LETTER E */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06D1 */
+ {0x0000u, 0x0000u, 0xFBAFu, 0xFBAEu}, /* U+06D2 ARABIC LETTER YEH BARREE */
+ {0x0000u, 0x0000u, 0xFBB1u, 0xFBB0u}, /* U+06D3 ARABIC LETTER YEH BARREE WITH HAMZA ABOVE */
};
-#define SHAPING_TABLE_FIRST 0x0621
-#define SHAPING_TABLE_LAST 0x06D3
+#define SHAPING_TABLE_FIRST 0x0621u
+#define SHAPING_TABLE_LAST 0x06D3u
static const struct ligature_set_t {
@@ -922,17 +363,17 @@ static const struct ligature_set_t {
} ligatures[4];
} ligature_table[] =
{
- { 0xFEDF, {
- { 0xFE88, 0xFEF9 }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM */
- { 0xFE82, 0xFEF5 }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM */
- { 0xFE8E, 0xFEFB }, /* ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM */
- { 0xFE84, 0xFEF7 }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM */
+ { 0xFEDFu, {
+ { 0xFE88u, 0xFEF9u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM */
+ { 0xFE82u, 0xFEF5u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM */
+ { 0xFE8Eu, 0xFEFBu }, /* ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM */
+ { 0xFE84u, 0xFEF7u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM */
}},
- { 0xFEE0, {
- { 0xFE88, 0xFEFA }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM */
- { 0xFE82, 0xFEF6 }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM */
- { 0xFE8E, 0xFEFC }, /* ARABIC LIGATURE LAM WITH ALEF FINAL FORM */
- { 0xFE84, 0xFEF8 }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM */
+ { 0xFEE0u, {
+ { 0xFE88u, 0xFEFAu }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM */
+ { 0xFE82u, 0xFEF6u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM */
+ { 0xFE8Eu, 0xFEFCu }, /* ARABIC LIGATURE LAM WITH ALEF FINAL FORM */
+ { 0xFE84u, 0xFEF8u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM */
}},
};
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc
index ea6d85c1e6..9870ba3da0 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc
@@ -57,68 +57,41 @@ enum {
static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_category_t gen_cat)
{
- if (likely (hb_in_range<hb_codepoint_t> (u, JOINING_TABLE_FIRST, JOINING_TABLE_LAST))) {
- unsigned int j_type = joining_table[u - JOINING_TABLE_FIRST];
- if (likely (j_type != JOINING_TYPE_X))
- return j_type;
- }
-
- /* Mongolian joining data is not in ArabicJoining.txt yet. */
- if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x1800, 0x18AF)))
- {
- if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x1880, 0x1886)))
- return JOINING_TYPE_U;
-
- /* All letters, SIBE SYLLABLE BOUNDARY MARKER, and NIRUGU are D */
- if ((FLAG(gen_cat) & (FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER) |
- FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER)))
- || u == 0x1807 || u == 0x180A)
- return JOINING_TYPE_D;
- }
-
- /* 'Phags-pa joining data is not in ArabicJoining.txt yet. */
- if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xA840, 0xA872)))
- {
- if (unlikely (u == 0xA872))
- return JOINING_TYPE_L;
-
- return JOINING_TYPE_D;
- }
-
- if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x200C, 0x200D)))
- {
- return u == 0x200C ? JOINING_TYPE_U : JOINING_TYPE_C;
- }
-
- return (FLAG(gen_cat) & (FLAG(HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | FLAG(HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | FLAG(HB_UNICODE_GENERAL_CATEGORY_FORMAT))) ?
- JOINING_TYPE_T : JOINING_TYPE_U;
+ unsigned int j_type = joining_type(u);
+ if (likely (j_type != JOINING_TYPE_X))
+ return j_type;
+
+ return (FLAG(gen_cat) &
+ (FLAG(HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) |
+ FLAG(HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) |
+ FLAG(HB_UNICODE_GENERAL_CATEGORY_FORMAT))
+ ) ? JOINING_TYPE_T : JOINING_TYPE_U;
}
+#define FEATURE_IS_SYRIAC(tag) hb_in_range<unsigned char> ((unsigned char) (tag), '2', '3')
+
static const hb_tag_t arabic_features[] =
{
- HB_TAG('i','n','i','t'),
- HB_TAG('m','e','d','i'),
- HB_TAG('f','i','n','a'),
HB_TAG('i','s','o','l'),
- /* Syriac */
- HB_TAG('m','e','d','2'),
+ HB_TAG('f','i','n','a'),
HB_TAG('f','i','n','2'),
HB_TAG('f','i','n','3'),
+ HB_TAG('m','e','d','i'),
+ HB_TAG('m','e','d','2'),
+ HB_TAG('i','n','i','t'),
HB_TAG_NONE
};
/* Same order as the feature array */
enum {
- INIT,
- MEDI,
- FINA,
ISOL,
-
- /* Syriac */
- MED2,
+ FINA,
FIN2,
FIN3,
+ MEDI,
+ MED2,
+ INIT,
NONE,
@@ -171,14 +144,23 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
{
hb_ot_map_builder_t *map = &plan->map;
- /* For Language forms (in ArabicOT speak), we do the iso/fina/medi/init together,
- * then rlig and calt each in their own stage. This makes IranNastaliq's ALLAH
- * ligature work correctly. It's unfortunate though...
+ /* We apply features according to the Arabic spec, with pauses
+ * in between most.
*
- * This also makes Arial Bold in Windows7 work. See:
+ * The pause between init/medi/... and rlig is required. See eg:
* https://bugzilla.mozilla.org/show_bug.cgi?id=644184
*
- * TODO: Add test cases for these two.
+ * The pauses between init/medi/... themselves are not necessarily
+ * needed as only one of those features is applied to any character.
+ * The only difference it makes is when fonts have contextual
+ * substitutions. We now follow the order of the spec, which makes
+ * for better experience if that's what Uniscribe is doing.
+ *
+ * At least for Arabic, looks like Uniscribe has a pause between
+ * rlig and calt. Otherwise the IranNastaliq's ALLAH ligature won't
+ * work. However, testing shows that rlig and calt are applied
+ * together for Mongolian in Uniscribe. As such, we only add a
+ * pause for Arabic, not other scripts.
*/
map->add_gsub_pause (nuke_joiners);
@@ -189,16 +171,28 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
map->add_gsub_pause (NULL);
for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++)
- map->add_feature (arabic_features[i], 1, i < 4 ? F_HAS_FALLBACK : F_NONE); /* The first four features have fallback. */
-
- map->add_gsub_pause (NULL);
+ {
+ bool has_fallback = plan->props.script == HB_SCRIPT_ARABIC && !FEATURE_IS_SYRIAC (arabic_features[i]);
+ map->add_feature (arabic_features[i], 1, has_fallback ? F_HAS_FALLBACK : F_NONE);
+ map->add_gsub_pause (NULL);
+ }
map->add_feature (HB_TAG('r','l','i','g'), 1, F_GLOBAL|F_HAS_FALLBACK);
- map->add_gsub_pause (arabic_fallback_shape);
+ if (plan->props.script == HB_SCRIPT_ARABIC)
+ map->add_gsub_pause (arabic_fallback_shape);
map->add_global_bool_feature (HB_TAG('c','a','l','t'));
map->add_gsub_pause (NULL);
+ /* The spec includes 'cswh'. Earlier versions of Windows
+ * used to enable this by default, but testing suggests
+ * that Windows 8 and later do not enable it by default,
+ * and spec now says 'Off by default'.
+ * We disabled this in ae23c24c32.
+ * Note that IranNastaliq uses this feature extensively
+ * to fixup broken glyph sequences. Oh well...
+ * Test case: U+0643,U+0640,U+0631. */
+ //map->add_global_bool_feature (HB_TAG('c','s','w','h'));
map->add_global_bool_feature (HB_TAG('m','s','e','t'));
}
@@ -228,8 +222,9 @@ data_create_arabic (const hb_ot_shape_plan_t *plan)
arabic_plan->do_fallback = plan->props.script == HB_SCRIPT_ARABIC;
for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) {
arabic_plan->mask_array[i] = plan->map.get_1_mask (arabic_features[i]);
- if (i < 4)
- arabic_plan->do_fallback = arabic_plan->do_fallback && plan->map.needs_fallback (arabic_features[i]);
+ arabic_plan->do_fallback = arabic_plan->do_fallback &&
+ !FEATURE_IS_SYRIAC (arabic_features[i]) &&
+ plan->map.needs_fallback (arabic_features[i]);
}
return arabic_plan;
@@ -249,10 +244,9 @@ static void
arabic_joining (hb_buffer_t *buffer)
{
unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
unsigned int prev = (unsigned int) -1, state = 0;
- HB_BUFFER_ALLOCATE_VAR (buffer, arabic_shaping_action);
-
/* Check pre-context */
if (!(buffer->flags & HB_BUFFER_FLAG_BOT))
for (unsigned int i = 0; i < buffer->context_len[0]; i++)
@@ -269,20 +263,19 @@ arabic_joining (hb_buffer_t *buffer)
for (unsigned int i = 0; i < count; i++)
{
- unsigned int this_type = get_joining_type (buffer->info[i].codepoint, _hb_glyph_info_get_general_category (&buffer->info[i]));
+ unsigned int this_type = get_joining_type (info[i].codepoint, _hb_glyph_info_get_general_category (&info[i]));
if (unlikely (this_type == JOINING_TYPE_T)) {
- buffer->info[i].arabic_shaping_action() = NONE;
+ info[i].arabic_shaping_action() = NONE;
continue;
}
const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
if (entry->prev_action != NONE && prev != (unsigned int) -1)
- for (; prev < i; prev++)
- buffer->info[prev].arabic_shaping_action() = entry->prev_action;
+ info[prev].arabic_shaping_action() = entry->prev_action;
- buffer->info[i].arabic_shaping_action() = entry->curr_action;
+ info[i].arabic_shaping_action() = entry->curr_action;
prev = i;
state = entry->next_state;
@@ -298,12 +291,20 @@ arabic_joining (hb_buffer_t *buffer)
const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
if (entry->prev_action != NONE && prev != (unsigned int) -1)
- buffer->info[prev].arabic_shaping_action() = entry->prev_action;
+ info[prev].arabic_shaping_action() = entry->prev_action;
break;
}
+}
-
- HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
+static void
+mongolian_variation_selectors (hb_buffer_t *buffer)
+{
+ /* Copy arabic_shaping_action() from base to Mongolian variation selectors. */
+ unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
+ for (unsigned int i = 1; i < count; i++)
+ if (unlikely (hb_in_range (info[i].codepoint, 0x180Bu, 0x180Du)))
+ info[i].arabic_shaping_action() = info[i - 1].arabic_shaping_action();
}
static void
@@ -311,12 +312,20 @@ setup_masks_arabic (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer,
hb_font_t *font HB_UNUSED)
{
+ HB_BUFFER_ALLOCATE_VAR (buffer, arabic_shaping_action);
+
const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
arabic_joining (buffer);
+ if (plan->props.script == HB_SCRIPT_MONGOLIAN)
+ mongolian_variation_selectors (buffer);
+
unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
- buffer->info[i].mask |= arabic_plan->mask_array[buffer->info[i].arabic_shaping_action()];
+ info[i].mask |= arabic_plan->mask_array[info[i].arabic_shaping_action()];
+
+ HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
}
@@ -326,9 +335,10 @@ nuke_joiners (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_buffer_t *buffer)
{
unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
- if (_hb_glyph_info_is_zwj (&buffer->info[i]))
- _hb_glyph_info_flip_joiners (&buffer->info[i]);
+ if (_hb_glyph_info_is_zwj (&info[i]))
+ _hb_glyph_info_flip_joiners (&info[i]);
}
static void
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc
index 47aa44fedb..54c12ebca2 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc
@@ -86,26 +86,26 @@ data_destroy_hangul (void *data)
}
/* Constants for algorithmic hangul syllable [de]composition. */
-#define LBase 0x1100
-#define VBase 0x1161
-#define TBase 0x11A7
-#define LCount 19
-#define VCount 21
-#define TCount 28
-#define SBase 0xAC00
+#define LBase 0x1100u
+#define VBase 0x1161u
+#define TBase 0x11A7u
+#define LCount 19u
+#define VCount 21u
+#define TCount 28u
+#define SBase 0xAC00u
#define NCount (VCount * TCount)
#define SCount (LCount * NCount)
-#define isCombiningL(u) (hb_in_range<hb_codepoint_t> ((u), LBase, LBase+LCount-1))
-#define isCombiningV(u) (hb_in_range<hb_codepoint_t> ((u), VBase, VBase+VCount-1))
-#define isCombiningT(u) (hb_in_range<hb_codepoint_t> ((u), TBase+1, TBase+TCount-1))
-#define isCombinedS(u) (hb_in_range<hb_codepoint_t> ((u), SBase, SBase+SCount-1))
+#define isCombiningL(u) (hb_in_range ((u), LBase, LBase+LCount-1))
+#define isCombiningV(u) (hb_in_range ((u), VBase, VBase+VCount-1))
+#define isCombiningT(u) (hb_in_range ((u), TBase+1, TBase+TCount-1))
+#define isCombinedS(u) (hb_in_range ((u), SBase, SBase+SCount-1))
-#define isL(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1100, 0x115F, 0xA960, 0xA97C))
-#define isV(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1160, 0x11A7, 0xD7B0, 0xD7C6))
-#define isT(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x11A8, 0x11FF, 0xD7CB, 0xD7FB))
+#define isL(u) (hb_in_ranges ((u), 0x1100u, 0x115Fu, 0xA960u, 0xA97Cu))
+#define isV(u) (hb_in_ranges ((u), 0x1160u, 0x11A7u, 0xD7B0u, 0xD7C6u))
+#define isT(u) (hb_in_ranges ((u), 0x11A8u, 0x11FFu, 0xD7CBu, 0xD7FBu))
-#define isHangulTone(u) (hb_in_range<hb_codepoint_t> ((u), 0x302e, 0x302f))
+#define isHangulTone(u) (hb_in_range ((u), 0x302Eu, 0x302Fu))
/* buffer var allocations */
#define hangul_shaping_feature() complex_var_u8_0() /* hangul jamo shaping feature */
@@ -211,14 +211,14 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
else
{
/* No valid syllable as base for tone mark; try to insert dotted circle. */
- if (font->has_glyph (0x25cc))
+ if (font->has_glyph (0x25CCu))
{
hb_codepoint_t chars[2];
if (!is_zero_width_char (font, u)) {
chars[0] = u;
- chars[1] = 0x25cc;
+ chars[1] = 0x25CCu;
} else {
- chars[0] = 0x25cc;
+ chars[0] = 0x25CCu;
chars[1] = u;
}
buffer->replace_glyphs (1, 2, chars);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc
index efef8c14ad..2381a6e732 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc
@@ -35,116 +35,116 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c,
{
/* Hebrew presentation-form shaping.
* https://bugzilla.mozilla.org/show_bug.cgi?id=728866
- * Hebrew presentation forms with dagesh, for characters 0x05D0..0x05EA;
+ * Hebrew presentation forms with dagesh, for characters U+05D0..05EA;
* Note that some letters do not have a dagesh presForm encoded.
*/
- static const hb_codepoint_t sDageshForms[0x05EA - 0x05D0 + 1] = {
- 0xFB30, /* ALEF */
- 0xFB31, /* BET */
- 0xFB32, /* GIMEL */
- 0xFB33, /* DALET */
- 0xFB34, /* HE */
- 0xFB35, /* VAV */
- 0xFB36, /* ZAYIN */
- 0x0000, /* HET */
- 0xFB38, /* TET */
- 0xFB39, /* YOD */
- 0xFB3A, /* FINAL KAF */
- 0xFB3B, /* KAF */
- 0xFB3C, /* LAMED */
- 0x0000, /* FINAL MEM */
- 0xFB3E, /* MEM */
- 0x0000, /* FINAL NUN */
- 0xFB40, /* NUN */
- 0xFB41, /* SAMEKH */
- 0x0000, /* AYIN */
- 0xFB43, /* FINAL PE */
- 0xFB44, /* PE */
- 0x0000, /* FINAL TSADI */
- 0xFB46, /* TSADI */
- 0xFB47, /* QOF */
- 0xFB48, /* RESH */
- 0xFB49, /* SHIN */
- 0xFB4A /* TAV */
+ static const hb_codepoint_t sDageshForms[0x05EAu - 0x05D0u + 1] = {
+ 0xFB30u, /* ALEF */
+ 0xFB31u, /* BET */
+ 0xFB32u, /* GIMEL */
+ 0xFB33u, /* DALET */
+ 0xFB34u, /* HE */
+ 0xFB35u, /* VAV */
+ 0xFB36u, /* ZAYIN */
+ 0x0000u, /* HET */
+ 0xFB38u, /* TET */
+ 0xFB39u, /* YOD */
+ 0xFB3Au, /* FINAL KAF */
+ 0xFB3Bu, /* KAF */
+ 0xFB3Cu, /* LAMED */
+ 0x0000u, /* FINAL MEM */
+ 0xFB3Eu, /* MEM */
+ 0x0000u, /* FINAL NUN */
+ 0xFB40u, /* NUN */
+ 0xFB41u, /* SAMEKH */
+ 0x0000u, /* AYIN */
+ 0xFB43u, /* FINAL PE */
+ 0xFB44u, /* PE */
+ 0x0000u, /* FINAL TSADI */
+ 0xFB46u, /* TSADI */
+ 0xFB47u, /* QOF */
+ 0xFB48u, /* RESH */
+ 0xFB49u, /* SHIN */
+ 0xFB4Au /* TAV */
};
bool found = c->unicode->compose (a, b, ab);
- if (!found)
+ if (!found && !c->plan->has_mark)
{
/* Special-case Hebrew presentation forms that are excluded from
* standard normalization, but wanted for old fonts. */
switch (b) {
- case 0x05B4: /* HIRIQ */
- if (a == 0x05D9) { /* YOD */
- *ab = 0xFB1D;
+ case 0x05B4u: /* HIRIQ */
+ if (a == 0x05D9u) { /* YOD */
+ *ab = 0xFB1Du;
found = true;
}
break;
- case 0x05B7: /* patah */
- if (a == 0x05F2) { /* YIDDISH YOD YOD */
- *ab = 0xFB1F;
+ case 0x05B7u: /* patah */
+ if (a == 0x05F2u) { /* YIDDISH YOD YOD */
+ *ab = 0xFB1Fu;
found = true;
- } else if (a == 0x05D0) { /* ALEF */
- *ab = 0xFB2E;
+ } else if (a == 0x05D0u) { /* ALEF */
+ *ab = 0xFB2Eu;
found = true;
}
break;
- case 0x05B8: /* QAMATS */
- if (a == 0x05D0) { /* ALEF */
- *ab = 0xFB2F;
+ case 0x05B8u: /* QAMATS */
+ if (a == 0x05D0u) { /* ALEF */
+ *ab = 0xFB2Fu;
found = true;
}
break;
- case 0x05B9: /* HOLAM */
- if (a == 0x05D5) { /* VAV */
- *ab = 0xFB4B;
+ case 0x05B9u: /* HOLAM */
+ if (a == 0x05D5u) { /* VAV */
+ *ab = 0xFB4Bu;
found = true;
}
break;
- case 0x05BC: /* DAGESH */
- if (a >= 0x05D0 && a <= 0x05EA) {
- *ab = sDageshForms[a - 0x05D0];
+ case 0x05BCu: /* DAGESH */
+ if (a >= 0x05D0u && a <= 0x05EAu) {
+ *ab = sDageshForms[a - 0x05D0u];
found = (*ab != 0);
- } else if (a == 0xFB2A) { /* SHIN WITH SHIN DOT */
- *ab = 0xFB2C;
+ } else if (a == 0xFB2Au) { /* SHIN WITH SHIN DOT */
+ *ab = 0xFB2Cu;
found = true;
- } else if (a == 0xFB2B) { /* SHIN WITH SIN DOT */
- *ab = 0xFB2D;
+ } else if (a == 0xFB2Bu) { /* SHIN WITH SIN DOT */
+ *ab = 0xFB2Du;
found = true;
}
break;
- case 0x05BF: /* RAFE */
+ case 0x05BFu: /* RAFE */
switch (a) {
- case 0x05D1: /* BET */
- *ab = 0xFB4C;
+ case 0x05D1u: /* BET */
+ *ab = 0xFB4Cu;
found = true;
break;
- case 0x05DB: /* KAF */
- *ab = 0xFB4D;
+ case 0x05DBu: /* KAF */
+ *ab = 0xFB4Du;
found = true;
break;
- case 0x05E4: /* PE */
- *ab = 0xFB4E;
+ case 0x05E4u: /* PE */
+ *ab = 0xFB4Eu;
found = true;
break;
}
break;
- case 0x05C1: /* SHIN DOT */
- if (a == 0x05E9) { /* SHIN */
- *ab = 0xFB2A;
+ case 0x05C1u: /* SHIN DOT */
+ if (a == 0x05E9u) { /* SHIN */
+ *ab = 0xFB2Au;
found = true;
- } else if (a == 0xFB49) { /* SHIN WITH DAGESH */
- *ab = 0xFB2C;
+ } else if (a == 0xFB49u) { /* SHIN WITH DAGESH */
+ *ab = 0xFB2Cu;
found = true;
}
break;
- case 0x05C2: /* SIN DOT */
- if (a == 0x05E9) { /* SHIN */
- *ab = 0xFB2B;
+ case 0x05C2u: /* SIN DOT */
+ if (a == 0x05E9u) { /* SHIN */
+ *ab = 0xFB2Bu;
found = true;
- } else if (a == 0xFB49) { /* SHIN WITH DAGESH */
- *ab = 0xFB2D;
+ } else if (a == 0xFB49u) { /* SHIN WITH DAGESH */
+ *ab = 0xFB2Du;
found = true;
}
break;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh
index 71621034ee..522ccc67fe 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh
@@ -55,52 +55,52 @@ static const unsigned char _indic_syllable_machine_trans_keys[] = {
4u, 14u, 5u, 7u, 5u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u,
7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 1u, 16u, 13u, 13u, 4u, 4u, 6u, 6u,
16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u,
- 6u, 6u, 16u, 16u, 1u, 31u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u,
- 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u,
- 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 18u, 8u, 18u,
- 5u, 10u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 18u, 3u, 18u, 8u, 18u,
- 3u, 10u, 8u, 10u, 3u, 18u, 3u, 18u, 3u, 18u, 3u, 18u, 4u, 18u, 5u, 18u,
- 3u, 18u, 4u, 18u, 5u, 18u, 3u, 18u, 4u, 18u, 5u, 18u, 3u, 18u, 4u, 18u,
- 6u, 18u, 3u, 18u, 1u, 18u, 4u, 31u, 4u, 18u, 3u, 31u, 3u, 31u, 1u, 18u,
- 1u, 18u, 1u, 18u, 1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u,
- 1u, 18u, 1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 1u, 18u,
- 1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 1u, 18u, 1u, 18u,
- 1u, 18u, 3u, 31u, 3u, 31u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u,
- 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u,
- 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 18u, 8u, 18u,
- 5u, 10u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 18u, 3u, 18u, 8u, 18u,
- 3u, 10u, 8u, 10u, 3u, 18u, 3u, 18u, 3u, 18u, 3u, 18u, 4u, 18u, 5u, 18u,
- 3u, 18u, 4u, 18u, 5u, 18u, 3u, 18u, 4u, 18u, 5u, 18u, 3u, 18u, 4u, 18u,
- 6u, 18u, 3u, 18u, 1u, 18u, 4u, 31u, 4u, 18u, 3u, 31u, 3u, 31u, 1u, 18u,
- 1u, 18u, 1u, 18u, 1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u,
- 1u, 18u, 1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 1u, 18u,
- 1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 1u, 18u, 1u, 18u,
- 4u, 14u, 1u, 18u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 3u, 31u,
- 4u, 31u, 1u, 18u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 3u, 31u,
- 4u, 31u, 1u, 18u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 18u, 8u, 18u, 5u, 10u,
- 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 18u, 3u, 18u, 8u, 18u, 3u, 10u,
- 8u, 10u, 3u, 18u, 3u, 18u, 3u, 18u, 3u, 18u, 4u, 18u, 5u, 18u, 3u, 18u,
- 4u, 18u, 5u, 18u, 3u, 18u, 4u, 18u, 5u, 18u, 3u, 18u, 4u, 18u, 6u, 18u,
- 3u, 18u, 1u, 18u, 4u, 31u, 4u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u,
- 1u, 18u, 1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 1u, 18u,
- 1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 1u, 18u, 1u, 18u,
- 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 1u, 18u, 1u, 18u, 1u, 18u,
- 4u, 14u, 3u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u,
- 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u,
- 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 18u, 8u, 18u,
- 5u, 10u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 18u, 3u, 18u, 8u, 18u,
- 3u, 10u, 8u, 10u, 3u, 18u, 3u, 18u, 3u, 18u, 3u, 18u, 4u, 18u, 5u, 18u,
- 3u, 18u, 4u, 18u, 5u, 18u, 3u, 18u, 4u, 18u, 5u, 18u, 3u, 18u, 4u, 18u,
- 6u, 18u, 3u, 18u, 1u, 18u, 4u, 31u, 4u, 18u, 3u, 31u, 3u, 31u, 1u, 18u,
- 1u, 18u, 1u, 18u, 1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u,
- 1u, 18u, 1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 1u, 18u,
- 1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 1u, 18u, 1u, 18u,
- 1u, 18u, 3u, 31u, 1u, 31u, 3u, 31u, 1u, 31u, 4u, 18u, 1u, 18u, 3u, 31u,
- 3u, 31u, 4u, 31u, 5u, 10u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 10u,
- 8u, 10u, 3u, 31u, 3u, 31u, 1u, 18u, 3u, 18u, 4u, 18u, 5u, 18u, 3u, 18u,
- 4u, 18u, 5u, 18u, 3u, 18u, 4u, 18u, 5u, 18u, 3u, 18u, 4u, 18u, 8u, 18u,
- 3u, 18u, 3u, 18u, 8u, 18u, 3u, 18u, 3u, 18u, 1u, 18u, 3u, 10u, 8u, 10u,
- 5u, 10u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 0
+ 6u, 6u, 16u, 16u, 1u, 31u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u,
+ 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u,
+ 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 8u, 14u,
+ 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 13u,
+ 3u, 10u, 8u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u,
+ 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u,
+ 6u, 14u, 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u,
+ 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u,
+ 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u,
+ 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u,
+ 1u, 16u, 3u, 31u, 3u, 31u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u,
+ 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u,
+ 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 8u, 14u,
+ 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 13u,
+ 3u, 10u, 8u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u,
+ 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u,
+ 6u, 14u, 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u,
+ 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u,
+ 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u,
+ 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u,
+ 4u, 14u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u,
+ 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u,
+ 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 8u, 14u, 5u, 10u,
+ 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 13u, 3u, 10u,
+ 8u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u,
+ 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 6u, 14u,
+ 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u,
+ 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u,
+ 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u,
+ 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u,
+ 4u, 14u, 3u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u,
+ 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u,
+ 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 8u, 14u,
+ 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 13u,
+ 3u, 10u, 8u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u,
+ 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u,
+ 6u, 14u, 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u,
+ 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u,
+ 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u,
+ 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u,
+ 1u, 16u, 3u, 31u, 1u, 31u, 3u, 31u, 1u, 31u, 4u, 14u, 1u, 16u, 3u, 31u,
+ 3u, 31u, 4u, 31u, 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u,
+ 5u, 10u, 3u, 31u, 3u, 31u, 1u, 16u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u,
+ 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 8u, 14u,
+ 3u, 13u, 3u, 10u, 8u, 10u, 3u, 10u, 3u, 13u, 1u, 16u, 3u, 10u, 8u, 10u,
+ 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 0
};
static const char _indic_syllable_machine_key_spans[] = {
@@ -125,52 +125,52 @@ static const char _indic_syllable_machine_key_spans[] = {
11, 3, 3, 3, 3, 1, 3, 3,
1, 3, 3, 1, 16, 1, 1, 1,
1, 4, 1, 1, 4, 1, 1, 4,
- 1, 1, 31, 29, 29, 28, 18, 29,
- 29, 28, 18, 29, 29, 28, 18, 29,
- 29, 28, 18, 29, 29, 28, 14, 11,
- 6, 2, 2, 1, 6, 16, 16, 11,
- 8, 3, 16, 16, 16, 16, 15, 14,
- 16, 15, 14, 16, 15, 14, 16, 15,
- 13, 16, 18, 28, 15, 29, 29, 18,
- 18, 18, 18, 18, 29, 29, 18, 18,
- 18, 18, 18, 29, 29, 18, 18, 18,
- 18, 18, 29, 29, 18, 18, 18, 18,
- 18, 29, 29, 29, 29, 28, 18, 29,
- 29, 28, 18, 29, 29, 28, 18, 29,
- 29, 28, 18, 29, 29, 28, 14, 11,
- 6, 2, 2, 1, 6, 16, 16, 11,
- 8, 3, 16, 16, 16, 16, 15, 14,
- 16, 15, 14, 16, 15, 14, 16, 15,
- 13, 16, 18, 28, 15, 29, 29, 18,
- 18, 18, 18, 18, 29, 29, 18, 18,
- 18, 18, 18, 29, 29, 18, 18, 18,
- 18, 18, 29, 29, 18, 18, 18, 18,
- 11, 18, 29, 29, 28, 18, 29, 29,
- 28, 18, 29, 29, 28, 18, 29, 29,
- 28, 18, 29, 29, 28, 14, 11, 6,
- 2, 2, 1, 6, 16, 16, 11, 8,
- 3, 16, 16, 16, 16, 15, 14, 16,
- 15, 14, 16, 15, 14, 16, 15, 13,
- 16, 18, 28, 15, 29, 29, 18, 18,
- 18, 18, 18, 29, 29, 18, 18, 18,
- 18, 18, 29, 29, 18, 18, 18, 18,
- 18, 29, 29, 18, 18, 18, 18, 18,
- 11, 29, 11, 29, 29, 28, 18, 29,
- 29, 28, 18, 29, 29, 28, 18, 29,
- 29, 28, 18, 29, 29, 28, 14, 11,
- 6, 2, 2, 1, 6, 16, 16, 11,
- 8, 3, 16, 16, 16, 16, 15, 14,
- 16, 15, 14, 16, 15, 14, 16, 15,
- 13, 16, 18, 28, 15, 29, 29, 18,
- 18, 18, 18, 18, 29, 29, 18, 18,
- 18, 18, 18, 29, 29, 18, 18, 18,
- 18, 18, 29, 29, 18, 18, 18, 18,
- 18, 29, 31, 29, 31, 15, 18, 29,
- 29, 28, 6, 2, 2, 1, 6, 8,
- 3, 29, 29, 18, 16, 15, 14, 16,
- 15, 14, 16, 15, 14, 16, 15, 11,
- 16, 16, 11, 16, 16, 18, 8, 3,
- 6, 2, 2, 1, 6
+ 1, 1, 31, 29, 29, 28, 16, 29,
+ 29, 28, 16, 29, 29, 28, 16, 29,
+ 29, 28, 16, 29, 29, 28, 10, 7,
+ 6, 2, 1, 2, 2, 1, 6, 11,
+ 8, 3, 8, 11, 12, 12, 11, 10,
+ 12, 11, 10, 12, 11, 10, 12, 11,
+ 9, 12, 16, 28, 11, 29, 29, 16,
+ 16, 16, 16, 16, 29, 29, 16, 16,
+ 16, 16, 16, 29, 29, 16, 16, 16,
+ 16, 16, 29, 29, 16, 16, 16, 16,
+ 16, 29, 29, 29, 29, 28, 16, 29,
+ 29, 28, 16, 29, 29, 28, 16, 29,
+ 29, 28, 16, 29, 29, 28, 10, 7,
+ 6, 2, 1, 2, 2, 1, 6, 11,
+ 8, 3, 8, 11, 12, 12, 11, 10,
+ 12, 11, 10, 12, 11, 10, 12, 11,
+ 9, 12, 16, 28, 11, 29, 29, 16,
+ 16, 16, 16, 16, 29, 29, 16, 16,
+ 16, 16, 16, 29, 29, 16, 16, 16,
+ 16, 16, 29, 29, 16, 16, 16, 16,
+ 11, 16, 29, 29, 28, 16, 29, 29,
+ 28, 16, 29, 29, 28, 16, 29, 29,
+ 28, 16, 29, 29, 28, 10, 7, 6,
+ 2, 1, 2, 2, 1, 6, 11, 8,
+ 3, 8, 11, 12, 12, 11, 10, 12,
+ 11, 10, 12, 11, 10, 12, 11, 9,
+ 12, 16, 28, 11, 29, 29, 16, 16,
+ 16, 16, 16, 29, 29, 16, 16, 16,
+ 16, 16, 29, 29, 16, 16, 16, 16,
+ 16, 29, 29, 16, 16, 16, 16, 16,
+ 11, 29, 11, 29, 29, 28, 16, 29,
+ 29, 28, 16, 29, 29, 28, 16, 29,
+ 29, 28, 16, 29, 29, 28, 10, 7,
+ 6, 2, 1, 2, 2, 1, 6, 11,
+ 8, 3, 8, 11, 12, 12, 11, 10,
+ 12, 11, 10, 12, 11, 10, 12, 11,
+ 9, 12, 16, 28, 11, 29, 29, 16,
+ 16, 16, 16, 16, 29, 29, 16, 16,
+ 16, 16, 16, 29, 29, 16, 16, 16,
+ 16, 16, 29, 29, 16, 16, 16, 16,
+ 16, 29, 31, 29, 31, 11, 16, 29,
+ 29, 28, 6, 2, 1, 2, 2, 1,
+ 6, 29, 29, 16, 12, 11, 10, 12,
+ 11, 10, 12, 11, 10, 12, 11, 7,
+ 11, 8, 3, 8, 11, 16, 8, 3,
+ 6, 2, 1, 2, 2, 1, 6
};
static const short _indic_syllable_machine_index_offsets[] = {
@@ -195,52 +195,52 @@ static const short _indic_syllable_machine_index_offsets[] = {
848, 860, 864, 868, 872, 876, 878, 882,
886, 888, 892, 896, 898, 915, 917, 919,
921, 923, 928, 930, 932, 937, 939, 941,
- 946, 948, 950, 982, 1012, 1042, 1071, 1090,
- 1120, 1150, 1179, 1198, 1228, 1258, 1287, 1306,
- 1336, 1366, 1395, 1414, 1444, 1474, 1503, 1518,
- 1530, 1537, 1540, 1543, 1545, 1552, 1569, 1586,
- 1598, 1607, 1611, 1628, 1645, 1662, 1679, 1695,
- 1710, 1727, 1743, 1758, 1775, 1791, 1806, 1823,
- 1839, 1853, 1870, 1889, 1918, 1934, 1964, 1994,
- 2013, 2032, 2051, 2070, 2089, 2119, 2149, 2168,
- 2187, 2206, 2225, 2244, 2274, 2304, 2323, 2342,
- 2361, 2380, 2399, 2429, 2459, 2478, 2497, 2516,
- 2535, 2554, 2584, 2614, 2644, 2674, 2703, 2722,
- 2752, 2782, 2811, 2830, 2860, 2890, 2919, 2938,
- 2968, 2998, 3027, 3046, 3076, 3106, 3135, 3150,
- 3162, 3169, 3172, 3175, 3177, 3184, 3201, 3218,
- 3230, 3239, 3243, 3260, 3277, 3294, 3311, 3327,
- 3342, 3359, 3375, 3390, 3407, 3423, 3438, 3455,
- 3471, 3485, 3502, 3521, 3550, 3566, 3596, 3626,
- 3645, 3664, 3683, 3702, 3721, 3751, 3781, 3800,
- 3819, 3838, 3857, 3876, 3906, 3936, 3955, 3974,
- 3993, 4012, 4031, 4061, 4091, 4110, 4129, 4148,
- 4167, 4179, 4198, 4228, 4258, 4287, 4306, 4336,
- 4366, 4395, 4414, 4444, 4474, 4503, 4522, 4552,
- 4582, 4611, 4630, 4660, 4690, 4719, 4734, 4746,
- 4753, 4756, 4759, 4761, 4768, 4785, 4802, 4814,
- 4823, 4827, 4844, 4861, 4878, 4895, 4911, 4926,
- 4943, 4959, 4974, 4991, 5007, 5022, 5039, 5055,
- 5069, 5086, 5105, 5134, 5150, 5180, 5210, 5229,
- 5248, 5267, 5286, 5305, 5335, 5365, 5384, 5403,
- 5422, 5441, 5460, 5490, 5520, 5539, 5558, 5577,
- 5596, 5615, 5645, 5675, 5694, 5713, 5732, 5751,
- 5770, 5782, 5812, 5824, 5854, 5884, 5913, 5932,
- 5962, 5992, 6021, 6040, 6070, 6100, 6129, 6148,
- 6178, 6208, 6237, 6256, 6286, 6316, 6345, 6360,
- 6372, 6379, 6382, 6385, 6387, 6394, 6411, 6428,
- 6440, 6449, 6453, 6470, 6487, 6504, 6521, 6537,
- 6552, 6569, 6585, 6600, 6617, 6633, 6648, 6665,
- 6681, 6695, 6712, 6731, 6760, 6776, 6806, 6836,
- 6855, 6874, 6893, 6912, 6931, 6961, 6991, 7010,
- 7029, 7048, 7067, 7086, 7116, 7146, 7165, 7184,
- 7203, 7222, 7241, 7271, 7301, 7320, 7339, 7358,
- 7377, 7396, 7426, 7458, 7488, 7520, 7536, 7555,
- 7585, 7615, 7644, 7651, 7654, 7657, 7659, 7666,
- 7675, 7679, 7709, 7739, 7758, 7775, 7791, 7806,
- 7823, 7839, 7854, 7871, 7887, 7902, 7919, 7935,
- 7947, 7964, 7981, 7993, 8010, 8027, 8046, 8055,
- 8059, 8066, 8069, 8072, 8074
+ 946, 948, 950, 982, 1012, 1042, 1071, 1088,
+ 1118, 1148, 1177, 1194, 1224, 1254, 1283, 1300,
+ 1330, 1360, 1389, 1406, 1436, 1466, 1495, 1506,
+ 1514, 1521, 1524, 1526, 1529, 1532, 1534, 1541,
+ 1553, 1562, 1566, 1575, 1587, 1600, 1613, 1625,
+ 1636, 1649, 1661, 1672, 1685, 1697, 1708, 1721,
+ 1733, 1743, 1756, 1773, 1802, 1814, 1844, 1874,
+ 1891, 1908, 1925, 1942, 1959, 1989, 2019, 2036,
+ 2053, 2070, 2087, 2104, 2134, 2164, 2181, 2198,
+ 2215, 2232, 2249, 2279, 2309, 2326, 2343, 2360,
+ 2377, 2394, 2424, 2454, 2484, 2514, 2543, 2560,
+ 2590, 2620, 2649, 2666, 2696, 2726, 2755, 2772,
+ 2802, 2832, 2861, 2878, 2908, 2938, 2967, 2978,
+ 2986, 2993, 2996, 2998, 3001, 3004, 3006, 3013,
+ 3025, 3034, 3038, 3047, 3059, 3072, 3085, 3097,
+ 3108, 3121, 3133, 3144, 3157, 3169, 3180, 3193,
+ 3205, 3215, 3228, 3245, 3274, 3286, 3316, 3346,
+ 3363, 3380, 3397, 3414, 3431, 3461, 3491, 3508,
+ 3525, 3542, 3559, 3576, 3606, 3636, 3653, 3670,
+ 3687, 3704, 3721, 3751, 3781, 3798, 3815, 3832,
+ 3849, 3861, 3878, 3908, 3938, 3967, 3984, 4014,
+ 4044, 4073, 4090, 4120, 4150, 4179, 4196, 4226,
+ 4256, 4285, 4302, 4332, 4362, 4391, 4402, 4410,
+ 4417, 4420, 4422, 4425, 4428, 4430, 4437, 4449,
+ 4458, 4462, 4471, 4483, 4496, 4509, 4521, 4532,
+ 4545, 4557, 4568, 4581, 4593, 4604, 4617, 4629,
+ 4639, 4652, 4669, 4698, 4710, 4740, 4770, 4787,
+ 4804, 4821, 4838, 4855, 4885, 4915, 4932, 4949,
+ 4966, 4983, 5000, 5030, 5060, 5077, 5094, 5111,
+ 5128, 5145, 5175, 5205, 5222, 5239, 5256, 5273,
+ 5290, 5302, 5332, 5344, 5374, 5404, 5433, 5450,
+ 5480, 5510, 5539, 5556, 5586, 5616, 5645, 5662,
+ 5692, 5722, 5751, 5768, 5798, 5828, 5857, 5868,
+ 5876, 5883, 5886, 5888, 5891, 5894, 5896, 5903,
+ 5915, 5924, 5928, 5937, 5949, 5962, 5975, 5987,
+ 5998, 6011, 6023, 6034, 6047, 6059, 6070, 6083,
+ 6095, 6105, 6118, 6135, 6164, 6176, 6206, 6236,
+ 6253, 6270, 6287, 6304, 6321, 6351, 6381, 6398,
+ 6415, 6432, 6449, 6466, 6496, 6526, 6543, 6560,
+ 6577, 6594, 6611, 6641, 6671, 6688, 6705, 6722,
+ 6739, 6756, 6786, 6818, 6848, 6880, 6892, 6909,
+ 6939, 6969, 6998, 7005, 7008, 7010, 7013, 7016,
+ 7018, 7025, 7055, 7085, 7102, 7115, 7127, 7138,
+ 7151, 7163, 7174, 7187, 7199, 7210, 7223, 7235,
+ 7243, 7255, 7264, 7268, 7277, 7289, 7306, 7315,
+ 7319, 7326, 7329, 7331, 7334, 7337, 7339
};
static const short _indic_syllable_machine_indicies[] = {
@@ -368,911 +368,819 @@ static const short _indic_syllable_machine_indicies[] = {
180, 180, 180, 180, 180, 180, 180, 180,
180, 180, 180, 180, 196, 180, 198, 199,
200, 201, 5, 202, 203, 204, 197, 197,
- 37, 205, 197, 197, 206, 207, 197, 197,
+ 37, 205, 197, 197, 206, 197, 197, 197,
197, 197, 197, 197, 197, 197, 197, 197,
- 197, 197, 208, 197, 209, 199, 210, 210,
+ 197, 197, 207, 197, 208, 199, 209, 209,
5, 202, 203, 204, 197, 197, 197, 205,
- 197, 197, 206, 207, 197, 197, 197, 197,
+ 197, 197, 206, 197, 197, 197, 197, 197,
197, 197, 197, 197, 197, 197, 197, 197,
- 208, 197, 199, 210, 210, 5, 202, 203,
+ 207, 197, 199, 209, 209, 5, 202, 203,
204, 197, 197, 197, 205, 197, 197, 206,
- 207, 197, 197, 197, 197, 197, 197, 197,
- 197, 197, 197, 197, 197, 208, 197, 211,
- 197, 197, 197, 18, 212, 197, 202, 203,
- 204, 197, 197, 197, 213, 197, 211, 197,
- 207, 197, 214, 215, 216, 217, 5, 202,
- 203, 204, 197, 197, 35, 218, 197, 197,
- 206, 207, 197, 197, 197, 197, 197, 197,
- 197, 197, 197, 197, 197, 197, 208, 197,
- 219, 215, 220, 220, 5, 202, 203, 204,
- 197, 197, 197, 218, 197, 197, 206, 207,
197, 197, 197, 197, 197, 197, 197, 197,
- 197, 197, 197, 197, 208, 197, 215, 220,
- 220, 5, 202, 203, 204, 197, 197, 197,
- 218, 197, 197, 206, 207, 197, 197, 197,
+ 197, 197, 197, 197, 197, 207, 197, 210,
+ 197, 197, 197, 18, 211, 197, 202, 203,
+ 204, 197, 197, 197, 212, 197, 210, 197,
+ 213, 214, 215, 216, 5, 202, 203, 204,
+ 197, 197, 35, 217, 197, 197, 206, 197,
197, 197, 197, 197, 197, 197, 197, 197,
- 197, 208, 197, 221, 197, 197, 197, 18,
- 222, 197, 202, 203, 204, 197, 197, 197,
- 213, 197, 221, 197, 207, 197, 223, 224,
- 225, 226, 5, 202, 203, 204, 197, 197,
- 33, 227, 197, 197, 206, 207, 197, 197,
+ 197, 197, 197, 197, 207, 197, 218, 214,
+ 219, 219, 5, 202, 203, 204, 197, 197,
+ 197, 217, 197, 197, 206, 197, 197, 197,
197, 197, 197, 197, 197, 197, 197, 197,
- 197, 197, 208, 197, 228, 224, 229, 229,
- 5, 202, 203, 204, 197, 197, 197, 227,
- 197, 197, 206, 207, 197, 197, 197, 197,
+ 197, 197, 207, 197, 214, 219, 219, 5,
+ 202, 203, 204, 197, 197, 197, 217, 197,
+ 197, 206, 197, 197, 197, 197, 197, 197,
+ 197, 197, 197, 197, 197, 197, 197, 207,
+ 197, 220, 197, 197, 197, 18, 221, 197,
+ 202, 203, 204, 197, 197, 197, 212, 197,
+ 220, 197, 222, 223, 224, 225, 5, 202,
+ 203, 204, 197, 197, 33, 226, 197, 197,
+ 206, 197, 197, 197, 197, 197, 197, 197,
+ 197, 197, 197, 197, 197, 197, 207, 197,
+ 227, 223, 228, 228, 5, 202, 203, 204,
+ 197, 197, 197, 226, 197, 197, 206, 197,
197, 197, 197, 197, 197, 197, 197, 197,
- 208, 197, 224, 229, 229, 5, 202, 203,
- 204, 197, 197, 197, 227, 197, 197, 206,
- 207, 197, 197, 197, 197, 197, 197, 197,
- 197, 197, 197, 197, 197, 208, 197, 230,
- 197, 197, 197, 18, 231, 197, 202, 203,
- 204, 197, 197, 197, 213, 197, 230, 197,
- 207, 197, 232, 233, 234, 235, 5, 202,
- 203, 204, 197, 197, 31, 236, 197, 197,
- 206, 207, 197, 197, 197, 197, 197, 197,
- 197, 197, 197, 197, 197, 197, 208, 197,
- 237, 233, 238, 238, 5, 202, 203, 204,
- 197, 197, 197, 236, 197, 197, 206, 207,
+ 197, 197, 197, 197, 207, 197, 223, 228,
+ 228, 5, 202, 203, 204, 197, 197, 197,
+ 226, 197, 197, 206, 197, 197, 197, 197,
197, 197, 197, 197, 197, 197, 197, 197,
- 197, 197, 197, 197, 208, 197, 233, 238,
- 238, 5, 202, 203, 204, 197, 197, 197,
- 236, 197, 197, 206, 207, 197, 197, 197,
+ 197, 207, 197, 229, 197, 197, 197, 18,
+ 230, 197, 202, 203, 204, 197, 197, 197,
+ 212, 197, 229, 197, 231, 232, 233, 234,
+ 5, 202, 203, 204, 197, 197, 31, 235,
+ 197, 197, 206, 197, 197, 197, 197, 197,
197, 197, 197, 197, 197, 197, 197, 197,
- 197, 208, 197, 239, 197, 197, 197, 18,
- 240, 197, 202, 203, 204, 197, 197, 197,
- 213, 197, 239, 197, 207, 197, 241, 242,
- 243, 244, 5, 202, 203, 204, 197, 197,
- 29, 245, 197, 197, 206, 207, 197, 197,
+ 207, 197, 236, 232, 237, 237, 5, 202,
+ 203, 204, 197, 197, 197, 235, 197, 197,
+ 206, 197, 197, 197, 197, 197, 197, 197,
+ 197, 197, 197, 197, 197, 197, 207, 197,
+ 232, 237, 237, 5, 202, 203, 204, 197,
+ 197, 197, 235, 197, 197, 206, 197, 197,
197, 197, 197, 197, 197, 197, 197, 197,
- 197, 197, 208, 197, 246, 242, 247, 247,
- 5, 202, 203, 204, 197, 197, 197, 245,
- 197, 197, 206, 207, 197, 197, 197, 197,
+ 197, 197, 197, 207, 197, 238, 197, 197,
+ 197, 18, 239, 197, 202, 203, 204, 197,
+ 197, 197, 212, 197, 238, 197, 240, 241,
+ 242, 243, 5, 202, 203, 204, 197, 197,
+ 29, 244, 197, 197, 206, 197, 197, 197,
197, 197, 197, 197, 197, 197, 197, 197,
- 208, 197, 242, 247, 247, 5, 202, 203,
- 204, 197, 197, 197, 245, 197, 197, 206,
- 207, 197, 197, 197, 197, 197, 197, 197,
- 197, 197, 197, 197, 197, 208, 197, 18,
- 248, 197, 202, 203, 204, 197, 197, 197,
- 213, 197, 197, 197, 207, 197, 202, 203,
- 204, 197, 197, 197, 213, 197, 197, 197,
- 207, 197, 249, 197, 197, 250, 203, 204,
- 197, 203, 204, 197, 203, 251, 197, 203,
- 197, 249, 197, 197, 197, 203, 204, 197,
- 252, 197, 253, 254, 197, 202, 203, 204,
- 197, 197, 3, 197, 197, 197, 197, 207,
+ 197, 197, 207, 197, 245, 241, 246, 246,
+ 5, 202, 203, 204, 197, 197, 197, 244,
+ 197, 197, 206, 197, 197, 197, 197, 197,
+ 197, 197, 197, 197, 197, 197, 197, 197,
+ 207, 197, 241, 246, 246, 5, 202, 203,
+ 204, 197, 197, 197, 244, 197, 197, 206,
+ 197, 197, 197, 197, 197, 197, 197, 197,
+ 197, 197, 197, 197, 197, 207, 197, 18,
+ 247, 197, 202, 203, 204, 197, 197, 197,
+ 212, 197, 202, 203, 204, 197, 197, 197,
+ 212, 197, 248, 197, 197, 249, 203, 204,
+ 197, 203, 204, 197, 250, 197, 203, 251,
+ 197, 203, 252, 197, 203, 197, 248, 197,
+ 197, 197, 203, 204, 197, 253, 197, 254,
+ 255, 197, 202, 203, 204, 197, 197, 3,
197, 2, 197, 197, 197, 197, 202, 203,
- 204, 197, 197, 197, 197, 197, 197, 197,
- 207, 197, 202, 203, 204, 197, 197, 197,
- 197, 197, 197, 197, 207, 197, 255, 197,
- 197, 197, 197, 202, 203, 204, 197, 202,
- 203, 204, 197, 252, 197, 197, 197, 197,
- 202, 203, 204, 197, 197, 197, 197, 197,
- 197, 197, 207, 197, 252, 197, 253, 197,
- 197, 202, 203, 204, 197, 197, 3, 197,
- 197, 197, 197, 207, 197, 18, 197, 256,
- 256, 5, 202, 203, 204, 197, 197, 197,
- 213, 197, 197, 197, 207, 197, 257, 27,
- 258, 259, 8, 202, 203, 204, 197, 197,
- 197, 213, 197, 197, 197, 207, 197, 27,
- 258, 259, 8, 202, 203, 204, 197, 197,
- 197, 213, 197, 197, 197, 207, 197, 258,
- 258, 8, 202, 203, 204, 197, 197, 197,
- 213, 197, 197, 197, 207, 197, 260, 24,
- 261, 262, 11, 202, 203, 204, 197, 197,
- 197, 213, 197, 197, 197, 207, 197, 24,
- 261, 262, 11, 202, 203, 204, 197, 197,
- 197, 213, 197, 197, 197, 207, 197, 261,
- 261, 11, 202, 203, 204, 197, 197, 197,
- 213, 197, 197, 197, 207, 197, 263, 21,
- 264, 265, 14, 202, 203, 204, 197, 197,
- 197, 213, 197, 197, 197, 207, 197, 21,
- 264, 265, 14, 202, 203, 204, 197, 197,
- 197, 213, 197, 197, 197, 207, 197, 264,
- 264, 14, 202, 203, 204, 197, 197, 197,
- 213, 197, 197, 197, 207, 197, 266, 18,
- 197, 267, 197, 202, 203, 204, 197, 197,
- 197, 213, 197, 197, 197, 207, 197, 18,
- 197, 267, 197, 202, 203, 204, 197, 197,
- 197, 213, 197, 197, 197, 207, 197, 268,
- 197, 202, 203, 204, 197, 197, 197, 213,
- 197, 197, 197, 207, 197, 18, 197, 197,
- 197, 197, 202, 203, 204, 197, 197, 197,
- 213, 197, 197, 197, 207, 197, 1, 2,
- 197, 197, 18, 248, 197, 202, 203, 204,
- 197, 197, 197, 213, 197, 1, 197, 207,
- 197, 242, 247, 247, 5, 202, 203, 204,
- 197, 197, 197, 245, 197, 197, 197, 207,
+ 204, 197, 202, 203, 204, 197, 253, 197,
+ 197, 197, 197, 202, 203, 204, 197, 253,
+ 197, 254, 197, 197, 202, 203, 204, 197,
+ 197, 3, 197, 18, 197, 256, 256, 5,
+ 202, 203, 204, 197, 197, 197, 212, 197,
+ 257, 27, 258, 259, 8, 202, 203, 204,
+ 197, 197, 197, 212, 197, 27, 258, 259,
+ 8, 202, 203, 204, 197, 197, 197, 212,
+ 197, 258, 258, 8, 202, 203, 204, 197,
+ 197, 197, 212, 197, 260, 24, 261, 262,
+ 11, 202, 203, 204, 197, 197, 197, 212,
+ 197, 24, 261, 262, 11, 202, 203, 204,
+ 197, 197, 197, 212, 197, 261, 261, 11,
+ 202, 203, 204, 197, 197, 197, 212, 197,
+ 263, 21, 264, 265, 14, 202, 203, 204,
+ 197, 197, 197, 212, 197, 21, 264, 265,
+ 14, 202, 203, 204, 197, 197, 197, 212,
+ 197, 264, 264, 14, 202, 203, 204, 197,
+ 197, 197, 212, 197, 266, 18, 197, 267,
+ 197, 202, 203, 204, 197, 197, 197, 212,
+ 197, 18, 197, 267, 197, 202, 203, 204,
+ 197, 197, 197, 212, 197, 268, 197, 202,
+ 203, 204, 197, 197, 197, 212, 197, 18,
+ 197, 197, 197, 197, 202, 203, 204, 197,
+ 197, 197, 212, 197, 1, 2, 197, 197,
+ 18, 247, 197, 202, 203, 204, 197, 197,
+ 197, 212, 197, 1, 197, 241, 246, 246,
+ 5, 202, 203, 204, 197, 197, 197, 244,
197, 197, 197, 197, 197, 197, 197, 197,
- 197, 197, 197, 197, 208, 197, 242, 247,
- 247, 5, 202, 203, 204, 197, 197, 197,
- 245, 197, 197, 197, 207, 197, 241, 242,
- 247, 247, 5, 202, 203, 204, 197, 197,
- 197, 245, 197, 197, 206, 207, 197, 197,
197, 197, 197, 197, 197, 197, 197, 197,
- 197, 197, 208, 197, 241, 242, 243, 247,
- 5, 202, 203, 204, 197, 197, 29, 245,
- 197, 197, 206, 207, 197, 197, 197, 197,
+ 207, 197, 241, 246, 246, 5, 202, 203,
+ 204, 197, 197, 197, 244, 197, 240, 241,
+ 246, 246, 5, 202, 203, 204, 197, 197,
+ 197, 244, 197, 197, 206, 197, 197, 197,
197, 197, 197, 197, 197, 197, 197, 197,
- 208, 197, 239, 197, 269, 197, 256, 256,
- 5, 202, 203, 204, 197, 197, 197, 213,
- 197, 239, 197, 207, 197, 239, 197, 197,
- 197, 197, 197, 197, 202, 203, 204, 197,
- 197, 197, 213, 197, 239, 197, 207, 197,
- 239, 197, 197, 197, 197, 270, 197, 202,
- 203, 204, 197, 197, 197, 213, 197, 239,
- 197, 207, 197, 239, 197, 269, 197, 197,
+ 197, 197, 207, 197, 240, 241, 242, 246,
+ 5, 202, 203, 204, 197, 197, 29, 244,
+ 197, 197, 206, 197, 197, 197, 197, 197,
+ 197, 197, 197, 197, 197, 197, 197, 197,
+ 207, 197, 238, 197, 269, 197, 256, 256,
+ 5, 202, 203, 204, 197, 197, 197, 212,
+ 197, 238, 197, 238, 197, 197, 197, 197,
197, 197, 202, 203, 204, 197, 197, 197,
- 213, 197, 239, 197, 207, 197, 239, 2,
- 197, 197, 18, 240, 197, 202, 203, 204,
- 197, 197, 197, 213, 197, 239, 197, 207,
- 197, 232, 233, 238, 238, 5, 202, 203,
- 204, 197, 197, 197, 236, 197, 197, 206,
- 207, 197, 197, 197, 197, 197, 197, 197,
- 197, 197, 197, 197, 197, 208, 197, 232,
- 233, 234, 238, 5, 202, 203, 204, 197,
- 197, 31, 236, 197, 197, 206, 207, 197,
+ 212, 197, 238, 197, 238, 197, 197, 197,
+ 197, 270, 197, 202, 203, 204, 197, 197,
+ 197, 212, 197, 238, 197, 238, 197, 269,
+ 197, 197, 197, 197, 202, 203, 204, 197,
+ 197, 197, 212, 197, 238, 197, 238, 2,
+ 197, 197, 18, 239, 197, 202, 203, 204,
+ 197, 197, 197, 212, 197, 238, 197, 231,
+ 232, 237, 237, 5, 202, 203, 204, 197,
+ 197, 197, 235, 197, 197, 206, 197, 197,
197, 197, 197, 197, 197, 197, 197, 197,
- 197, 197, 197, 208, 197, 230, 197, 271,
- 197, 256, 256, 5, 202, 203, 204, 197,
- 197, 197, 213, 197, 230, 197, 207, 197,
- 230, 197, 197, 197, 197, 197, 197, 202,
- 203, 204, 197, 197, 197, 213, 197, 230,
- 197, 207, 197, 230, 197, 197, 197, 197,
- 272, 197, 202, 203, 204, 197, 197, 197,
- 213, 197, 230, 197, 207, 197, 230, 197,
+ 197, 197, 197, 207, 197, 231, 232, 233,
+ 237, 5, 202, 203, 204, 197, 197, 31,
+ 235, 197, 197, 206, 197, 197, 197, 197,
+ 197, 197, 197, 197, 197, 197, 197, 197,
+ 197, 207, 197, 229, 197, 271, 197, 256,
+ 256, 5, 202, 203, 204, 197, 197, 197,
+ 212, 197, 229, 197, 229, 197, 197, 197,
+ 197, 197, 197, 202, 203, 204, 197, 197,
+ 197, 212, 197, 229, 197, 229, 197, 197,
+ 197, 197, 272, 197, 202, 203, 204, 197,
+ 197, 197, 212, 197, 229, 197, 229, 197,
271, 197, 197, 197, 197, 202, 203, 204,
- 197, 197, 197, 213, 197, 230, 197, 207,
- 197, 230, 2, 197, 197, 18, 231, 197,
- 202, 203, 204, 197, 197, 197, 213, 197,
- 230, 197, 207, 197, 223, 224, 229, 229,
- 5, 202, 203, 204, 197, 197, 197, 227,
- 197, 197, 206, 207, 197, 197, 197, 197,
+ 197, 197, 197, 212, 197, 229, 197, 229,
+ 2, 197, 197, 18, 230, 197, 202, 203,
+ 204, 197, 197, 197, 212, 197, 229, 197,
+ 222, 223, 228, 228, 5, 202, 203, 204,
+ 197, 197, 197, 226, 197, 197, 206, 197,
197, 197, 197, 197, 197, 197, 197, 197,
- 208, 197, 223, 224, 225, 229, 5, 202,
- 203, 204, 197, 197, 33, 227, 197, 197,
- 206, 207, 197, 197, 197, 197, 197, 197,
- 197, 197, 197, 197, 197, 197, 208, 197,
- 221, 197, 273, 197, 256, 256, 5, 202,
- 203, 204, 197, 197, 197, 213, 197, 221,
- 197, 207, 197, 221, 197, 197, 197, 197,
- 197, 197, 202, 203, 204, 197, 197, 197,
- 213, 197, 221, 197, 207, 197, 221, 197,
+ 197, 197, 197, 197, 207, 197, 222, 223,
+ 224, 228, 5, 202, 203, 204, 197, 197,
+ 33, 226, 197, 197, 206, 197, 197, 197,
+ 197, 197, 197, 197, 197, 197, 197, 197,
+ 197, 197, 207, 197, 220, 197, 273, 197,
+ 256, 256, 5, 202, 203, 204, 197, 197,
+ 197, 212, 197, 220, 197, 220, 197, 197,
+ 197, 197, 197, 197, 202, 203, 204, 197,
+ 197, 197, 212, 197, 220, 197, 220, 197,
197, 197, 197, 274, 197, 202, 203, 204,
- 197, 197, 197, 213, 197, 221, 197, 207,
- 197, 221, 197, 273, 197, 197, 197, 197,
- 202, 203, 204, 197, 197, 197, 213, 197,
- 221, 197, 207, 197, 221, 2, 197, 197,
- 18, 222, 197, 202, 203, 204, 197, 197,
- 197, 213, 197, 221, 197, 207, 197, 214,
- 215, 220, 220, 5, 202, 203, 204, 197,
- 197, 197, 218, 197, 197, 206, 207, 197,
+ 197, 197, 197, 212, 197, 220, 197, 220,
+ 197, 273, 197, 197, 197, 197, 202, 203,
+ 204, 197, 197, 197, 212, 197, 220, 197,
+ 220, 2, 197, 197, 18, 221, 197, 202,
+ 203, 204, 197, 197, 197, 212, 197, 220,
+ 197, 213, 214, 219, 219, 5, 202, 203,
+ 204, 197, 197, 197, 217, 197, 197, 206,
197, 197, 197, 197, 197, 197, 197, 197,
- 197, 197, 197, 208, 197, 214, 215, 216,
- 220, 5, 202, 203, 204, 197, 197, 35,
- 218, 197, 197, 206, 207, 197, 197, 197,
+ 197, 197, 197, 197, 197, 207, 197, 213,
+ 214, 215, 219, 5, 202, 203, 204, 197,
+ 197, 35, 217, 197, 197, 206, 197, 197,
197, 197, 197, 197, 197, 197, 197, 197,
- 197, 208, 197, 211, 197, 275, 197, 256,
- 256, 5, 202, 203, 204, 197, 197, 197,
- 213, 197, 211, 197, 207, 197, 211, 197,
+ 197, 197, 197, 207, 197, 210, 197, 275,
+ 197, 256, 256, 5, 202, 203, 204, 197,
+ 197, 197, 212, 197, 210, 197, 210, 197,
197, 197, 197, 197, 197, 202, 203, 204,
- 197, 197, 197, 213, 197, 211, 197, 207,
- 197, 211, 197, 197, 197, 197, 276, 197,
- 202, 203, 204, 197, 197, 197, 213, 197,
- 211, 197, 207, 197, 211, 197, 275, 197,
- 197, 197, 197, 202, 203, 204, 197, 197,
- 197, 213, 197, 211, 197, 207, 197, 211,
- 2, 197, 197, 18, 212, 197, 202, 203,
- 204, 197, 197, 197, 213, 197, 211, 197,
- 207, 197, 198, 199, 210, 210, 5, 202,
+ 197, 197, 197, 212, 197, 210, 197, 210,
+ 197, 197, 197, 197, 276, 197, 202, 203,
+ 204, 197, 197, 197, 212, 197, 210, 197,
+ 210, 197, 275, 197, 197, 197, 197, 202,
+ 203, 204, 197, 197, 197, 212, 197, 210,
+ 197, 210, 2, 197, 197, 18, 211, 197,
+ 202, 203, 204, 197, 197, 197, 212, 197,
+ 210, 197, 198, 199, 209, 209, 5, 202,
203, 204, 197, 197, 197, 205, 197, 197,
- 206, 207, 197, 197, 197, 197, 197, 197,
- 197, 197, 197, 197, 197, 197, 208, 197,
- 198, 199, 200, 210, 5, 202, 203, 204,
- 197, 197, 37, 205, 197, 197, 206, 207,
+ 206, 197, 197, 197, 197, 197, 197, 197,
+ 197, 197, 197, 197, 197, 197, 207, 197,
+ 198, 199, 200, 209, 5, 202, 203, 204,
+ 197, 197, 37, 205, 197, 197, 206, 197,
197, 197, 197, 197, 197, 197, 197, 197,
- 197, 197, 197, 197, 208, 197, 278, 279,
+ 197, 197, 197, 197, 207, 197, 278, 279,
280, 281, 43, 282, 283, 284, 277, 277,
- 75, 285, 277, 277, 286, 287, 277, 277,
+ 75, 285, 277, 277, 286, 277, 277, 277,
277, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 288, 277, 289, 279, 290, 281,
+ 277, 277, 287, 277, 288, 279, 289, 281,
43, 282, 283, 284, 277, 277, 277, 285,
- 277, 277, 286, 287, 277, 277, 277, 277,
+ 277, 277, 286, 277, 277, 277, 277, 277,
277, 277, 277, 277, 277, 277, 277, 277,
- 288, 277, 279, 290, 281, 43, 282, 283,
+ 287, 277, 279, 289, 281, 43, 282, 283,
284, 277, 277, 277, 285, 277, 277, 286,
- 287, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 277, 277, 277, 288, 277, 291,
- 277, 277, 277, 56, 292, 277, 282, 283,
- 284, 277, 277, 277, 293, 277, 291, 277,
- 287, 277, 294, 295, 296, 297, 43, 282,
- 283, 284, 277, 277, 73, 298, 277, 277,
- 286, 287, 277, 277, 277, 277, 277, 277,
- 277, 277, 277, 277, 277, 277, 288, 277,
- 299, 295, 300, 300, 43, 282, 283, 284,
- 277, 277, 277, 298, 277, 277, 286, 287,
277, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 277, 277, 288, 277, 295, 300,
- 300, 43, 282, 283, 284, 277, 277, 277,
- 298, 277, 277, 286, 287, 277, 277, 277,
+ 277, 277, 277, 277, 277, 287, 277, 290,
+ 277, 277, 277, 56, 291, 277, 282, 283,
+ 284, 277, 277, 277, 292, 277, 290, 277,
+ 293, 294, 295, 296, 43, 282, 283, 284,
+ 277, 277, 73, 297, 277, 277, 286, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 287, 277, 298, 294,
+ 299, 299, 43, 282, 283, 284, 277, 277,
+ 277, 297, 277, 277, 286, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 287, 277, 294, 299, 299, 43,
+ 282, 283, 284, 277, 277, 277, 297, 277,
+ 277, 286, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 287,
+ 277, 300, 277, 277, 277, 56, 301, 277,
+ 282, 283, 284, 277, 277, 277, 292, 277,
+ 300, 277, 302, 303, 304, 305, 43, 282,
+ 283, 284, 277, 277, 71, 306, 277, 277,
+ 286, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 287, 277,
+ 307, 303, 308, 308, 43, 282, 283, 284,
+ 277, 277, 277, 306, 277, 277, 286, 277,
277, 277, 277, 277, 277, 277, 277, 277,
- 277, 288, 277, 301, 277, 277, 277, 56,
- 302, 277, 282, 283, 284, 277, 277, 277,
- 293, 277, 301, 277, 287, 277, 303, 304,
- 305, 306, 43, 282, 283, 284, 277, 277,
- 71, 307, 277, 277, 286, 287, 277, 277,
+ 277, 277, 277, 277, 287, 277, 303, 308,
+ 308, 43, 282, 283, 284, 277, 277, 277,
+ 306, 277, 277, 286, 277, 277, 277, 277,
277, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 288, 277, 308, 304, 309, 309,
- 43, 282, 283, 284, 277, 277, 277, 307,
- 277, 277, 286, 287, 277, 277, 277, 277,
+ 277, 287, 277, 309, 277, 277, 277, 56,
+ 310, 277, 282, 283, 284, 277, 277, 277,
+ 292, 277, 309, 277, 311, 312, 313, 314,
+ 43, 282, 283, 284, 277, 277, 69, 315,
+ 277, 277, 286, 277, 277, 277, 277, 277,
277, 277, 277, 277, 277, 277, 277, 277,
- 288, 277, 304, 309, 309, 43, 282, 283,
- 284, 277, 277, 277, 307, 277, 277, 286,
- 287, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 277, 277, 277, 288, 277, 310,
- 277, 277, 277, 56, 311, 277, 282, 283,
- 284, 277, 277, 277, 293, 277, 310, 277,
- 287, 277, 312, 313, 314, 315, 43, 282,
- 283, 284, 277, 277, 69, 316, 277, 277,
- 286, 287, 277, 277, 277, 277, 277, 277,
- 277, 277, 277, 277, 277, 277, 288, 277,
- 317, 313, 318, 318, 43, 282, 283, 284,
- 277, 277, 277, 316, 277, 277, 286, 287,
+ 287, 277, 316, 312, 317, 317, 43, 282,
+ 283, 284, 277, 277, 277, 315, 277, 277,
+ 286, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 287, 277,
+ 312, 317, 317, 43, 282, 283, 284, 277,
+ 277, 277, 315, 277, 277, 286, 277, 277,
277, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 277, 277, 288, 277, 313, 318,
- 318, 43, 282, 283, 284, 277, 277, 277,
- 316, 277, 277, 286, 287, 277, 277, 277,
+ 277, 277, 277, 287, 277, 318, 277, 277,
+ 277, 56, 319, 277, 282, 283, 284, 277,
+ 277, 277, 292, 277, 318, 277, 320, 321,
+ 322, 323, 43, 282, 283, 284, 277, 277,
+ 67, 324, 277, 277, 286, 277, 277, 277,
277, 277, 277, 277, 277, 277, 277, 277,
- 277, 288, 277, 319, 277, 277, 277, 56,
- 320, 277, 282, 283, 284, 277, 277, 277,
- 293, 277, 319, 277, 287, 277, 321, 322,
- 323, 324, 43, 282, 283, 284, 277, 277,
- 67, 325, 277, 277, 286, 287, 277, 277,
+ 277, 277, 287, 277, 325, 321, 326, 326,
+ 43, 282, 283, 284, 277, 277, 277, 324,
+ 277, 277, 286, 277, 277, 277, 277, 277,
277, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 288, 277, 326, 322, 327, 327,
- 43, 282, 283, 284, 277, 277, 277, 325,
- 277, 277, 286, 287, 277, 277, 277, 277,
+ 287, 277, 321, 326, 326, 43, 282, 283,
+ 284, 277, 277, 277, 324, 277, 277, 286,
277, 277, 277, 277, 277, 277, 277, 277,
- 288, 277, 322, 327, 327, 43, 282, 283,
- 284, 277, 277, 277, 325, 277, 277, 286,
- 287, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 277, 277, 277, 288, 277, 56,
- 328, 277, 282, 283, 284, 277, 277, 277,
- 293, 277, 277, 277, 287, 277, 282, 283,
- 284, 277, 277, 277, 293, 277, 277, 277,
- 287, 277, 329, 277, 277, 330, 283, 284,
- 277, 283, 284, 277, 283, 331, 277, 283,
- 277, 329, 277, 277, 277, 283, 284, 277,
- 332, 277, 333, 334, 277, 282, 283, 284,
- 277, 277, 41, 277, 277, 277, 277, 287,
+ 277, 277, 277, 277, 277, 287, 277, 56,
+ 327, 277, 282, 283, 284, 277, 277, 277,
+ 292, 277, 282, 283, 284, 277, 277, 277,
+ 292, 277, 328, 277, 277, 329, 283, 284,
+ 277, 283, 284, 277, 330, 277, 283, 331,
+ 277, 283, 332, 277, 283, 277, 328, 277,
+ 277, 277, 283, 284, 277, 333, 277, 334,
+ 335, 277, 282, 283, 284, 277, 277, 41,
277, 40, 277, 277, 277, 277, 282, 283,
- 284, 277, 277, 277, 277, 277, 277, 277,
- 287, 277, 282, 283, 284, 277, 277, 277,
- 277, 277, 277, 277, 287, 277, 335, 277,
- 277, 277, 277, 282, 283, 284, 277, 282,
- 283, 284, 277, 332, 277, 277, 277, 277,
- 282, 283, 284, 277, 277, 277, 277, 277,
- 277, 277, 287, 277, 332, 277, 333, 277,
- 277, 282, 283, 284, 277, 277, 41, 277,
- 277, 277, 277, 287, 277, 56, 277, 336,
- 336, 43, 282, 283, 284, 277, 277, 277,
- 293, 277, 277, 277, 287, 277, 337, 65,
- 338, 339, 46, 282, 283, 284, 277, 277,
- 277, 293, 277, 277, 277, 287, 277, 65,
- 338, 339, 46, 282, 283, 284, 277, 277,
- 277, 293, 277, 277, 277, 287, 277, 338,
- 338, 46, 282, 283, 284, 277, 277, 277,
- 293, 277, 277, 277, 287, 277, 340, 62,
- 341, 342, 49, 282, 283, 284, 277, 277,
- 277, 293, 277, 277, 277, 287, 277, 62,
- 341, 342, 49, 282, 283, 284, 277, 277,
- 277, 293, 277, 277, 277, 287, 277, 341,
- 341, 49, 282, 283, 284, 277, 277, 277,
- 293, 277, 277, 277, 287, 277, 343, 59,
- 344, 345, 52, 282, 283, 284, 277, 277,
- 277, 293, 277, 277, 277, 287, 277, 59,
- 344, 345, 52, 282, 283, 284, 277, 277,
- 277, 293, 277, 277, 277, 287, 277, 344,
- 344, 52, 282, 283, 284, 277, 277, 277,
- 293, 277, 277, 277, 287, 277, 346, 56,
- 277, 347, 277, 282, 283, 284, 277, 277,
- 277, 293, 277, 277, 277, 287, 277, 56,
- 277, 347, 277, 282, 283, 284, 277, 277,
- 277, 293, 277, 277, 277, 287, 277, 348,
- 277, 282, 283, 284, 277, 277, 277, 293,
- 277, 277, 277, 287, 277, 56, 277, 277,
- 277, 277, 282, 283, 284, 277, 277, 277,
- 293, 277, 277, 277, 287, 277, 39, 40,
- 277, 277, 56, 328, 277, 282, 283, 284,
- 277, 277, 277, 293, 277, 39, 277, 287,
- 277, 322, 327, 327, 43, 282, 283, 284,
- 277, 277, 277, 325, 277, 277, 277, 287,
+ 284, 277, 282, 283, 284, 277, 333, 277,
+ 277, 277, 277, 282, 283, 284, 277, 333,
+ 277, 334, 277, 277, 282, 283, 284, 277,
+ 277, 41, 277, 56, 277, 336, 336, 43,
+ 282, 283, 284, 277, 277, 277, 292, 277,
+ 337, 65, 338, 339, 46, 282, 283, 284,
+ 277, 277, 277, 292, 277, 65, 338, 339,
+ 46, 282, 283, 284, 277, 277, 277, 292,
+ 277, 338, 338, 46, 282, 283, 284, 277,
+ 277, 277, 292, 277, 340, 62, 341, 342,
+ 49, 282, 283, 284, 277, 277, 277, 292,
+ 277, 62, 341, 342, 49, 282, 283, 284,
+ 277, 277, 277, 292, 277, 341, 341, 49,
+ 282, 283, 284, 277, 277, 277, 292, 277,
+ 343, 59, 344, 345, 52, 282, 283, 284,
+ 277, 277, 277, 292, 277, 59, 344, 345,
+ 52, 282, 283, 284, 277, 277, 277, 292,
+ 277, 344, 344, 52, 282, 283, 284, 277,
+ 277, 277, 292, 277, 346, 56, 277, 347,
+ 277, 282, 283, 284, 277, 277, 277, 292,
+ 277, 56, 277, 347, 277, 282, 283, 284,
+ 277, 277, 277, 292, 277, 348, 277, 282,
+ 283, 284, 277, 277, 277, 292, 277, 56,
+ 277, 277, 277, 277, 282, 283, 284, 277,
+ 277, 277, 292, 277, 39, 40, 277, 277,
+ 56, 327, 277, 282, 283, 284, 277, 277,
+ 277, 292, 277, 39, 277, 321, 326, 326,
+ 43, 282, 283, 284, 277, 277, 277, 324,
277, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 277, 277, 288, 277, 322, 327,
- 327, 43, 282, 283, 284, 277, 277, 277,
- 325, 277, 277, 277, 287, 277, 321, 322,
- 327, 327, 43, 282, 283, 284, 277, 277,
- 277, 325, 277, 277, 286, 287, 277, 277,
277, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 288, 277, 321, 322, 323, 327,
- 43, 282, 283, 284, 277, 277, 67, 325,
- 277, 277, 286, 287, 277, 277, 277, 277,
+ 287, 277, 321, 326, 326, 43, 282, 283,
+ 284, 277, 277, 277, 324, 277, 320, 321,
+ 326, 326, 43, 282, 283, 284, 277, 277,
+ 277, 324, 277, 277, 286, 277, 277, 277,
277, 277, 277, 277, 277, 277, 277, 277,
- 288, 277, 319, 277, 349, 277, 336, 336,
- 43, 282, 283, 284, 277, 277, 277, 293,
- 277, 319, 277, 287, 277, 319, 277, 277,
- 277, 277, 277, 277, 282, 283, 284, 277,
- 277, 277, 293, 277, 319, 277, 287, 277,
- 319, 277, 277, 277, 277, 350, 277, 282,
- 283, 284, 277, 277, 277, 293, 277, 319,
- 277, 287, 277, 319, 277, 349, 277, 277,
+ 277, 277, 287, 277, 320, 321, 322, 326,
+ 43, 282, 283, 284, 277, 277, 67, 324,
+ 277, 277, 286, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277,
+ 287, 277, 318, 277, 349, 277, 336, 336,
+ 43, 282, 283, 284, 277, 277, 277, 292,
+ 277, 318, 277, 318, 277, 277, 277, 277,
277, 277, 282, 283, 284, 277, 277, 277,
- 293, 277, 319, 277, 287, 277, 319, 40,
- 277, 277, 56, 320, 277, 282, 283, 284,
- 277, 277, 277, 293, 277, 319, 277, 287,
- 277, 312, 313, 318, 318, 43, 282, 283,
- 284, 277, 277, 277, 316, 277, 277, 286,
- 287, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 277, 277, 277, 288, 277, 312,
- 313, 314, 318, 43, 282, 283, 284, 277,
- 277, 69, 316, 277, 277, 286, 287, 277,
+ 292, 277, 318, 277, 318, 277, 277, 277,
+ 277, 350, 277, 282, 283, 284, 277, 277,
+ 277, 292, 277, 318, 277, 318, 277, 349,
+ 277, 277, 277, 277, 282, 283, 284, 277,
+ 277, 277, 292, 277, 318, 277, 318, 40,
+ 277, 277, 56, 319, 277, 282, 283, 284,
+ 277, 277, 277, 292, 277, 318, 277, 311,
+ 312, 317, 317, 43, 282, 283, 284, 277,
+ 277, 277, 315, 277, 277, 286, 277, 277,
277, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 277, 288, 277, 310, 277, 351,
- 277, 336, 336, 43, 282, 283, 284, 277,
- 277, 277, 293, 277, 310, 277, 287, 277,
- 310, 277, 277, 277, 277, 277, 277, 282,
- 283, 284, 277, 277, 277, 293, 277, 310,
- 277, 287, 277, 310, 277, 277, 277, 277,
- 352, 277, 282, 283, 284, 277, 277, 277,
- 293, 277, 310, 277, 287, 277, 310, 277,
+ 277, 277, 277, 287, 277, 311, 312, 313,
+ 317, 43, 282, 283, 284, 277, 277, 69,
+ 315, 277, 277, 286, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 287, 277, 309, 277, 351, 277, 336,
+ 336, 43, 282, 283, 284, 277, 277, 277,
+ 292, 277, 309, 277, 309, 277, 277, 277,
+ 277, 277, 277, 282, 283, 284, 277, 277,
+ 277, 292, 277, 309, 277, 309, 277, 277,
+ 277, 277, 352, 277, 282, 283, 284, 277,
+ 277, 277, 292, 277, 309, 277, 309, 277,
351, 277, 277, 277, 277, 282, 283, 284,
- 277, 277, 277, 293, 277, 310, 277, 287,
- 277, 310, 40, 277, 277, 56, 311, 277,
- 282, 283, 284, 277, 277, 277, 293, 277,
- 310, 277, 287, 277, 303, 304, 309, 309,
- 43, 282, 283, 284, 277, 277, 277, 307,
- 277, 277, 286, 287, 277, 277, 277, 277,
+ 277, 277, 277, 292, 277, 309, 277, 309,
+ 40, 277, 277, 56, 310, 277, 282, 283,
+ 284, 277, 277, 277, 292, 277, 309, 277,
+ 302, 303, 308, 308, 43, 282, 283, 284,
+ 277, 277, 277, 306, 277, 277, 286, 277,
277, 277, 277, 277, 277, 277, 277, 277,
- 288, 277, 303, 304, 305, 309, 43, 282,
- 283, 284, 277, 277, 71, 307, 277, 277,
- 286, 287, 277, 277, 277, 277, 277, 277,
- 277, 277, 277, 277, 277, 277, 288, 277,
- 301, 277, 353, 277, 336, 336, 43, 282,
- 283, 284, 277, 277, 277, 293, 277, 301,
- 277, 287, 277, 301, 277, 277, 277, 277,
- 277, 277, 282, 283, 284, 277, 277, 277,
- 293, 277, 301, 277, 287, 277, 301, 277,
+ 277, 277, 277, 277, 287, 277, 302, 303,
+ 304, 308, 43, 282, 283, 284, 277, 277,
+ 71, 306, 277, 277, 286, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 287, 277, 300, 277, 353, 277,
+ 336, 336, 43, 282, 283, 284, 277, 277,
+ 277, 292, 277, 300, 277, 300, 277, 277,
+ 277, 277, 277, 277, 282, 283, 284, 277,
+ 277, 277, 292, 277, 300, 277, 300, 277,
277, 277, 277, 354, 277, 282, 283, 284,
- 277, 277, 277, 293, 277, 301, 277, 287,
- 277, 301, 277, 353, 277, 277, 277, 277,
- 282, 283, 284, 277, 277, 277, 293, 277,
- 301, 277, 287, 277, 301, 40, 277, 277,
- 56, 302, 277, 282, 283, 284, 277, 277,
- 277, 293, 277, 301, 277, 287, 277, 294,
- 295, 300, 300, 43, 282, 283, 284, 277,
- 277, 277, 298, 277, 277, 286, 287, 277,
+ 277, 277, 277, 292, 277, 300, 277, 300,
+ 277, 353, 277, 277, 277, 277, 282, 283,
+ 284, 277, 277, 277, 292, 277, 300, 277,
+ 300, 40, 277, 277, 56, 301, 277, 282,
+ 283, 284, 277, 277, 277, 292, 277, 300,
+ 277, 293, 294, 299, 299, 43, 282, 283,
+ 284, 277, 277, 277, 297, 277, 277, 286,
277, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 277, 288, 277, 294, 295, 296,
- 300, 43, 282, 283, 284, 277, 277, 73,
- 298, 277, 277, 286, 287, 277, 277, 277,
+ 277, 277, 277, 277, 277, 287, 277, 293,
+ 294, 295, 299, 43, 282, 283, 284, 277,
+ 277, 73, 297, 277, 277, 286, 277, 277,
277, 277, 277, 277, 277, 277, 277, 277,
- 277, 288, 277, 291, 277, 355, 277, 336,
- 336, 43, 282, 283, 284, 277, 277, 277,
- 293, 277, 291, 277, 287, 277, 291, 277,
+ 277, 277, 277, 287, 277, 290, 277, 355,
+ 277, 336, 336, 43, 282, 283, 284, 277,
+ 277, 277, 292, 277, 290, 277, 290, 277,
277, 277, 277, 277, 277, 282, 283, 284,
- 277, 277, 277, 293, 277, 291, 277, 287,
- 277, 291, 277, 277, 277, 277, 356, 277,
- 282, 283, 284, 277, 277, 277, 293, 277,
- 291, 277, 287, 277, 291, 277, 355, 277,
- 277, 277, 277, 282, 283, 284, 277, 277,
- 277, 293, 277, 291, 277, 287, 277, 74,
- 42, 42, 43, 277, 277, 277, 277, 277,
- 277, 74, 277, 291, 40, 277, 277, 56,
- 292, 277, 282, 283, 284, 277, 277, 277,
- 293, 277, 291, 277, 287, 277, 278, 279,
- 290, 281, 43, 282, 283, 284, 277, 277,
- 277, 285, 277, 277, 286, 287, 277, 277,
+ 277, 277, 277, 292, 277, 290, 277, 290,
+ 277, 277, 277, 277, 356, 277, 282, 283,
+ 284, 277, 277, 277, 292, 277, 290, 277,
+ 290, 277, 355, 277, 277, 277, 277, 282,
+ 283, 284, 277, 277, 277, 292, 277, 290,
+ 277, 74, 42, 42, 43, 277, 277, 277,
+ 277, 277, 277, 74, 277, 290, 40, 277,
+ 277, 56, 291, 277, 282, 283, 284, 277,
+ 277, 277, 292, 277, 290, 277, 278, 279,
+ 289, 281, 43, 282, 283, 284, 277, 277,
+ 277, 285, 277, 277, 286, 277, 277, 277,
277, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 288, 277, 358, 184, 359, 359,
+ 277, 277, 287, 277, 358, 184, 359, 359,
81, 187, 188, 189, 357, 357, 357, 191,
- 357, 357, 194, 360, 357, 357, 357, 357,
+ 357, 357, 194, 357, 357, 357, 357, 357,
357, 357, 357, 357, 357, 357, 357, 357,
196, 357, 184, 359, 359, 81, 187, 188,
189, 357, 357, 357, 191, 357, 357, 194,
- 360, 357, 357, 357, 357, 357, 357, 357,
- 357, 357, 357, 357, 357, 196, 357, 361,
- 357, 357, 357, 95, 362, 357, 187, 188,
- 189, 357, 357, 357, 363, 357, 361, 357,
- 360, 357, 364, 365, 366, 367, 81, 187,
- 188, 189, 357, 357, 112, 368, 357, 357,
- 194, 360, 357, 357, 357, 357, 357, 357,
- 357, 357, 357, 357, 357, 357, 196, 357,
- 369, 365, 370, 370, 81, 187, 188, 189,
- 357, 357, 357, 368, 357, 357, 194, 360,
357, 357, 357, 357, 357, 357, 357, 357,
- 357, 357, 357, 357, 196, 357, 365, 370,
- 370, 81, 187, 188, 189, 357, 357, 357,
- 368, 357, 357, 194, 360, 357, 357, 357,
+ 357, 357, 357, 357, 357, 196, 357, 360,
+ 357, 357, 357, 95, 361, 357, 187, 188,
+ 189, 357, 357, 357, 362, 357, 360, 357,
+ 363, 364, 365, 366, 81, 187, 188, 189,
+ 357, 357, 112, 367, 357, 357, 194, 357,
+ 357, 357, 357, 357, 357, 357, 357, 357,
+ 357, 357, 357, 357, 196, 357, 368, 364,
+ 369, 369, 81, 187, 188, 189, 357, 357,
+ 357, 367, 357, 357, 194, 357, 357, 357,
357, 357, 357, 357, 357, 357, 357, 357,
- 357, 196, 357, 371, 357, 357, 357, 95,
- 372, 357, 187, 188, 189, 357, 357, 357,
- 363, 357, 371, 357, 360, 357, 373, 374,
- 375, 376, 81, 187, 188, 189, 357, 357,
- 110, 377, 357, 357, 194, 360, 357, 357,
+ 357, 357, 196, 357, 364, 369, 369, 81,
+ 187, 188, 189, 357, 357, 357, 367, 357,
+ 357, 194, 357, 357, 357, 357, 357, 357,
+ 357, 357, 357, 357, 357, 357, 357, 196,
+ 357, 370, 357, 357, 357, 95, 371, 357,
+ 187, 188, 189, 357, 357, 357, 362, 357,
+ 370, 357, 372, 373, 374, 375, 81, 187,
+ 188, 189, 357, 357, 110, 376, 357, 357,
+ 194, 357, 357, 357, 357, 357, 357, 357,
+ 357, 357, 357, 357, 357, 357, 196, 357,
+ 377, 373, 378, 378, 81, 187, 188, 189,
+ 357, 357, 357, 376, 357, 357, 194, 357,
+ 357, 357, 357, 357, 357, 357, 357, 357,
+ 357, 357, 357, 357, 196, 357, 373, 378,
+ 378, 81, 187, 188, 189, 357, 357, 357,
+ 376, 357, 357, 194, 357, 357, 357, 357,
357, 357, 357, 357, 357, 357, 357, 357,
- 357, 357, 196, 357, 378, 374, 379, 379,
- 81, 187, 188, 189, 357, 357, 357, 377,
- 357, 357, 194, 360, 357, 357, 357, 357,
+ 357, 196, 357, 379, 357, 357, 357, 95,
+ 380, 357, 187, 188, 189, 357, 357, 357,
+ 362, 357, 379, 357, 381, 382, 383, 384,
+ 81, 187, 188, 189, 357, 357, 108, 385,
+ 357, 357, 194, 357, 357, 357, 357, 357,
357, 357, 357, 357, 357, 357, 357, 357,
- 196, 357, 374, 379, 379, 81, 187, 188,
- 189, 357, 357, 357, 377, 357, 357, 194,
- 360, 357, 357, 357, 357, 357, 357, 357,
- 357, 357, 357, 357, 357, 196, 357, 380,
- 357, 357, 357, 95, 381, 357, 187, 188,
- 189, 357, 357, 357, 363, 357, 380, 357,
- 360, 357, 382, 383, 384, 385, 81, 187,
- 188, 189, 357, 357, 108, 386, 357, 357,
- 194, 360, 357, 357, 357, 357, 357, 357,
+ 196, 357, 386, 382, 387, 387, 81, 187,
+ 188, 189, 357, 357, 357, 385, 357, 357,
+ 194, 357, 357, 357, 357, 357, 357, 357,
357, 357, 357, 357, 357, 357, 196, 357,
- 387, 383, 388, 388, 81, 187, 188, 189,
- 357, 357, 357, 386, 357, 357, 194, 360,
+ 382, 387, 387, 81, 187, 188, 189, 357,
+ 357, 357, 385, 357, 357, 194, 357, 357,
357, 357, 357, 357, 357, 357, 357, 357,
- 357, 357, 357, 357, 196, 357, 383, 388,
- 388, 81, 187, 188, 189, 357, 357, 357,
- 386, 357, 357, 194, 360, 357, 357, 357,
+ 357, 357, 357, 196, 357, 388, 357, 357,
+ 357, 95, 389, 357, 187, 188, 189, 357,
+ 357, 357, 362, 357, 388, 357, 390, 391,
+ 392, 393, 81, 187, 188, 189, 357, 357,
+ 106, 394, 357, 357, 194, 357, 357, 357,
357, 357, 357, 357, 357, 357, 357, 357,
- 357, 196, 357, 389, 357, 357, 357, 95,
- 390, 357, 187, 188, 189, 357, 357, 357,
- 363, 357, 389, 357, 360, 357, 391, 392,
- 393, 394, 81, 187, 188, 189, 357, 357,
- 106, 395, 357, 357, 194, 360, 357, 357,
+ 357, 357, 196, 357, 395, 391, 396, 396,
+ 81, 187, 188, 189, 357, 357, 357, 394,
+ 357, 357, 194, 357, 357, 357, 357, 357,
357, 357, 357, 357, 357, 357, 357, 357,
- 357, 357, 196, 357, 396, 392, 397, 397,
- 81, 187, 188, 189, 357, 357, 357, 395,
- 357, 357, 194, 360, 357, 357, 357, 357,
+ 196, 357, 391, 396, 396, 81, 187, 188,
+ 189, 357, 357, 357, 394, 357, 357, 194,
357, 357, 357, 357, 357, 357, 357, 357,
- 196, 357, 392, 397, 397, 81, 187, 188,
- 189, 357, 357, 357, 395, 357, 357, 194,
- 360, 357, 357, 357, 357, 357, 357, 357,
357, 357, 357, 357, 357, 196, 357, 95,
- 398, 357, 187, 188, 189, 357, 357, 357,
- 363, 357, 357, 357, 360, 357, 187, 188,
- 189, 357, 357, 357, 363, 357, 357, 357,
- 360, 357, 399, 357, 357, 400, 188, 189,
- 357, 188, 189, 357, 188, 401, 357, 188,
- 357, 399, 357, 357, 357, 188, 189, 357,
- 402, 357, 403, 404, 357, 187, 188, 189,
- 357, 357, 79, 357, 357, 357, 357, 360,
+ 397, 357, 187, 188, 189, 357, 357, 357,
+ 362, 357, 187, 188, 189, 357, 357, 357,
+ 362, 357, 398, 357, 357, 399, 188, 189,
+ 357, 188, 189, 357, 400, 357, 188, 401,
+ 357, 188, 402, 357, 188, 357, 398, 357,
+ 357, 357, 188, 189, 357, 403, 357, 404,
+ 405, 357, 187, 188, 189, 357, 357, 79,
357, 78, 357, 357, 357, 357, 187, 188,
- 189, 357, 357, 357, 357, 357, 357, 357,
- 360, 357, 187, 188, 189, 357, 357, 357,
- 357, 357, 357, 357, 360, 357, 405, 357,
- 357, 357, 357, 187, 188, 189, 357, 187,
- 188, 189, 357, 402, 357, 357, 357, 357,
- 187, 188, 189, 357, 357, 357, 357, 357,
- 357, 357, 360, 357, 402, 357, 403, 357,
- 357, 187, 188, 189, 357, 357, 79, 357,
- 357, 357, 357, 360, 357, 95, 357, 406,
- 406, 81, 187, 188, 189, 357, 357, 357,
- 363, 357, 357, 357, 360, 357, 407, 104,
- 408, 409, 85, 187, 188, 189, 357, 357,
- 357, 363, 357, 357, 357, 360, 357, 104,
- 408, 409, 85, 187, 188, 189, 357, 357,
- 357, 363, 357, 357, 357, 360, 357, 408,
- 408, 85, 187, 188, 189, 357, 357, 357,
- 363, 357, 357, 357, 360, 357, 410, 101,
- 411, 412, 88, 187, 188, 189, 357, 357,
- 357, 363, 357, 357, 357, 360, 357, 101,
- 411, 412, 88, 187, 188, 189, 357, 357,
- 357, 363, 357, 357, 357, 360, 357, 411,
- 411, 88, 187, 188, 189, 357, 357, 357,
- 363, 357, 357, 357, 360, 357, 413, 98,
- 414, 415, 91, 187, 188, 189, 357, 357,
- 357, 363, 357, 357, 357, 360, 357, 98,
- 414, 415, 91, 187, 188, 189, 357, 357,
- 357, 363, 357, 357, 357, 360, 357, 414,
- 414, 91, 187, 188, 189, 357, 357, 357,
- 363, 357, 357, 357, 360, 357, 416, 95,
- 357, 417, 357, 187, 188, 189, 357, 357,
- 357, 363, 357, 357, 357, 360, 357, 95,
- 357, 417, 357, 187, 188, 189, 357, 357,
- 357, 363, 357, 357, 357, 360, 357, 418,
- 357, 187, 188, 189, 357, 357, 357, 363,
- 357, 357, 357, 360, 357, 95, 357, 357,
- 357, 357, 187, 188, 189, 357, 357, 357,
- 363, 357, 357, 357, 360, 357, 77, 78,
- 357, 357, 95, 398, 357, 187, 188, 189,
- 357, 357, 357, 363, 357, 77, 357, 360,
- 357, 392, 397, 397, 81, 187, 188, 189,
- 357, 357, 357, 395, 357, 357, 357, 360,
+ 189, 357, 187, 188, 189, 357, 403, 357,
+ 357, 357, 357, 187, 188, 189, 357, 403,
+ 357, 404, 357, 357, 187, 188, 189, 357,
+ 357, 79, 357, 95, 357, 406, 406, 81,
+ 187, 188, 189, 357, 357, 357, 362, 357,
+ 407, 104, 408, 409, 85, 187, 188, 189,
+ 357, 357, 357, 362, 357, 104, 408, 409,
+ 85, 187, 188, 189, 357, 357, 357, 362,
+ 357, 408, 408, 85, 187, 188, 189, 357,
+ 357, 357, 362, 357, 410, 101, 411, 412,
+ 88, 187, 188, 189, 357, 357, 357, 362,
+ 357, 101, 411, 412, 88, 187, 188, 189,
+ 357, 357, 357, 362, 357, 411, 411, 88,
+ 187, 188, 189, 357, 357, 357, 362, 357,
+ 413, 98, 414, 415, 91, 187, 188, 189,
+ 357, 357, 357, 362, 357, 98, 414, 415,
+ 91, 187, 188, 189, 357, 357, 357, 362,
+ 357, 414, 414, 91, 187, 188, 189, 357,
+ 357, 357, 362, 357, 416, 95, 357, 417,
+ 357, 187, 188, 189, 357, 357, 357, 362,
+ 357, 95, 357, 417, 357, 187, 188, 189,
+ 357, 357, 357, 362, 357, 418, 357, 187,
+ 188, 189, 357, 357, 357, 362, 357, 95,
+ 357, 357, 357, 357, 187, 188, 189, 357,
+ 357, 357, 362, 357, 77, 78, 357, 357,
+ 95, 397, 357, 187, 188, 189, 357, 357,
+ 357, 362, 357, 77, 357, 391, 396, 396,
+ 81, 187, 188, 189, 357, 357, 357, 394,
357, 357, 357, 357, 357, 357, 357, 357,
- 357, 357, 357, 357, 196, 357, 392, 397,
- 397, 81, 187, 188, 189, 357, 357, 357,
- 395, 357, 357, 357, 360, 357, 391, 392,
- 397, 397, 81, 187, 188, 189, 357, 357,
- 357, 395, 357, 357, 194, 360, 357, 357,
357, 357, 357, 357, 357, 357, 357, 357,
- 357, 357, 196, 357, 391, 392, 393, 397,
- 81, 187, 188, 189, 357, 357, 106, 395,
- 357, 357, 194, 360, 357, 357, 357, 357,
+ 196, 357, 391, 396, 396, 81, 187, 188,
+ 189, 357, 357, 357, 394, 357, 390, 391,
+ 396, 396, 81, 187, 188, 189, 357, 357,
+ 357, 394, 357, 357, 194, 357, 357, 357,
357, 357, 357, 357, 357, 357, 357, 357,
- 196, 357, 389, 357, 419, 357, 406, 406,
- 81, 187, 188, 189, 357, 357, 357, 363,
- 357, 389, 357, 360, 357, 389, 357, 357,
- 357, 357, 357, 357, 187, 188, 189, 357,
- 357, 357, 363, 357, 389, 357, 360, 357,
- 389, 357, 357, 357, 357, 420, 357, 187,
- 188, 189, 357, 357, 357, 363, 357, 389,
- 357, 360, 357, 389, 357, 419, 357, 357,
+ 357, 357, 196, 357, 390, 391, 392, 396,
+ 81, 187, 188, 189, 357, 357, 106, 394,
+ 357, 357, 194, 357, 357, 357, 357, 357,
+ 357, 357, 357, 357, 357, 357, 357, 357,
+ 196, 357, 388, 357, 419, 357, 406, 406,
+ 81, 187, 188, 189, 357, 357, 357, 362,
+ 357, 388, 357, 388, 357, 357, 357, 357,
357, 357, 187, 188, 189, 357, 357, 357,
- 363, 357, 389, 357, 360, 357, 389, 78,
- 357, 357, 95, 390, 357, 187, 188, 189,
- 357, 357, 357, 363, 357, 389, 357, 360,
- 357, 382, 383, 388, 388, 81, 187, 188,
- 189, 357, 357, 357, 386, 357, 357, 194,
- 360, 357, 357, 357, 357, 357, 357, 357,
- 357, 357, 357, 357, 357, 196, 357, 382,
- 383, 384, 388, 81, 187, 188, 189, 357,
- 357, 108, 386, 357, 357, 194, 360, 357,
+ 362, 357, 388, 357, 388, 357, 357, 357,
+ 357, 420, 357, 187, 188, 189, 357, 357,
+ 357, 362, 357, 388, 357, 388, 357, 419,
+ 357, 357, 357, 357, 187, 188, 189, 357,
+ 357, 357, 362, 357, 388, 357, 388, 78,
+ 357, 357, 95, 389, 357, 187, 188, 189,
+ 357, 357, 357, 362, 357, 388, 357, 381,
+ 382, 387, 387, 81, 187, 188, 189, 357,
+ 357, 357, 385, 357, 357, 194, 357, 357,
357, 357, 357, 357, 357, 357, 357, 357,
- 357, 357, 357, 196, 357, 380, 357, 421,
- 357, 406, 406, 81, 187, 188, 189, 357,
- 357, 357, 363, 357, 380, 357, 360, 357,
- 380, 357, 357, 357, 357, 357, 357, 187,
- 188, 189, 357, 357, 357, 363, 357, 380,
- 357, 360, 357, 380, 357, 357, 357, 357,
- 422, 357, 187, 188, 189, 357, 357, 357,
- 363, 357, 380, 357, 360, 357, 380, 357,
+ 357, 357, 357, 196, 357, 381, 382, 383,
+ 387, 81, 187, 188, 189, 357, 357, 108,
+ 385, 357, 357, 194, 357, 357, 357, 357,
+ 357, 357, 357, 357, 357, 357, 357, 357,
+ 357, 196, 357, 379, 357, 421, 357, 406,
+ 406, 81, 187, 188, 189, 357, 357, 357,
+ 362, 357, 379, 357, 379, 357, 357, 357,
+ 357, 357, 357, 187, 188, 189, 357, 357,
+ 357, 362, 357, 379, 357, 379, 357, 357,
+ 357, 357, 422, 357, 187, 188, 189, 357,
+ 357, 357, 362, 357, 379, 357, 379, 357,
421, 357, 357, 357, 357, 187, 188, 189,
- 357, 357, 357, 363, 357, 380, 357, 360,
- 357, 380, 78, 357, 357, 95, 381, 357,
- 187, 188, 189, 357, 357, 357, 363, 357,
- 380, 357, 360, 357, 373, 374, 379, 379,
- 81, 187, 188, 189, 357, 357, 357, 377,
- 357, 357, 194, 360, 357, 357, 357, 357,
+ 357, 357, 357, 362, 357, 379, 357, 379,
+ 78, 357, 357, 95, 380, 357, 187, 188,
+ 189, 357, 357, 357, 362, 357, 379, 357,
+ 372, 373, 378, 378, 81, 187, 188, 189,
+ 357, 357, 357, 376, 357, 357, 194, 357,
357, 357, 357, 357, 357, 357, 357, 357,
- 196, 357, 373, 374, 375, 379, 81, 187,
- 188, 189, 357, 357, 110, 377, 357, 357,
- 194, 360, 357, 357, 357, 357, 357, 357,
- 357, 357, 357, 357, 357, 357, 196, 357,
- 371, 357, 423, 357, 406, 406, 81, 187,
- 188, 189, 357, 357, 357, 363, 357, 371,
- 357, 360, 357, 371, 357, 357, 357, 357,
- 357, 357, 187, 188, 189, 357, 357, 357,
- 363, 357, 371, 357, 360, 357, 371, 357,
+ 357, 357, 357, 357, 196, 357, 372, 373,
+ 374, 378, 81, 187, 188, 189, 357, 357,
+ 110, 376, 357, 357, 194, 357, 357, 357,
+ 357, 357, 357, 357, 357, 357, 357, 357,
+ 357, 357, 196, 357, 370, 357, 423, 357,
+ 406, 406, 81, 187, 188, 189, 357, 357,
+ 357, 362, 357, 370, 357, 370, 357, 357,
+ 357, 357, 357, 357, 187, 188, 189, 357,
+ 357, 357, 362, 357, 370, 357, 370, 357,
357, 357, 357, 424, 357, 187, 188, 189,
- 357, 357, 357, 363, 357, 371, 357, 360,
- 357, 371, 357, 423, 357, 357, 357, 357,
- 187, 188, 189, 357, 357, 357, 363, 357,
- 371, 357, 360, 357, 371, 78, 357, 357,
- 95, 372, 357, 187, 188, 189, 357, 357,
- 357, 363, 357, 371, 357, 360, 357, 364,
- 365, 370, 370, 81, 187, 188, 189, 357,
- 357, 357, 368, 357, 357, 194, 360, 357,
+ 357, 357, 357, 362, 357, 370, 357, 370,
+ 357, 423, 357, 357, 357, 357, 187, 188,
+ 189, 357, 357, 357, 362, 357, 370, 357,
+ 370, 78, 357, 357, 95, 371, 357, 187,
+ 188, 189, 357, 357, 357, 362, 357, 370,
+ 357, 363, 364, 369, 369, 81, 187, 188,
+ 189, 357, 357, 357, 367, 357, 357, 194,
357, 357, 357, 357, 357, 357, 357, 357,
- 357, 357, 357, 196, 357, 364, 365, 366,
- 370, 81, 187, 188, 189, 357, 357, 112,
- 368, 357, 357, 194, 360, 357, 357, 357,
+ 357, 357, 357, 357, 357, 196, 357, 363,
+ 364, 365, 369, 81, 187, 188, 189, 357,
+ 357, 112, 367, 357, 357, 194, 357, 357,
357, 357, 357, 357, 357, 357, 357, 357,
- 357, 196, 357, 361, 357, 425, 357, 406,
- 406, 81, 187, 188, 189, 357, 357, 357,
- 363, 357, 361, 357, 360, 357, 361, 357,
+ 357, 357, 357, 196, 357, 360, 357, 425,
+ 357, 406, 406, 81, 187, 188, 189, 357,
+ 357, 357, 362, 357, 360, 357, 360, 357,
357, 357, 357, 357, 357, 187, 188, 189,
- 357, 357, 357, 363, 357, 361, 357, 360,
- 357, 361, 357, 357, 357, 357, 426, 357,
- 187, 188, 189, 357, 357, 357, 363, 357,
- 361, 357, 360, 357, 361, 357, 425, 357,
- 357, 357, 357, 187, 188, 189, 357, 357,
- 357, 363, 357, 361, 357, 360, 357, 361,
- 78, 357, 357, 95, 362, 357, 187, 188,
- 189, 357, 357, 357, 363, 357, 361, 357,
+ 357, 357, 357, 362, 357, 360, 357, 360,
+ 357, 357, 357, 357, 426, 357, 187, 188,
+ 189, 357, 357, 357, 362, 357, 360, 357,
+ 360, 357, 425, 357, 357, 357, 357, 187,
+ 188, 189, 357, 357, 357, 362, 357, 360,
+ 357, 360, 78, 357, 357, 95, 361, 357,
+ 187, 188, 189, 357, 357, 357, 362, 357,
360, 357, 113, 80, 80, 81, 427, 427,
427, 427, 427, 152, 113, 427, 183, 184,
359, 359, 81, 187, 188, 189, 357, 357,
- 357, 191, 357, 357, 194, 360, 357, 357,
+ 357, 191, 357, 357, 194, 357, 357, 357,
357, 357, 357, 357, 357, 357, 357, 357,
357, 357, 196, 357, 113, 80, 80, 81,
427, 427, 427, 427, 427, 427, 113, 427,
429, 430, 431, 432, 119, 433, 434, 435,
- 428, 428, 151, 436, 428, 428, 437, 438,
+ 428, 428, 151, 436, 428, 428, 437, 428,
428, 428, 428, 428, 428, 428, 428, 428,
- 428, 428, 428, 428, 439, 428, 440, 430,
+ 428, 428, 428, 428, 438, 428, 439, 430,
432, 432, 119, 433, 434, 435, 428, 428,
- 428, 436, 428, 428, 437, 438, 428, 428,
+ 428, 436, 428, 428, 437, 428, 428, 428,
428, 428, 428, 428, 428, 428, 428, 428,
- 428, 428, 439, 428, 430, 432, 432, 119,
+ 428, 428, 438, 428, 430, 432, 432, 119,
433, 434, 435, 428, 428, 428, 436, 428,
- 428, 437, 438, 428, 428, 428, 428, 428,
- 428, 428, 428, 428, 428, 428, 428, 439,
- 428, 441, 428, 428, 428, 132, 442, 428,
- 433, 434, 435, 428, 428, 428, 443, 428,
- 441, 428, 438, 428, 444, 445, 446, 447,
- 119, 433, 434, 435, 428, 428, 149, 448,
- 428, 428, 437, 438, 428, 428, 428, 428,
+ 428, 437, 428, 428, 428, 428, 428, 428,
+ 428, 428, 428, 428, 428, 428, 428, 438,
+ 428, 440, 428, 428, 428, 132, 441, 428,
+ 433, 434, 435, 428, 428, 428, 442, 428,
+ 440, 428, 443, 444, 445, 446, 119, 433,
+ 434, 435, 428, 428, 149, 447, 428, 428,
+ 437, 428, 428, 428, 428, 428, 428, 428,
+ 428, 428, 428, 428, 428, 428, 438, 428,
+ 448, 444, 449, 449, 119, 433, 434, 435,
+ 428, 428, 428, 447, 428, 428, 437, 428,
428, 428, 428, 428, 428, 428, 428, 428,
- 439, 428, 449, 445, 450, 450, 119, 433,
- 434, 435, 428, 428, 428, 448, 428, 428,
- 437, 438, 428, 428, 428, 428, 428, 428,
- 428, 428, 428, 428, 428, 428, 439, 428,
- 445, 450, 450, 119, 433, 434, 435, 428,
- 428, 428, 448, 428, 428, 437, 438, 428,
+ 428, 428, 428, 428, 438, 428, 444, 449,
+ 449, 119, 433, 434, 435, 428, 428, 428,
+ 447, 428, 428, 437, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428, 428, 428,
- 428, 428, 428, 439, 428, 451, 428, 428,
- 428, 132, 452, 428, 433, 434, 435, 428,
- 428, 428, 443, 428, 451, 428, 438, 428,
- 453, 454, 455, 456, 119, 433, 434, 435,
- 428, 428, 147, 457, 428, 428, 437, 438,
+ 428, 438, 428, 450, 428, 428, 428, 132,
+ 451, 428, 433, 434, 435, 428, 428, 428,
+ 442, 428, 450, 428, 452, 453, 454, 455,
+ 119, 433, 434, 435, 428, 428, 147, 456,
+ 428, 428, 437, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428, 428, 428,
- 428, 428, 428, 428, 439, 428, 458, 454,
- 459, 459, 119, 433, 434, 435, 428, 428,
- 428, 457, 428, 428, 437, 438, 428, 428,
+ 438, 428, 457, 453, 458, 458, 119, 433,
+ 434, 435, 428, 428, 428, 456, 428, 428,
+ 437, 428, 428, 428, 428, 428, 428, 428,
+ 428, 428, 428, 428, 428, 428, 438, 428,
+ 453, 458, 458, 119, 433, 434, 435, 428,
+ 428, 428, 456, 428, 428, 437, 428, 428,
428, 428, 428, 428, 428, 428, 428, 428,
- 428, 428, 439, 428, 454, 459, 459, 119,
- 433, 434, 435, 428, 428, 428, 457, 428,
- 428, 437, 438, 428, 428, 428, 428, 428,
- 428, 428, 428, 428, 428, 428, 428, 439,
- 428, 460, 428, 428, 428, 132, 461, 428,
- 433, 434, 435, 428, 428, 428, 443, 428,
- 460, 428, 438, 428, 462, 463, 464, 465,
- 119, 433, 434, 435, 428, 428, 145, 466,
- 428, 428, 437, 438, 428, 428, 428, 428,
+ 428, 428, 428, 438, 428, 459, 428, 428,
+ 428, 132, 460, 428, 433, 434, 435, 428,
+ 428, 428, 442, 428, 459, 428, 461, 462,
+ 463, 464, 119, 433, 434, 435, 428, 428,
+ 145, 465, 428, 428, 437, 428, 428, 428,
428, 428, 428, 428, 428, 428, 428, 428,
- 439, 428, 467, 463, 468, 468, 119, 433,
- 434, 435, 428, 428, 428, 466, 428, 428,
- 437, 438, 428, 428, 428, 428, 428, 428,
- 428, 428, 428, 428, 428, 428, 439, 428,
- 463, 468, 468, 119, 433, 434, 435, 428,
- 428, 428, 466, 428, 428, 437, 438, 428,
+ 428, 428, 438, 428, 466, 462, 467, 467,
+ 119, 433, 434, 435, 428, 428, 428, 465,
+ 428, 428, 437, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428, 428, 428,
- 428, 428, 428, 439, 428, 469, 428, 428,
- 428, 132, 470, 428, 433, 434, 435, 428,
- 428, 428, 443, 428, 469, 428, 438, 428,
- 471, 472, 473, 474, 119, 433, 434, 435,
- 428, 428, 143, 475, 428, 428, 437, 438,
+ 438, 428, 462, 467, 467, 119, 433, 434,
+ 435, 428, 428, 428, 465, 428, 428, 437,
428, 428, 428, 428, 428, 428, 428, 428,
- 428, 428, 428, 428, 439, 428, 476, 472,
- 477, 477, 119, 433, 434, 435, 428, 428,
- 428, 475, 428, 428, 437, 438, 428, 428,
+ 428, 428, 428, 428, 428, 438, 428, 468,
+ 428, 428, 428, 132, 469, 428, 433, 434,
+ 435, 428, 428, 428, 442, 428, 468, 428,
+ 470, 471, 472, 473, 119, 433, 434, 435,
+ 428, 428, 143, 474, 428, 428, 437, 428,
428, 428, 428, 428, 428, 428, 428, 428,
- 428, 428, 439, 428, 472, 477, 477, 119,
- 433, 434, 435, 428, 428, 428, 475, 428,
- 428, 437, 438, 428, 428, 428, 428, 428,
- 428, 428, 428, 428, 428, 428, 428, 439,
- 428, 132, 478, 428, 433, 434, 435, 428,
- 428, 428, 443, 428, 428, 428, 438, 428,
- 433, 434, 435, 428, 428, 428, 443, 428,
- 428, 428, 438, 428, 479, 428, 428, 480,
- 434, 435, 428, 434, 435, 428, 434, 481,
- 428, 434, 428, 479, 428, 428, 428, 434,
- 435, 428, 482, 428, 483, 484, 428, 433,
- 434, 435, 428, 428, 117, 428, 428, 428,
- 428, 438, 428, 116, 428, 428, 428, 428,
- 433, 434, 435, 428, 428, 428, 428, 428,
- 428, 428, 438, 428, 433, 434, 435, 428,
- 428, 428, 428, 428, 428, 428, 438, 428,
- 485, 428, 428, 428, 428, 433, 434, 435,
- 428, 433, 434, 435, 428, 482, 428, 428,
- 428, 428, 433, 434, 435, 428, 428, 428,
- 428, 428, 428, 428, 438, 428, 482, 428,
- 483, 428, 428, 433, 434, 435, 428, 428,
- 117, 428, 428, 428, 428, 438, 428, 132,
- 428, 486, 486, 119, 433, 434, 435, 428,
- 428, 428, 443, 428, 428, 428, 438, 428,
- 487, 141, 488, 489, 122, 433, 434, 435,
- 428, 428, 428, 443, 428, 428, 428, 438,
- 428, 141, 488, 489, 122, 433, 434, 435,
- 428, 428, 428, 443, 428, 428, 428, 438,
- 428, 488, 488, 122, 433, 434, 435, 428,
- 428, 428, 443, 428, 428, 428, 438, 428,
- 490, 138, 491, 492, 125, 433, 434, 435,
- 428, 428, 428, 443, 428, 428, 428, 438,
- 428, 138, 491, 492, 125, 433, 434, 435,
- 428, 428, 428, 443, 428, 428, 428, 438,
- 428, 491, 491, 125, 433, 434, 435, 428,
- 428, 428, 443, 428, 428, 428, 438, 428,
- 493, 135, 494, 495, 128, 433, 434, 435,
- 428, 428, 428, 443, 428, 428, 428, 438,
- 428, 135, 494, 495, 128, 433, 434, 435,
- 428, 428, 428, 443, 428, 428, 428, 438,
- 428, 494, 494, 128, 433, 434, 435, 428,
- 428, 428, 443, 428, 428, 428, 438, 428,
- 496, 132, 428, 497, 428, 433, 434, 435,
- 428, 428, 428, 443, 428, 428, 428, 438,
- 428, 132, 428, 497, 428, 433, 434, 435,
- 428, 428, 428, 443, 428, 428, 428, 438,
- 428, 498, 428, 433, 434, 435, 428, 428,
- 428, 443, 428, 428, 428, 438, 428, 132,
- 428, 428, 428, 428, 433, 434, 435, 428,
- 428, 428, 443, 428, 428, 428, 438, 428,
- 115, 116, 428, 428, 132, 478, 428, 433,
- 434, 435, 428, 428, 428, 443, 428, 115,
- 428, 438, 428, 472, 477, 477, 119, 433,
- 434, 435, 428, 428, 428, 475, 428, 428,
- 428, 438, 428, 428, 428, 428, 428, 428,
- 428, 428, 428, 428, 428, 428, 439, 428,
- 472, 477, 477, 119, 433, 434, 435, 428,
- 428, 428, 475, 428, 428, 428, 438, 428,
- 471, 472, 477, 477, 119, 433, 434, 435,
- 428, 428, 428, 475, 428, 428, 437, 438,
+ 428, 428, 428, 428, 438, 428, 475, 471,
+ 476, 476, 119, 433, 434, 435, 428, 428,
+ 428, 474, 428, 428, 437, 428, 428, 428,
428, 428, 428, 428, 428, 428, 428, 428,
- 428, 428, 428, 428, 439, 428, 471, 472,
- 473, 477, 119, 433, 434, 435, 428, 428,
- 143, 475, 428, 428, 437, 438, 428, 428,
+ 428, 428, 438, 428, 471, 476, 476, 119,
+ 433, 434, 435, 428, 428, 428, 474, 428,
+ 428, 437, 428, 428, 428, 428, 428, 428,
+ 428, 428, 428, 428, 428, 428, 428, 438,
+ 428, 132, 477, 428, 433, 434, 435, 428,
+ 428, 428, 442, 428, 433, 434, 435, 428,
+ 428, 428, 442, 428, 478, 428, 428, 479,
+ 434, 435, 428, 434, 435, 428, 480, 428,
+ 434, 481, 428, 434, 482, 428, 434, 428,
+ 478, 428, 428, 428, 434, 435, 428, 483,
+ 428, 484, 485, 428, 433, 434, 435, 428,
+ 428, 117, 428, 116, 428, 428, 428, 428,
+ 433, 434, 435, 428, 433, 434, 435, 428,
+ 483, 428, 428, 428, 428, 433, 434, 435,
+ 428, 483, 428, 484, 428, 428, 433, 434,
+ 435, 428, 428, 117, 428, 132, 428, 486,
+ 486, 119, 433, 434, 435, 428, 428, 428,
+ 442, 428, 487, 141, 488, 489, 122, 433,
+ 434, 435, 428, 428, 428, 442, 428, 141,
+ 488, 489, 122, 433, 434, 435, 428, 428,
+ 428, 442, 428, 488, 488, 122, 433, 434,
+ 435, 428, 428, 428, 442, 428, 490, 138,
+ 491, 492, 125, 433, 434, 435, 428, 428,
+ 428, 442, 428, 138, 491, 492, 125, 433,
+ 434, 435, 428, 428, 428, 442, 428, 491,
+ 491, 125, 433, 434, 435, 428, 428, 428,
+ 442, 428, 493, 135, 494, 495, 128, 433,
+ 434, 435, 428, 428, 428, 442, 428, 135,
+ 494, 495, 128, 433, 434, 435, 428, 428,
+ 428, 442, 428, 494, 494, 128, 433, 434,
+ 435, 428, 428, 428, 442, 428, 496, 132,
+ 428, 497, 428, 433, 434, 435, 428, 428,
+ 428, 442, 428, 132, 428, 497, 428, 433,
+ 434, 435, 428, 428, 428, 442, 428, 498,
+ 428, 433, 434, 435, 428, 428, 428, 442,
+ 428, 132, 428, 428, 428, 428, 433, 434,
+ 435, 428, 428, 428, 442, 428, 115, 116,
+ 428, 428, 132, 477, 428, 433, 434, 435,
+ 428, 428, 428, 442, 428, 115, 428, 471,
+ 476, 476, 119, 433, 434, 435, 428, 428,
+ 428, 474, 428, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428, 428, 428,
- 428, 428, 439, 428, 469, 428, 499, 428,
- 486, 486, 119, 433, 434, 435, 428, 428,
- 428, 443, 428, 469, 428, 438, 428, 469,
- 428, 428, 428, 428, 428, 428, 433, 434,
- 435, 428, 428, 428, 443, 428, 469, 428,
- 438, 428, 469, 428, 428, 428, 428, 500,
- 428, 433, 434, 435, 428, 428, 428, 443,
- 428, 469, 428, 438, 428, 469, 428, 499,
- 428, 428, 428, 428, 433, 434, 435, 428,
- 428, 428, 443, 428, 469, 428, 438, 428,
- 469, 116, 428, 428, 132, 470, 428, 433,
- 434, 435, 428, 428, 428, 443, 428, 469,
- 428, 438, 428, 462, 463, 468, 468, 119,
- 433, 434, 435, 428, 428, 428, 466, 428,
- 428, 437, 438, 428, 428, 428, 428, 428,
- 428, 428, 428, 428, 428, 428, 428, 439,
- 428, 462, 463, 464, 468, 119, 433, 434,
- 435, 428, 428, 145, 466, 428, 428, 437,
- 438, 428, 428, 428, 428, 428, 428, 428,
- 428, 428, 428, 428, 428, 439, 428, 460,
- 428, 501, 428, 486, 486, 119, 433, 434,
- 435, 428, 428, 428, 443, 428, 460, 428,
- 438, 428, 460, 428, 428, 428, 428, 428,
- 428, 433, 434, 435, 428, 428, 428, 443,
- 428, 460, 428, 438, 428, 460, 428, 428,
- 428, 428, 502, 428, 433, 434, 435, 428,
- 428, 428, 443, 428, 460, 428, 438, 428,
- 460, 428, 501, 428, 428, 428, 428, 433,
- 434, 435, 428, 428, 428, 443, 428, 460,
- 428, 438, 428, 460, 116, 428, 428, 132,
- 461, 428, 433, 434, 435, 428, 428, 428,
- 443, 428, 460, 428, 438, 428, 453, 454,
- 459, 459, 119, 433, 434, 435, 428, 428,
- 428, 457, 428, 428, 437, 438, 428, 428,
+ 428, 428, 438, 428, 471, 476, 476, 119,
+ 433, 434, 435, 428, 428, 428, 474, 428,
+ 470, 471, 476, 476, 119, 433, 434, 435,
+ 428, 428, 428, 474, 428, 428, 437, 428,
428, 428, 428, 428, 428, 428, 428, 428,
- 428, 428, 439, 428, 453, 454, 455, 459,
- 119, 433, 434, 435, 428, 428, 147, 457,
- 428, 428, 437, 438, 428, 428, 428, 428,
+ 428, 428, 428, 428, 438, 428, 470, 471,
+ 472, 476, 119, 433, 434, 435, 428, 428,
+ 143, 474, 428, 428, 437, 428, 428, 428,
428, 428, 428, 428, 428, 428, 428, 428,
- 439, 428, 451, 428, 503, 428, 486, 486,
- 119, 433, 434, 435, 428, 428, 428, 443,
- 428, 451, 428, 438, 428, 451, 428, 428,
+ 428, 428, 438, 428, 468, 428, 499, 428,
+ 486, 486, 119, 433, 434, 435, 428, 428,
+ 428, 442, 428, 468, 428, 468, 428, 428,
428, 428, 428, 428, 433, 434, 435, 428,
- 428, 428, 443, 428, 451, 428, 438, 428,
- 451, 428, 428, 428, 428, 504, 428, 433,
- 434, 435, 428, 428, 428, 443, 428, 451,
- 428, 438, 428, 451, 428, 503, 428, 428,
- 428, 428, 433, 434, 435, 428, 428, 428,
- 443, 428, 451, 428, 438, 428, 451, 116,
- 428, 428, 132, 452, 428, 433, 434, 435,
- 428, 428, 428, 443, 428, 451, 428, 438,
- 428, 444, 445, 450, 450, 119, 433, 434,
- 435, 428, 428, 428, 448, 428, 428, 437,
- 438, 428, 428, 428, 428, 428, 428, 428,
- 428, 428, 428, 428, 428, 439, 428, 444,
- 445, 446, 450, 119, 433, 434, 435, 428,
- 428, 149, 448, 428, 428, 437, 438, 428,
+ 428, 428, 442, 428, 468, 428, 468, 428,
+ 428, 428, 428, 500, 428, 433, 434, 435,
+ 428, 428, 428, 442, 428, 468, 428, 468,
+ 428, 499, 428, 428, 428, 428, 433, 434,
+ 435, 428, 428, 428, 442, 428, 468, 428,
+ 468, 116, 428, 428, 132, 469, 428, 433,
+ 434, 435, 428, 428, 428, 442, 428, 468,
+ 428, 461, 462, 467, 467, 119, 433, 434,
+ 435, 428, 428, 428, 465, 428, 428, 437,
428, 428, 428, 428, 428, 428, 428, 428,
- 428, 428, 428, 439, 428, 441, 428, 505,
+ 428, 428, 428, 428, 428, 438, 428, 461,
+ 462, 463, 467, 119, 433, 434, 435, 428,
+ 428, 145, 465, 428, 428, 437, 428, 428,
+ 428, 428, 428, 428, 428, 428, 428, 428,
+ 428, 428, 428, 438, 428, 459, 428, 501,
428, 486, 486, 119, 433, 434, 435, 428,
- 428, 428, 443, 428, 441, 428, 438, 428,
- 441, 428, 428, 428, 428, 428, 428, 433,
- 434, 435, 428, 428, 428, 443, 428, 441,
- 428, 438, 428, 441, 428, 428, 428, 428,
- 506, 428, 433, 434, 435, 428, 428, 428,
- 443, 428, 441, 428, 438, 428, 441, 428,
- 505, 428, 428, 428, 428, 433, 434, 435,
- 428, 428, 428, 443, 428, 441, 428, 438,
- 428, 441, 116, 428, 428, 132, 442, 428,
- 433, 434, 435, 428, 428, 428, 443, 428,
- 441, 428, 438, 428, 429, 430, 432, 432,
+ 428, 428, 442, 428, 459, 428, 459, 428,
+ 428, 428, 428, 428, 428, 433, 434, 435,
+ 428, 428, 428, 442, 428, 459, 428, 459,
+ 428, 428, 428, 428, 502, 428, 433, 434,
+ 435, 428, 428, 428, 442, 428, 459, 428,
+ 459, 428, 501, 428, 428, 428, 428, 433,
+ 434, 435, 428, 428, 428, 442, 428, 459,
+ 428, 459, 116, 428, 428, 132, 460, 428,
+ 433, 434, 435, 428, 428, 428, 442, 428,
+ 459, 428, 452, 453, 458, 458, 119, 433,
+ 434, 435, 428, 428, 428, 456, 428, 428,
+ 437, 428, 428, 428, 428, 428, 428, 428,
+ 428, 428, 428, 428, 428, 428, 438, 428,
+ 452, 453, 454, 458, 119, 433, 434, 435,
+ 428, 428, 147, 456, 428, 428, 437, 428,
+ 428, 428, 428, 428, 428, 428, 428, 428,
+ 428, 428, 428, 428, 438, 428, 450, 428,
+ 503, 428, 486, 486, 119, 433, 434, 435,
+ 428, 428, 428, 442, 428, 450, 428, 450,
+ 428, 428, 428, 428, 428, 428, 433, 434,
+ 435, 428, 428, 428, 442, 428, 450, 428,
+ 450, 428, 428, 428, 428, 504, 428, 433,
+ 434, 435, 428, 428, 428, 442, 428, 450,
+ 428, 450, 428, 503, 428, 428, 428, 428,
+ 433, 434, 435, 428, 428, 428, 442, 428,
+ 450, 428, 450, 116, 428, 428, 132, 451,
+ 428, 433, 434, 435, 428, 428, 428, 442,
+ 428, 450, 428, 443, 444, 449, 449, 119,
+ 433, 434, 435, 428, 428, 428, 447, 428,
+ 428, 437, 428, 428, 428, 428, 428, 428,
+ 428, 428, 428, 428, 428, 428, 428, 438,
+ 428, 443, 444, 445, 449, 119, 433, 434,
+ 435, 428, 428, 149, 447, 428, 428, 437,
+ 428, 428, 428, 428, 428, 428, 428, 428,
+ 428, 428, 428, 428, 428, 438, 428, 440,
+ 428, 505, 428, 486, 486, 119, 433, 434,
+ 435, 428, 428, 428, 442, 428, 440, 428,
+ 440, 428, 428, 428, 428, 428, 428, 433,
+ 434, 435, 428, 428, 428, 442, 428, 440,
+ 428, 440, 428, 428, 428, 428, 506, 428,
+ 433, 434, 435, 428, 428, 428, 442, 428,
+ 440, 428, 440, 428, 505, 428, 428, 428,
+ 428, 433, 434, 435, 428, 428, 428, 442,
+ 428, 440, 428, 440, 116, 428, 428, 132,
+ 441, 428, 433, 434, 435, 428, 428, 428,
+ 442, 428, 440, 428, 429, 430, 432, 432,
119, 433, 434, 435, 428, 428, 428, 436,
- 428, 428, 437, 438, 428, 428, 428, 428,
+ 428, 428, 437, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428, 428, 428,
- 439, 428, 181, 182, 183, 184, 507, 359,
+ 438, 428, 181, 182, 183, 184, 507, 359,
81, 187, 188, 189, 190, 190, 152, 191,
- 357, 181, 194, 360, 357, 357, 357, 357,
+ 357, 181, 194, 357, 357, 357, 357, 357,
357, 357, 357, 357, 357, 357, 357, 357,
196, 357, 198, 508, 200, 201, 5, 202,
203, 204, 197, 197, 37, 205, 197, 197,
- 206, 207, 197, 197, 197, 197, 197, 197,
- 197, 197, 197, 197, 197, 197, 208, 197,
- 211, 182, 183, 184, 509, 510, 81, 511,
- 203, 512, 190, 190, 152, 513, 197, 211,
- 194, 514, 197, 197, 197, 197, 197, 197,
+ 206, 197, 197, 197, 197, 197, 197, 197,
+ 197, 197, 197, 197, 197, 197, 207, 197,
+ 210, 182, 183, 184, 509, 510, 81, 511,
+ 512, 513, 197, 190, 152, 514, 197, 210,
+ 194, 197, 197, 197, 197, 197, 197, 197,
197, 197, 197, 197, 197, 197, 196, 197,
113, 80, 80, 81, 202, 203, 204, 197,
- 197, 152, 515, 197, 197, 197, 207, 197,
- 516, 2, 357, 357, 357, 426, 357, 187,
- 188, 189, 357, 357, 357, 363, 357, 516,
- 357, 360, 357, 517, 365, 518, 519, 81,
- 511, 203, 512, 197, 197, 153, 368, 197,
- 197, 194, 514, 197, 197, 197, 197, 197,
+ 197, 152, 515, 197, 516, 2, 357, 357,
+ 357, 426, 357, 187, 188, 189, 357, 357,
+ 357, 362, 357, 516, 357, 517, 364, 518,
+ 519, 81, 511, 512, 513, 197, 197, 153,
+ 367, 197, 197, 194, 197, 197, 197, 197,
+ 197, 197, 197, 197, 197, 197, 197, 197,
+ 197, 196, 197, 520, 364, 369, 369, 81,
+ 511, 512, 513, 197, 197, 197, 367, 197,
+ 197, 194, 197, 197, 197, 197, 197, 197,
197, 197, 197, 197, 197, 197, 197, 196,
- 197, 520, 365, 370, 370, 81, 511, 203,
- 512, 197, 197, 197, 368, 197, 197, 194,
- 514, 197, 197, 197, 197, 197, 197, 197,
- 197, 197, 197, 197, 197, 196, 197, 365,
- 370, 370, 81, 511, 203, 512, 197, 197,
- 197, 368, 197, 197, 194, 514, 197, 197,
+ 197, 364, 369, 369, 81, 511, 512, 513,
+ 197, 197, 197, 367, 197, 197, 194, 197,
197, 197, 197, 197, 197, 197, 197, 197,
- 197, 197, 196, 197, 521, 197, 197, 522,
- 203, 512, 197, 203, 512, 197, 203, 523,
- 197, 203, 197, 521, 197, 197, 197, 203,
- 512, 197, 524, 197, 197, 197, 197, 511,
- 203, 512, 197, 511, 203, 512, 197, 517,
- 365, 370, 370, 81, 511, 203, 512, 197,
- 197, 197, 368, 197, 197, 194, 514, 197,
+ 197, 197, 197, 197, 196, 197, 521, 197,
+ 197, 522, 512, 513, 197, 512, 513, 197,
+ 250, 197, 512, 523, 197, 512, 524, 197,
+ 512, 197, 521, 197, 197, 197, 512, 513,
+ 197, 517, 364, 369, 369, 81, 511, 512,
+ 513, 197, 197, 197, 367, 197, 197, 194,
197, 197, 197, 197, 197, 197, 197, 197,
- 197, 197, 197, 196, 197, 517, 365, 518,
- 370, 81, 511, 203, 512, 197, 197, 153,
- 368, 197, 197, 194, 514, 197, 197, 197,
+ 197, 197, 197, 197, 197, 196, 197, 517,
+ 364, 518, 369, 81, 511, 512, 513, 197,
+ 197, 153, 367, 197, 197, 194, 197, 197,
197, 197, 197, 197, 197, 197, 197, 197,
- 197, 196, 197, 211, 197, 275, 113, 525,
- 525, 155, 202, 203, 204, 197, 197, 197,
- 515, 197, 211, 197, 207, 197, 526, 179,
- 527, 528, 157, 511, 203, 512, 197, 197,
- 197, 529, 197, 197, 197, 514, 197, 179,
- 527, 528, 157, 511, 203, 512, 197, 197,
- 197, 529, 197, 197, 197, 514, 197, 527,
- 527, 157, 511, 203, 512, 197, 197, 197,
- 529, 197, 197, 197, 514, 197, 530, 176,
- 531, 532, 160, 511, 203, 512, 197, 197,
- 197, 529, 197, 197, 197, 514, 197, 176,
- 531, 532, 160, 511, 203, 512, 197, 197,
- 197, 529, 197, 197, 197, 514, 197, 531,
- 531, 160, 511, 203, 512, 197, 197, 197,
- 529, 197, 197, 197, 514, 197, 533, 173,
- 534, 535, 163, 511, 203, 512, 197, 197,
- 197, 529, 197, 197, 197, 514, 197, 173,
- 534, 535, 163, 511, 203, 512, 197, 197,
- 197, 529, 197, 197, 197, 514, 197, 534,
- 534, 163, 511, 203, 512, 197, 197, 197,
- 529, 197, 197, 197, 514, 197, 536, 170,
- 197, 537, 197, 511, 203, 512, 197, 197,
- 197, 529, 197, 197, 197, 514, 197, 170,
- 197, 537, 197, 511, 203, 512, 197, 197,
- 197, 529, 197, 197, 197, 514, 197, 511,
- 203, 512, 197, 197, 197, 529, 197, 197,
- 197, 514, 197, 538, 197, 539, 540, 197,
- 511, 203, 512, 197, 197, 167, 197, 197,
- 197, 197, 514, 197, 166, 197, 197, 197,
- 197, 511, 203, 512, 197, 197, 197, 197,
- 197, 197, 197, 514, 197, 511, 203, 512,
- 197, 197, 197, 197, 197, 197, 197, 514,
- 197, 538, 197, 197, 197, 197, 511, 203,
- 512, 197, 197, 197, 197, 197, 197, 197,
- 514, 197, 538, 197, 539, 197, 197, 511,
- 203, 512, 197, 197, 167, 197, 197, 197,
- 197, 514, 197, 516, 166, 357, 357, 95,
- 362, 357, 187, 188, 189, 357, 357, 357,
- 363, 357, 516, 357, 360, 357, 542, 541,
- 541, 541, 541, 543, 544, 545, 541, 543,
- 544, 545, 541, 546, 541, 541, 547, 544,
- 545, 541, 544, 545, 541, 544, 548, 541,
- 544, 541, 546, 541, 541, 541, 544, 545,
- 541, 0
+ 197, 197, 197, 196, 197, 210, 197, 275,
+ 113, 525, 525, 155, 202, 203, 204, 197,
+ 197, 197, 515, 197, 210, 197, 526, 179,
+ 527, 528, 157, 511, 512, 513, 197, 197,
+ 197, 529, 197, 179, 527, 528, 157, 511,
+ 512, 513, 197, 197, 197, 529, 197, 527,
+ 527, 157, 511, 512, 513, 197, 197, 197,
+ 529, 197, 530, 176, 531, 532, 160, 511,
+ 512, 513, 197, 197, 197, 529, 197, 176,
+ 531, 532, 160, 511, 512, 513, 197, 197,
+ 197, 529, 197, 531, 531, 160, 511, 512,
+ 513, 197, 197, 197, 529, 197, 533, 173,
+ 534, 535, 163, 511, 512, 513, 197, 197,
+ 197, 529, 197, 173, 534, 535, 163, 511,
+ 512, 513, 197, 197, 197, 529, 197, 534,
+ 534, 163, 511, 512, 513, 197, 197, 197,
+ 529, 197, 536, 170, 197, 537, 197, 511,
+ 512, 513, 197, 197, 197, 529, 197, 170,
+ 197, 537, 197, 511, 512, 513, 197, 197,
+ 197, 529, 197, 511, 512, 513, 197, 197,
+ 197, 529, 197, 538, 197, 539, 540, 197,
+ 511, 512, 513, 197, 197, 167, 197, 166,
+ 197, 197, 197, 197, 511, 512, 513, 197,
+ 511, 512, 513, 197, 538, 197, 197, 197,
+ 197, 511, 512, 513, 197, 538, 197, 539,
+ 197, 197, 511, 512, 513, 197, 197, 167,
+ 197, 516, 166, 357, 357, 95, 361, 357,
+ 187, 188, 189, 357, 357, 357, 362, 357,
+ 516, 357, 542, 541, 541, 541, 541, 543,
+ 544, 545, 541, 543, 544, 545, 541, 546,
+ 541, 541, 547, 544, 545, 541, 544, 545,
+ 541, 548, 541, 544, 549, 541, 544, 550,
+ 541, 544, 541, 546, 541, 541, 541, 544,
+ 545, 541, 0
};
static const short _indic_syllable_machine_trans_targs[] = {
- 170, 197, 199, 202, 3, 205, 4, 6,
+ 170, 199, 201, 202, 3, 205, 4, 6,
208, 7, 9, 211, 10, 12, 214, 13,
15, 16, 191, 18, 19, 213, 21, 22,
210, 24, 25, 207, 216, 221, 225, 228,
- 232, 235, 239, 242, 246, 249, 170, 277,
- 279, 282, 39, 285, 40, 42, 288, 43,
+ 232, 235, 239, 242, 246, 249, 170, 279,
+ 281, 282, 39, 285, 40, 42, 288, 43,
45, 291, 46, 48, 294, 49, 51, 52,
271, 54, 55, 293, 57, 58, 290, 60,
61, 287, 296, 301, 305, 308, 312, 315,
- 319, 322, 326, 330, 170, 356, 358, 361,
+ 319, 322, 326, 330, 170, 358, 360, 361,
75, 364, 170, 76, 78, 367, 79, 81,
370, 82, 84, 373, 85, 87, 88, 350,
90, 91, 372, 93, 94, 369, 96, 97,
366, 375, 380, 384, 387, 391, 394, 398,
- 401, 405, 170, 437, 439, 442, 110, 445,
+ 401, 405, 170, 439, 441, 442, 110, 445,
111, 113, 448, 114, 116, 451, 117, 119,
454, 120, 122, 123, 431, 125, 126, 453,
128, 129, 450, 131, 132, 447, 456, 461,
@@ -1281,52 +1189,52 @@ static const short _indic_syllable_machine_trans_targs[] = {
514, 152, 154, 517, 155, 520, 522, 523,
159, 160, 519, 162, 163, 516, 165, 166,
513, 168, 169, 510, 170, 171, 251, 331,
- 333, 408, 410, 351, 170, 353, 411, 407,
+ 333, 408, 410, 351, 353, 354, 411, 407,
490, 491, 378, 526, 379, 170, 172, 174,
- 35, 250, 192, 170, 194, 248, 219, 200,
- 220, 173, 34, 175, 244, 0, 176, 178,
- 33, 243, 241, 177, 32, 179, 237, 180,
- 182, 31, 236, 234, 181, 30, 183, 230,
- 184, 186, 29, 229, 227, 185, 28, 187,
- 223, 188, 190, 27, 222, 218, 189, 26,
- 204, 193, 196, 195, 198, 1, 203, 201,
+ 35, 250, 192, 194, 195, 248, 219, 220,
+ 173, 34, 175, 244, 0, 176, 178, 33,
+ 243, 241, 177, 32, 179, 237, 180, 182,
+ 31, 236, 234, 181, 30, 183, 230, 184,
+ 186, 29, 229, 227, 185, 28, 187, 223,
+ 188, 190, 27, 222, 218, 189, 26, 204,
+ 193, 198, 170, 196, 197, 200, 1, 203,
2, 206, 5, 23, 209, 8, 20, 212,
11, 17, 215, 14, 217, 224, 226, 231,
233, 238, 240, 245, 247, 170, 252, 254,
- 71, 328, 272, 170, 274, 329, 299, 280,
- 300, 253, 70, 255, 324, 36, 256, 258,
- 69, 323, 321, 257, 68, 259, 317, 260,
- 262, 67, 316, 314, 261, 66, 263, 310,
- 264, 266, 65, 309, 307, 265, 64, 267,
- 303, 268, 270, 63, 302, 298, 269, 62,
- 284, 273, 276, 275, 278, 37, 283, 281,
+ 71, 328, 272, 274, 275, 329, 299, 300,
+ 253, 70, 255, 324, 36, 256, 258, 69,
+ 323, 321, 257, 68, 259, 317, 260, 262,
+ 67, 316, 314, 261, 66, 263, 310, 264,
+ 266, 65, 309, 307, 265, 64, 267, 303,
+ 268, 270, 63, 302, 298, 269, 62, 284,
+ 273, 278, 170, 276, 277, 280, 37, 283,
38, 286, 41, 59, 289, 44, 56, 292,
47, 53, 295, 50, 297, 304, 306, 311,
313, 318, 320, 325, 327, 170, 332, 106,
- 359, 334, 403, 72, 335, 337, 105, 402,
- 400, 336, 104, 338, 396, 339, 341, 103,
- 395, 393, 340, 102, 342, 389, 343, 345,
- 101, 388, 386, 344, 100, 346, 382, 347,
- 349, 99, 381, 377, 348, 98, 363, 352,
- 355, 354, 357, 73, 362, 360, 74, 365,
+ 334, 403, 72, 335, 337, 105, 402, 400,
+ 336, 104, 338, 396, 339, 341, 103, 395,
+ 393, 340, 102, 342, 389, 343, 345, 101,
+ 388, 386, 344, 100, 346, 382, 347, 349,
+ 99, 381, 377, 348, 98, 363, 352, 357,
+ 170, 355, 356, 359, 73, 362, 74, 365,
77, 95, 368, 80, 92, 371, 83, 89,
374, 86, 376, 383, 385, 390, 392, 397,
399, 404, 406, 170, 170, 412, 414, 142,
- 141, 432, 170, 434, 488, 459, 440, 460,
- 413, 415, 484, 107, 416, 418, 140, 483,
- 481, 417, 139, 419, 477, 420, 422, 138,
- 476, 474, 421, 137, 423, 470, 424, 426,
- 136, 469, 467, 425, 135, 427, 463, 428,
- 430, 134, 462, 458, 429, 133, 444, 433,
- 436, 435, 438, 108, 443, 441, 109, 446,
+ 141, 432, 434, 435, 488, 459, 460, 413,
+ 415, 484, 107, 416, 418, 140, 483, 481,
+ 417, 139, 419, 477, 420, 422, 138, 476,
+ 474, 421, 137, 423, 470, 424, 426, 136,
+ 469, 467, 425, 135, 427, 463, 428, 430,
+ 134, 462, 458, 429, 133, 444, 433, 438,
+ 170, 436, 437, 440, 108, 443, 109, 446,
112, 130, 449, 115, 127, 452, 118, 124,
455, 121, 457, 464, 466, 471, 473, 478,
480, 485, 487, 143, 492, 493, 507, 498,
- 500, 525, 503, 494, 495, 496, 144, 506,
- 497, 499, 502, 501, 504, 145, 509, 147,
+ 500, 501, 525, 494, 495, 496, 144, 506,
+ 497, 499, 504, 502, 503, 145, 509, 147,
167, 156, 512, 150, 164, 515, 153, 161,
518, 158, 521, 157, 524, 170, 527, 528,
- 170, 530, 529, 532, 531
+ 530, 531, 529, 534, 170, 532, 533
};
static const char _indic_syllable_machine_trans_actions[] = {
@@ -1353,52 +1261,52 @@ static const char _indic_syllable_machine_trans_actions[] = {
2, 0, 0, 2, 0, 2, 0, 0,
0, 0, 2, 0, 0, 2, 0, 0,
2, 0, 0, 2, 11, 2, 2, 6,
- 2, 12, 12, 0, 13, 0, 2, 2,
- 6, 2, 6, 0, 6, 14, 2, 2,
- 0, 2, 0, 15, 0, 2, 2, 0,
- 2, 2, 0, 2, 2, 0, 2, 2,
+ 2, 12, 12, 0, 0, 0, 2, 2,
+ 6, 2, 6, 0, 6, 13, 2, 2,
+ 0, 2, 0, 0, 0, 2, 2, 2,
+ 2, 0, 2, 2, 0, 2, 2, 0,
+ 2, 2, 2, 0, 2, 2, 2, 2,
0, 2, 2, 2, 0, 2, 2, 2,
2, 0, 2, 2, 2, 0, 2, 2,
2, 2, 0, 2, 2, 2, 0, 2,
- 2, 2, 2, 0, 2, 2, 2, 0,
- 2, 0, 0, 0, 0, 0, 2, 0,
+ 0, 0, 14, 0, 0, 0, 0, 2,
0, 2, 0, 0, 2, 0, 0, 2,
0, 0, 2, 0, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 16, 2, 2,
- 0, 2, 0, 17, 0, 2, 2, 0,
- 2, 2, 0, 2, 2, 0, 2, 2,
+ 2, 2, 2, 2, 2, 15, 2, 2,
+ 0, 2, 0, 0, 0, 2, 2, 2,
+ 2, 0, 2, 2, 0, 2, 2, 0,
+ 2, 2, 2, 0, 2, 2, 2, 2,
0, 2, 2, 2, 0, 2, 2, 2,
2, 0, 2, 2, 2, 0, 2, 2,
2, 2, 0, 2, 2, 2, 0, 2,
- 2, 2, 2, 0, 2, 2, 2, 0,
- 2, 0, 0, 0, 0, 0, 2, 0,
+ 0, 0, 16, 0, 0, 0, 0, 2,
0, 2, 0, 0, 2, 0, 0, 2,
0, 0, 2, 0, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 18, 6, 0,
- 0, 6, 6, 0, 6, 2, 0, 6,
+ 2, 2, 2, 2, 2, 17, 6, 0,
+ 6, 6, 0, 6, 2, 0, 6, 2,
+ 6, 0, 6, 6, 6, 2, 0, 6,
2, 6, 0, 6, 6, 6, 2, 0,
6, 2, 6, 0, 6, 6, 6, 2,
- 0, 6, 2, 6, 0, 6, 6, 6,
- 2, 0, 6, 2, 6, 0, 6, 0,
- 0, 0, 0, 0, 2, 0, 0, 2,
+ 0, 6, 2, 6, 0, 6, 0, 0,
+ 18, 0, 0, 0, 0, 2, 0, 2,
0, 0, 2, 0, 0, 2, 0, 0,
2, 0, 2, 2, 2, 2, 2, 2,
2, 2, 2, 19, 20, 2, 2, 0,
- 0, 0, 21, 0, 2, 2, 0, 2,
- 2, 2, 2, 0, 2, 2, 0, 2,
+ 0, 0, 0, 0, 2, 2, 2, 2,
+ 2, 2, 0, 2, 2, 0, 2, 2,
+ 2, 0, 2, 2, 2, 2, 0, 2,
2, 2, 0, 2, 2, 2, 2, 0,
2, 2, 2, 0, 2, 2, 2, 2,
- 0, 2, 2, 2, 0, 2, 2, 2,
- 2, 0, 2, 2, 2, 0, 2, 0,
- 0, 0, 0, 0, 2, 0, 0, 2,
+ 0, 2, 2, 2, 0, 2, 0, 0,
+ 21, 0, 0, 0, 0, 2, 0, 2,
0, 0, 2, 0, 0, 2, 0, 0,
2, 0, 2, 2, 2, 2, 2, 2,
2, 2, 2, 0, 0, 8, 2, 0,
- 0, 2, 0, 2, 8, 8, 0, 8,
+ 0, 0, 2, 2, 8, 8, 0, 8,
8, 0, 0, 0, 0, 0, 2, 0,
0, 0, 2, 0, 0, 2, 0, 0,
2, 0, 0, 0, 2, 22, 0, 0,
- 23, 0, 0, 0, 0
+ 0, 0, 0, 0, 23, 0, 0
};
static const char _indic_syllable_machine_to_state_actions[] = {
@@ -1468,7 +1376,7 @@ static const char _indic_syllable_machine_to_state_actions[] = {
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
};
static const char _indic_syllable_machine_from_state_actions[] = {
@@ -1538,7 +1446,7 @@ static const char _indic_syllable_machine_from_state_actions[] = {
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
};
static const short _indic_syllable_machine_eof_trans[] = {
@@ -1608,7 +1516,7 @@ static const short _indic_syllable_machine_eof_trans[] = {
198, 198, 198, 198, 198, 198, 198, 198,
198, 198, 198, 198, 198, 198, 198, 198,
198, 198, 198, 198, 198, 358, 542, 542,
- 542, 542, 542, 542, 542
+ 542, 542, 542, 542, 542, 542, 542
};
static const int indic_syllable_machine_start = 170;
@@ -1622,7 +1530,7 @@ static const int indic_syllable_machine_en_main = 170;
-#line 98 "hb-ot-shape-complex-indic-machine.rl"
+#line 97 "hb-ot-shape-complex-indic-machine.rl"
#define found_syllable(syllable_type) \
@@ -1642,7 +1550,7 @@ find_syllables (hb_buffer_t *buffer)
int cs;
hb_glyph_info_t *info = buffer->info;
-#line 1646 "hb-ot-shape-complex-indic-machine.hh"
+#line 1554 "hb-ot-shape-complex-indic-machine.hh"
{
cs = indic_syllable_machine_start;
ts = 0;
@@ -1650,7 +1558,7 @@ find_syllables (hb_buffer_t *buffer)
act = 0;
}
-#line 119 "hb-ot-shape-complex-indic-machine.rl"
+#line 118 "hb-ot-shape-complex-indic-machine.rl"
p = 0;
@@ -1659,7 +1567,7 @@ find_syllables (hb_buffer_t *buffer)
unsigned int last = 0;
unsigned int syllable_serial = 1;
-#line 1663 "hb-ot-shape-complex-indic-machine.hh"
+#line 1571 "hb-ot-shape-complex-indic-machine.hh"
{
int _slen;
int _trans;
@@ -1673,7 +1581,7 @@ _resume:
#line 1 "NONE"
{ts = p;}
break;
-#line 1677 "hb-ot-shape-complex-indic-machine.hh"
+#line 1585 "hb-ot-shape-complex-indic-machine.hh"
}
_keys = _indic_syllable_machine_trans_keys + (cs<<1);
@@ -1695,68 +1603,68 @@ _eof_trans:
#line 1 "NONE"
{te = p+1;}
break;
- case 15:
-#line 89 "hb-ot-shape-complex-indic-machine.rl"
+ case 14:
+#line 88 "hb-ot-shape-complex-indic-machine.rl"
{te = p+1;{ found_syllable (consonant_syllable); }}
break;
- case 17:
-#line 90 "hb-ot-shape-complex-indic-machine.rl"
+ case 16:
+#line 89 "hb-ot-shape-complex-indic-machine.rl"
{te = p+1;{ found_syllable (vowel_syllable); }}
break;
case 21:
-#line 91 "hb-ot-shape-complex-indic-machine.rl"
+#line 90 "hb-ot-shape-complex-indic-machine.rl"
{te = p+1;{ found_syllable (standalone_cluster); }}
break;
case 23:
-#line 92 "hb-ot-shape-complex-indic-machine.rl"
- {te = p+1;{ found_syllable (avagraha_cluster); }}
+#line 91 "hb-ot-shape-complex-indic-machine.rl"
+ {te = p+1;{ found_syllable (symbol_cluster); }}
break;
- case 13:
-#line 93 "hb-ot-shape-complex-indic-machine.rl"
+ case 18:
+#line 92 "hb-ot-shape-complex-indic-machine.rl"
{te = p+1;{ found_syllable (broken_cluster); }}
break;
case 11:
-#line 94 "hb-ot-shape-complex-indic-machine.rl"
+#line 93 "hb-ot-shape-complex-indic-machine.rl"
{te = p+1;{ found_syllable (non_indic_cluster); }}
break;
- case 14:
-#line 89 "hb-ot-shape-complex-indic-machine.rl"
+ case 13:
+#line 88 "hb-ot-shape-complex-indic-machine.rl"
{te = p;p--;{ found_syllable (consonant_syllable); }}
break;
- case 16:
-#line 90 "hb-ot-shape-complex-indic-machine.rl"
+ case 15:
+#line 89 "hb-ot-shape-complex-indic-machine.rl"
{te = p;p--;{ found_syllable (vowel_syllable); }}
break;
case 20:
-#line 91 "hb-ot-shape-complex-indic-machine.rl"
+#line 90 "hb-ot-shape-complex-indic-machine.rl"
{te = p;p--;{ found_syllable (standalone_cluster); }}
break;
case 22:
-#line 92 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (avagraha_cluster); }}
+#line 91 "hb-ot-shape-complex-indic-machine.rl"
+ {te = p;p--;{ found_syllable (symbol_cluster); }}
break;
- case 18:
-#line 93 "hb-ot-shape-complex-indic-machine.rl"
+ case 17:
+#line 92 "hb-ot-shape-complex-indic-machine.rl"
{te = p;p--;{ found_syllable (broken_cluster); }}
break;
case 19:
-#line 94 "hb-ot-shape-complex-indic-machine.rl"
+#line 93 "hb-ot-shape-complex-indic-machine.rl"
{te = p;p--;{ found_syllable (non_indic_cluster); }}
break;
case 1:
-#line 89 "hb-ot-shape-complex-indic-machine.rl"
+#line 88 "hb-ot-shape-complex-indic-machine.rl"
{{p = ((te))-1;}{ found_syllable (consonant_syllable); }}
break;
case 3:
-#line 90 "hb-ot-shape-complex-indic-machine.rl"
+#line 89 "hb-ot-shape-complex-indic-machine.rl"
{{p = ((te))-1;}{ found_syllable (vowel_syllable); }}
break;
case 7:
-#line 91 "hb-ot-shape-complex-indic-machine.rl"
+#line 90 "hb-ot-shape-complex-indic-machine.rl"
{{p = ((te))-1;}{ found_syllable (standalone_cluster); }}
break;
case 4:
-#line 93 "hb-ot-shape-complex-indic-machine.rl"
+#line 92 "hb-ot-shape-complex-indic-machine.rl"
{{p = ((te))-1;}{ found_syllable (broken_cluster); }}
break;
case 5:
@@ -1777,22 +1685,22 @@ _eof_trans:
case 8:
#line 1 "NONE"
{te = p+1;}
-#line 89 "hb-ot-shape-complex-indic-machine.rl"
+#line 88 "hb-ot-shape-complex-indic-machine.rl"
{act = 1;}
break;
case 6:
#line 1 "NONE"
{te = p+1;}
-#line 93 "hb-ot-shape-complex-indic-machine.rl"
+#line 92 "hb-ot-shape-complex-indic-machine.rl"
{act = 5;}
break;
case 12:
#line 1 "NONE"
{te = p+1;}
-#line 94 "hb-ot-shape-complex-indic-machine.rl"
+#line 93 "hb-ot-shape-complex-indic-machine.rl"
{act = 6;}
break;
-#line 1796 "hb-ot-shape-complex-indic-machine.hh"
+#line 1704 "hb-ot-shape-complex-indic-machine.hh"
}
_again:
@@ -1801,7 +1709,7 @@ _again:
#line 1 "NONE"
{ts = 0;}
break;
-#line 1805 "hb-ot-shape-complex-indic-machine.hh"
+#line 1713 "hb-ot-shape-complex-indic-machine.hh"
}
if ( ++p != pe )
@@ -1817,7 +1725,7 @@ _again:
}
-#line 128 "hb-ot-shape-complex-indic-machine.rl"
+#line 127 "hb-ot-shape-complex-indic-machine.rl"
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh
index 3de5c203fa..d8dfc6507d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh
@@ -53,17 +53,29 @@ enum indic_category_t {
OT_SM = 8,
OT_VD = 9,
OT_A = 10,
- OT_NBSP = 11,
+ OT_PLACEHOLDER = 11,
OT_DOTTEDCIRCLE = 12,
OT_RS = 13, /* Register Shifter, used in Khmer OT spec. */
OT_Coeng = 14, /* Khmer-style Virama. */
OT_Repha = 15, /* Atomically-encoded logical or visual repha. */
OT_Ra = 16,
OT_CM = 17, /* Consonant-Medial. */
- OT_Avag = 18, /* Avagraha. */
+ OT_Symbol = 18, /* Avagraha, etc that take marks (SM,A,VD). */
OT_CM2 = 31 /* Consonant-Medial, second slot. */
};
+#define MEDIAL_FLAGS (FLAG (OT_CM) | FLAG (OT_CM2))
+
+/* Note:
+ *
+ * We treat Vowels and placeholders as if they were consonants. This is safe because Vowels
+ * cannot happen in a consonant syllable. The plus side however is, we can call the
+ * consonant syllable logic from the vowel syllable function and get it all right! */
+#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_Ra) | MEDIAL_FLAGS | FLAG (OT_V) | FLAG (OT_PLACEHOLDER) | FLAG (OT_DOTTEDCIRCLE))
+#define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ))
+#define HALANT_OR_COENG_FLAGS (FLAG (OT_H) | FLAG (OT_Coeng))
+
+
/* Visual positions in a syllable from left to right. */
enum indic_position_t {
POS_START,
@@ -93,57 +105,74 @@ enum indic_position_t {
/* Categories used in IndicSyllabicCategory.txt from UCD. */
enum indic_syllabic_category_t {
- INDIC_SYLLABIC_CATEGORY_OTHER = OT_X,
-
- INDIC_SYLLABIC_CATEGORY_AVAGRAHA = OT_Avag,
- INDIC_SYLLABIC_CATEGORY_BINDU = OT_SM,
- INDIC_SYLLABIC_CATEGORY_CONSONANT = OT_C,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD = OT_C,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL = OT_CM,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER = OT_C,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL = OT_CM,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER = OT_NBSP,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_CM,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_REPHA = OT_Repha,
- INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER = OT_X,
- INDIC_SYLLABIC_CATEGORY_NUKTA = OT_N,
- INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER = OT_RS,
- INDIC_SYLLABIC_CATEGORY_TONE_LETTER = OT_X,
- INDIC_SYLLABIC_CATEGORY_TONE_MARK = OT_N,
- INDIC_SYLLABIC_CATEGORY_VIRAMA = OT_H,
- INDIC_SYLLABIC_CATEGORY_VISARGA = OT_SM,
- INDIC_SYLLABIC_CATEGORY_VOWEL = OT_V,
- INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT = OT_M,
- INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT = OT_V
+ INDIC_SYLLABIC_CATEGORY_OTHER = OT_X,
+
+ INDIC_SYLLABIC_CATEGORY_AVAGRAHA = OT_Symbol,
+ INDIC_SYLLABIC_CATEGORY_BINDU = OT_SM,
+ INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER = OT_PLACEHOLDER, /* TODO */
+ INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK = OT_A,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT = OT_C,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD = OT_C,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL = OT_CM,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER = OT_C,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL = OT_CM,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER = OT_PLACEHOLDER,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA = OT_Repha,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_CM,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA = OT_N,
+ INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK = OT_SM,
+ INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER = OT_H, /* TODO */
+ INDIC_SYLLABIC_CATEGORY_JOINER = OT_ZWJ,
+ INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER = OT_X,
+ INDIC_SYLLABIC_CATEGORY_NON_JOINER = OT_ZWNJ,
+ INDIC_SYLLABIC_CATEGORY_NUKTA = OT_N,
+ INDIC_SYLLABIC_CATEGORY_NUMBER = OT_PLACEHOLDER,
+ INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER = OT_PLACEHOLDER, /* TODO */
+ INDIC_SYLLABIC_CATEGORY_PURE_KILLER = OT_H, /* TODO */
+ INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER = OT_RS,
+ INDIC_SYLLABIC_CATEGORY_TONE_LETTER = OT_X,
+ INDIC_SYLLABIC_CATEGORY_TONE_MARK = OT_N,
+ INDIC_SYLLABIC_CATEGORY_VIRAMA = OT_H,
+ INDIC_SYLLABIC_CATEGORY_VISARGA = OT_SM,
+ INDIC_SYLLABIC_CATEGORY_VOWEL = OT_V,
+ INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT = OT_M,
+ INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT = OT_V
};
/* Categories used in IndicSMatraCategory.txt from UCD */
enum indic_matra_category_t {
- INDIC_MATRA_CATEGORY_NOT_APPLICABLE = POS_END,
+ INDIC_MATRA_CATEGORY_NOT_APPLICABLE = POS_END,
- INDIC_MATRA_CATEGORY_LEFT = POS_PRE_C,
- INDIC_MATRA_CATEGORY_TOP = POS_ABOVE_C,
- INDIC_MATRA_CATEGORY_BOTTOM = POS_BELOW_C,
- INDIC_MATRA_CATEGORY_RIGHT = POS_POST_C,
+ INDIC_MATRA_CATEGORY_LEFT = POS_PRE_C,
+ INDIC_MATRA_CATEGORY_TOP = POS_ABOVE_C,
+ INDIC_MATRA_CATEGORY_BOTTOM = POS_BELOW_C,
+ INDIC_MATRA_CATEGORY_RIGHT = POS_POST_C,
/* These should resolve to the position of the last part of the split sequence. */
- INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
- INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
- INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM = INDIC_MATRA_CATEGORY_BOTTOM,
- INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
- INDIC_MATRA_CATEGORY_TOP_AND_LEFT = INDIC_MATRA_CATEGORY_TOP,
- INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
- INDIC_MATRA_CATEGORY_TOP_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
-
- INDIC_MATRA_CATEGORY_INVISIBLE = INDIC_MATRA_CATEGORY_NOT_APPLICABLE,
- INDIC_MATRA_CATEGORY_OVERSTRUCK = POS_AFTER_MAIN,
- INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT = POS_PRE_M
+ INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
+ INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
+ INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM = INDIC_MATRA_CATEGORY_BOTTOM,
+ INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
+ INDIC_MATRA_CATEGORY_TOP_AND_LEFT = INDIC_MATRA_CATEGORY_TOP,
+ INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
+ INDIC_MATRA_CATEGORY_TOP_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
+
+ INDIC_MATRA_CATEGORY_OVERSTRUCK = POS_AFTER_MAIN,
+ INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT = POS_PRE_M
};
/* Note: We use ASSERT_STATIC_EXPR_ZERO() instead of ASSERT_STATIC_EXPR() and the comma operation
* because gcc fails to optimize the latter and fills the table in at runtime. */
#define INDIC_COMBINE_CATEGORIES(S,M) \
- (ASSERT_STATIC_EXPR_ZERO (M == INDIC_MATRA_CATEGORY_NOT_APPLICABLE || (S == INDIC_SYLLABIC_CATEGORY_VIRAMA || S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT)) + \
+ (ASSERT_STATIC_EXPR_ZERO (M == INDIC_MATRA_CATEGORY_NOT_APPLICABLE || \
+ ( \
+ S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \
+ S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \
+ S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \
+ S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \
+ S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \
+ S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \
+ false)) + \
ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \
((M << 8) | S))
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc
index 18a022bc50..f58380e0c8 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc
@@ -6,54 +6,63 @@
*
* on files with these headers:
*
- * # IndicSyllabicCategory-6.2.0.txt
- * # Date: 2012-05-15, 21:12:00 GMT [KW]
- * # IndicMatraCategory-6.2.0.txt
- * # Date: 2012-05-15, 21:10:00 GMT [KW]
- * # Blocks-6.2.0.txt
- * # Date: 2012-05-14, 22:42:00 GMT [KW, LI]
+ * # IndicSyllabicCategory-7.0.0.txt
+ * # Date: 2014-06-03, 07:00:00 GMT [KW, LI, AG, RP]
+ * # IndicMatraCategory-7.0.0.txt
+ * # Date: 2014-06-03, 07:00:00 GMT [KW, LI, AG, RP]
+ * # Blocks-7.0.0.txt
+ * # Date: 2014-04-03, 23:23:00 GMT [RP, KW]
*/
#include "hb-ot-shape-complex-indic-private.hh"
-#define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 11 chars; Avagraha */
-#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 34 chars; Bindu */
-#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 123 chars; Consonant */
-#define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 2 chars; Consonant_Dead */
-#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 17 chars; Consonant_Final */
-#define ISC_CHL INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER /* 1 chars; Consonant_Head_Letter */
-#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 12 chars; Consonant_Medial */
-#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 4 chars; Consonant_Placeholder */
-#define ISC_CR INDIC_SYLLABIC_CATEGORY_CONSONANT_REPHA /* 5 chars; Consonant_Repha */
-#define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 10 chars; Consonant_Subjoined */
+#define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 13 chars; Avagraha */
+#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 59 chars; Bindu */
+#define ISC_BJN INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER /* 20 chars; Brahmi_Joining_Number */
+#define ISC_Ca INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK /* 30 chars; Cantillation_Mark */
+#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 1744 chars; Consonant */
+#define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 7 chars; Consonant_Dead */
+#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 61 chars; Consonant_Final */
+#define ISC_CHL INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER /* 5 chars; Consonant_Head_Letter */
+#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 19 chars; Consonant_Medial */
+#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 11 chars; Consonant_Placeholder */
+#define ISC_CPR INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA /* 1 chars; Consonant_Preceding_Repha */
+#define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 61 chars; Consonant_Subjoined */
+#define ISC_CSR INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA /* 4 chars; Consonant_Succeeding_Repha */
+#define ISC_GM INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK /* 2 chars; Gemination_Mark */
+#define ISC_IS INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER /* 7 chars; Invisible_Stacker */
+#define ISC_ZWJ INDIC_SYLLABIC_CATEGORY_JOINER /* 1 chars; Joiner */
#define ISC_ML INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER /* 1 chars; Modifying_Letter */
-#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 12 chars; Nukta */
+#define ISC_ZWNJ INDIC_SYLLABIC_CATEGORY_NON_JOINER /* 1 chars; Non_Joiner */
+#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 18 chars; Nukta */
+#define ISC_Nd INDIC_SYLLABIC_CATEGORY_NUMBER /* 408 chars; Number */
+#define ISC_NJ INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER /* 1 chars; Number_Joiner */
#define ISC_x INDIC_SYLLABIC_CATEGORY_OTHER /* 1 chars; Other */
-#define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 1 chars; Register_Shifter */
-#define ISC_TL INDIC_SYLLABIC_CATEGORY_TONE_LETTER /* 3 chars; Tone_Letter */
-#define ISC_TM INDIC_SYLLABIC_CATEGORY_TONE_MARK /* 16 chars; Tone_Mark */
-#define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 34 chars; Virama */
-#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 25 chars; Visarga */
-#define ISC_Vo INDIC_SYLLABIC_CATEGORY_VOWEL /* 5 chars; Vowel */
-#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 165 chars; Vowel_Dependent */
-#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 59 chars; Vowel_Independent */
-
-#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 65 chars; Bottom */
+#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 15 chars; Pure_Killer */
+#define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 3 chars; Register_Shifter */
+#define ISC_TL INDIC_SYLLABIC_CATEGORY_TONE_LETTER /* 7 chars; Tone_Letter */
+#define ISC_TM INDIC_SYLLABIC_CATEGORY_TONE_MARK /* 62 chars; Tone_Mark */
+#define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 22 chars; Virama */
+#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 29 chars; Visarga */
+#define ISC_Vo INDIC_SYLLABIC_CATEGORY_VOWEL /* 30 chars; Vowel */
+#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 553 chars; Vowel_Dependent */
+#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 395 chars; Vowel_Independent */
+
+#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 142 chars; Bottom */
#define IMC_BR INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT /* 2 chars; Bottom_And_Right */
-#define IMC_I INDIC_MATRA_CATEGORY_INVISIBLE /* 6 chars; Invisible */
-#define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 30 chars; Left */
-#define IMC_LR INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT /* 8 chars; Left_And_Right */
+#define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 57 chars; Left */
+#define IMC_LR INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT /* 21 chars; Left_And_Right */
#define IMC_x INDIC_MATRA_CATEGORY_NOT_APPLICABLE /* 1 chars; Not_Applicable */
#define IMC_O INDIC_MATRA_CATEGORY_OVERSTRUCK /* 2 chars; Overstruck */
-#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 75 chars; Right */
-#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 83 chars; Top */
-#define IMC_TB INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM /* 6 chars; Top_And_Bottom */
+#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 163 chars; Right */
+#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 169 chars; Top */
+#define IMC_TB INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM /* 10 chars; Top_And_Bottom */
#define IMC_TBR INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT /* 1 chars; Top_And_Bottom_And_Right */
-#define IMC_TL INDIC_MATRA_CATEGORY_TOP_AND_LEFT /* 4 chars; Top_And_Left */
-#define IMC_TLR INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT /* 2 chars; Top_And_Left_And_Right */
-#define IMC_TR INDIC_MATRA_CATEGORY_TOP_AND_RIGHT /* 8 chars; Top_And_Right */
-#define IMC_VOL INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT /* 5 chars; Visual_Order_Left */
+#define IMC_TL INDIC_MATRA_CATEGORY_TOP_AND_LEFT /* 6 chars; Top_And_Left */
+#define IMC_TLR INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT /* 4 chars; Top_And_Left_And_Right */
+#define IMC_TR INDIC_MATRA_CATEGORY_TOP_AND_RIGHT /* 13 chars; Top_And_Right */
+#define IMC_VOL INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT /* 15 chars; Visual_Order_Left */
#define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)
@@ -61,10 +70,26 @@
static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
-#define indic_offset_0x0900 0
+#define indic_offset_0x0028u 0
- /* Devanagari (0900..097F) */
+ /* Basic Latin */
+
+ /* 0028 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CP,x), _(x,x), _(x,x),
+ /* 0030 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* 0038 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+#define indic_offset_0x00d0u 24
+
+
+ /* Latin-1 Supplement */
+
+ /* 00D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CP,x),
+
+#define indic_offset_0x0900u 32
+
+
+ /* Devanagari */
/* 0900 */ _(Bi,x), _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 0908 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
@@ -76,14 +101,14 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 0938 */ _(C,x), _(C,x), _(M,T), _(M,R), _(N,x), _(A,x), _(M,R), _(M,L),
/* 0940 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(M,T), _(M,T),
/* 0948 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(V,B), _(M,L), _(M,R),
- /* 0950 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,B), _(M,B),
+ /* 0950 */ _(x,x), _(TM,x), _(TM,x), _(x,x), _(x,x), _(M,T), _(M,B), _(M,B),
/* 0958 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0960 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0968 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0960 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
+ /* 0968 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 0970 */ _(x,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0978 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0978 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* Bengali (0980..09FF) */
+ /* Bengali */
/* 0980 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0988 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x),
@@ -97,12 +122,12 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 09C8 */ _(M,L), _(x,x), _(x,x), _(M,LR), _(M,LR), _(V,B), _(CD,x), _(x,x),
/* 09D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
/* 09D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x),
- /* 09E0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 09E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 09E0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
+ /* 09E8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 09F0 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 09F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Gurmukhi (0A00..0A7F) */
+ /* Gurmukhi */
/* 0A00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0A08 */ _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(x,x), _(x,x), _(VI,x),
@@ -116,12 +141,12 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 0A48 */ _(M,T), _(x,x), _(x,x), _(M,T), _(M,T), _(V,B), _(x,x), _(x,x),
/* 0A50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0A58 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x),
- /* 0A60 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0A68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0A70 */ _(Bi,x), _(x,x), _(CP,x), _(CP,x), _(x,x), _(CM,x), _(x,x), _(x,x),
+ /* 0A60 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
+ /* 0A68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* 0A70 */ _(Bi,x), _(GM,T), _(CP,x), _(CP,x), _(x,x), _(CM,x), _(x,x), _(x,x),
/* 0A78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Gujarati (0A80..0AFF) */
+ /* Gujarati */
/* 0A80 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0A88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x),
@@ -135,12 +160,12 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 0AC8 */ _(M,T), _(M,TR), _(x,x), _(M,R), _(M,R), _(V,B), _(x,x), _(x,x),
/* 0AD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0AD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0AE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0AE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0AE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
+ /* 0AE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 0AF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0AF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Oriya (0B00..0B7F) */
+ /* Oriya */
/* 0B00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0B08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x),
@@ -154,12 +179,12 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 0B48 */ _(M,TL), _(x,x), _(x,x), _(M,LR),_(M,TLR), _(V,B), _(x,x), _(x,x),
/* 0B50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,TR),
/* 0B58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x),
- /* 0B60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0B68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0B60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
+ /* 0B68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 0B70 */ _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0B78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Tamil (0B80..0BFF) */
+ /* Tamil */
/* 0B80 */ _(x,x), _(x,x), _(Bi,x), _(ML,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0B88 */ _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(x,x), _(VI,x), _(VI,x),
@@ -173,33 +198,33 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 0BC8 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T), _(x,x), _(x,x),
/* 0BD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
/* 0BD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0BE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0BE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0BE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
+ /* 0BE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 0BF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0BF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Telugu (0C00..0C7F) */
+ /* Telugu */
- /* 0C00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 0C00 */ _(Bi,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0C08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x),
/* 0C10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
/* 0C18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0C20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0C28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0C30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
+ /* 0C30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0C38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(A,x), _(M,T), _(M,T),
/* 0C40 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,T),
/* 0C48 */ _(M,TB), _(x,x), _(M,T), _(M,T), _(M,T), _(V,T), _(x,x), _(x,x),
/* 0C50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,B), _(x,x),
/* 0C58 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0C60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0C68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0C60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
+ /* 0C68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 0C70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0C78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Kannada (0C80..0CFF) */
+ /* Kannada */
- /* 0C80 */ _(x,x), _(x,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 0C80 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0C88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x),
/* 0C90 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
/* 0C98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@@ -211,14 +236,14 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 0CC8 */ _(M,TR), _(x,x), _(M,TR), _(M,TR), _(M,T), _(V,T), _(x,x), _(x,x),
/* 0CD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), _(M,R), _(x,x),
/* 0CD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(x,x),
- /* 0CE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0CE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0CE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
+ /* 0CE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 0CF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0CF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Malayalam (0D00..0D7F) */
+ /* Malayalam */
- /* 0D00 */ _(x,x), _(x,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 0D00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0D08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x),
/* 0D10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
/* 0D18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@@ -227,15 +252,15 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 0D30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0D38 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(A,x), _(M,R), _(M,R),
/* 0D40 */ _(M,R), _(M,R), _(M,R), _(M,B), _(M,B), _(x,x), _(M,L), _(M,L),
- /* 0D48 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T), _(CR,x), _(x,x),
+ /* 0D48 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T),_(CPR,x), _(x,x),
/* 0D50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
/* 0D58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0D60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0D68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0D60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
+ /* 0D68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 0D70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0D78 */ _(x,x), _(x,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x),
- /* Sinhala (0D80..0DFF) */
+ /* Sinhala */
/* 0D80 */ _(x,x), _(x,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0D88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
@@ -248,86 +273,15 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 0DC0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x),
/* 0DC8 */ _(x,x), _(x,x), _(V,T), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
/* 0DD0 */ _(M,R), _(M,R), _(M,T), _(M,T), _(M,B), _(x,x), _(M,B), _(x,x),
- /* 0DD8 */ _(M,R), _(M,L), _(M,TL), _(M,L), _(M,LR), _(M,LR), _(M,LR), _(M,R),
- /* 0DE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0DE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0DD8 */ _(M,R), _(M,L), _(M,TL), _(M,L), _(M,LR),_(M,TLR), _(M,LR), _(M,R),
+ /* 0DE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
+ /* 0DE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 0DF0 */ _(x,x), _(x,x), _(M,R), _(M,R), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0DF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* Thai (0E00..0E7F) */
-
- /* 0E00 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0E08 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0E10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0E18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0E20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0E28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x),
- /* 0E30 */ _(M,R), _(M,T), _(M,R), _(M,R), _(M,T), _(M,T), _(M,T), _(M,T),
- /* 0E38 */ _(M,B), _(M,B), _(V,B), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0E40 */_(M,VOL),_(M,VOL),_(M,VOL),_(M,VOL),_(M,VOL), _(M,R), _(x,x), _(M,T),
- /* 0E48 */ _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(x,x), _(Bi,x), _(V,T), _(x,x),
- /* 0E50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0E58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0E60 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0E68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0E70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0E78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* Lao (0E80..0EFF) */
-
- /* 0E80 */ _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), _(x,x), _(C,x),
- /* 0E88 */ _(C,x), _(x,x), _(C,x), _(x,x), _(x,x), _(C,x), _(x,x), _(x,x),
- /* 0E90 */ _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0E98 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0EA0 */ _(x,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), _(C,x),
- /* 0EA8 */ _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(x,x),
- /* 0EB0 */ _(M,R), _(M,T), _(M,R), _(M,R), _(M,T), _(M,T), _(M,T), _(M,T),
- /* 0EB8 */ _(M,B), _(M,B), _(x,x), _(M,T), _(CM,x), _(CM,x), _(x,x), _(x,x),
- /* 0EC0 */_(M,VOL),_(M,VOL),_(M,VOL),_(M,VOL),_(M,VOL), _(x,x), _(x,x), _(x,x),
- /* 0EC8 */ _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(x,x), _(Bi,x), _(x,x), _(x,x),
- /* 0ED0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0ED8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(x,x),
- /* 0EE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0EE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0EF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0EF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* Tibetan (0F00..0FFF) */
-
- /* 0F00 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0F08 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0F10 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0F18 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0F20 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0F28 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0F30 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0F38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0F40 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0F48 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0F50 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0F58 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0F60 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0F68 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x),
- /* 0F70 */ _(x,x), _(M,B), _(M,T), _(M,TB), _(M,B), _(M,B), _(M,TB), _(M,TB),
- /* 0F78 */ _(M,TB), _(M,TB), _(M,T), _(M,T), _(M,T), _(M,T), _(Bi,x), _(Vs,x),
- /* 0F80 */ _(M,T), _(M,TB), _(Bi,x), _(Bi,x), _(V,B), _(A,x), _(x,x), _(x,x),
- /* 0F88 */_(CHL,x),_(CHL,x),_(CHL,x),_(CHL,x),_(CHL,x), _(CS,x), _(CS,x), _(CS,x),
- /* 0F90 */ _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x),
- /* 0F98 */ _(x,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x),
- /* 0FA0 */ _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x),
- /* 0FA8 */ _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x),
- /* 0FB0 */ _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x),
- /* 0FB8 */ _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(x,x), _(x,x), _(x,x),
- /* 0FC0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0FC8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0FD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0FD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0FE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0FE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0FF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0FF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* Myanmar (1000..109F) */
+
+#define indic_offset_0x1000u 1304
+
+
+ /* Myanmar */
/* 1000 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1008 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@@ -336,9 +290,9 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 1020 */ _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 1028 */ _(VI,x), _(VI,x), _(VI,x), _(M,R), _(M,R), _(M,T), _(M,T), _(M,B),
/* 1030 */ _(M,B), _(M,L), _(M,T), _(M,T), _(M,T), _(M,T), _(Bi,x), _(TM,x),
- /* 1038 */ _(Vs,x), _(V,I), _(V,T), _(CM,x), _(CM,x), _(CM,x), _(CM,x), _(C,x),
- /* 1040 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 1048 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1038 */ _(Vs,x), _(IS,x), _(PK,T), _(CM,x), _(CM,x), _(CM,x), _(CM,x), _(C,x),
+ /* 1040 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* 1048 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CP,x), _(x,x),
/* 1050 */ _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(M,R), _(M,R),
/* 1058 */ _(M,B), _(M,B), _(C,x), _(C,x), _(C,x), _(C,x), _(CM,x), _(CM,x),
/* 1060 */ _(CM,x), _(C,x), _(M,R), _(TM,x), _(TM,x), _(C,x), _(C,x), _(M,R),
@@ -347,41 +301,41 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 1078 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1080 */ _(C,x), _(C,x), _(CM,x), _(M,R), _(M,L), _(M,T), _(M,T), _(TM,x),
/* 1088 */ _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(C,x), _(TM,x),
- /* 1090 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 1098 */ _(x,x), _(x,x), _(TM,x), _(TM,x), _(M,R), _(M,T), _(x,x), _(x,x),
+ /* 1090 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* 1098 */ _(Nd,x), _(Nd,x), _(TM,x), _(TM,x), _(M,R), _(M,T), _(x,x), _(x,x),
-#define indic_offset_0x1700 1952
+#define indic_offset_0x1700u 1464
- /* Tagalog (1700..171F) */
+ /* Tagalog */
/* 1700 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1708 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x),
- /* 1710 */ _(C,x), _(C,x), _(M,T), _(M,B), _(V,B), _(x,x), _(x,x), _(x,x),
+ /* 1710 */ _(C,x), _(C,x), _(M,T), _(M,B), _(PK,B), _(x,x), _(x,x), _(x,x),
/* 1718 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Hanunoo (1720..173F) */
+ /* Hanunoo */
/* 1720 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1728 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1730 */ _(C,x), _(C,x), _(M,T), _(M,B), _(V,B), _(x,x), _(x,x), _(x,x),
+ /* 1730 */ _(C,x), _(C,x), _(M,T), _(M,B), _(PK,B), _(x,x), _(x,x), _(x,x),
/* 1738 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Buhid (1740..175F) */
+ /* Buhid */
/* 1740 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1748 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1750 */ _(C,x), _(C,x), _(M,T), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1758 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Tagbanwa (1760..177F) */
+ /* Tagbanwa */
/* 1760 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1768 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x),
/* 1770 */ _(C,x), _(x,x), _(M,T), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1778 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Khmer (1780..17FF) */
+ /* Khmer */
/* 1780 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1788 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@@ -392,31 +346,29 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 17B0 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(M,R), _(M,T),
/* 17B8 */ _(M,T), _(M,T), _(M,T), _(M,B), _(M,B), _(M,B), _(M,TL),_(M,TLR),
/* 17C0 */ _(M,LR), _(M,L), _(M,L), _(M,L), _(M,LR), _(M,LR), _(Bi,x), _(Vs,x),
- /* 17C8 */ _(M,R), _(RS,x), _(RS,x), _(x,x), _(CR,x), _(x,x), _(x,x), _(x,x),
- /* 17D0 */ _(x,x), _(V,T), _(V,I), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 17C8 */ _(M,R), _(RS,T), _(RS,T), _(RS,T),_(CSR,T), _(M,T), _(M,T), _(M,T),
+ /* 17D0 */ _(M,T), _(PK,T), _(IS,x), _(M,T), _(x,x), _(x,x), _(x,x), _(x,x),
/* 17D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(A,x), _(x,x), _(x,x), _(x,x),
- /* 17E0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 17E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 17F0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 17F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 17E0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* 17E8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-#define indic_offset_0x1900 2208
+#define indic_offset_0x1900u 1704
- /* Limbu (1900..194F) */
+ /* Limbu */
/* 1900 */ _(CP,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1908 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1910 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x),
+ /* 1918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x),
/* 1920 */ _(M,T), _(M,T), _(M,B), _(M,R), _(M,R), _(M,TR), _(M,TR), _(M,T),
/* 1928 */ _(M,T), _(CS,x), _(CS,x), _(CS,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1930 */ _(CF,x), _(CF,x), _(Bi,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x),
/* 1938 */ _(CF,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 1940 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 1948 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1940 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
+ /* 1948 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* Tai Le (1950..197F) */
+ /* Tai Le */
/* 1950 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1958 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@@ -425,7 +377,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 1970 */ _(TL,x), _(TL,x), _(TL,x), _(TL,x), _(TL,x), _(x,x), _(x,x), _(x,x),
/* 1978 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* New Tai Lue (1980..19DF) */
+ /* New Tai Lue */
/* 1980 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1988 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@@ -437,24 +389,21 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 19B8 */ _(M,R), _(M,R), _(M,L), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R),
/* 19C0 */ _(M,R), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x),
/* 19C8 */ _(TM,x), _(TM,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 19D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 19D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* FILLER (19E0..19FF) */
-
+ /* 19D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* 19D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 19E0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 19E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 19F0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 19F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Buginese (1A00..1A1F) */
+ /* Buginese */
/* 1A00 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1A08 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1A10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,T),
- /* 1A18 */ _(M,B), _(M,L), _(M,R), _(M,L), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1A18 */ _(M,B), _(M,L), _(M,R), _(M,T), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Tai Tham (1A20..1AAF) */
+ /* Tai Tham */
/* 1A20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1A28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@@ -462,25 +411,23 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 1A38 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1A40 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1A48 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x),
- /* 1A50 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(CM,x), _(CM,x), _(CF,x),
+ /* 1A50 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(CM,L), _(CM,x), _(CF,x),
/* 1A58 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(x,x),
- /* 1A60 */ _(V,I), _(M,R), _(M,T), _(M,R), _(M,R), _(M,T), _(M,T), _(M,T),
+ /* 1A60 */ _(IS,x), _(M,R), _(M,T), _(M,R), _(M,R), _(M,T), _(M,T), _(M,T),
/* 1A68 */ _(M,T), _(M,B), _(M,B), _(M,T), _(M,B), _(M,R), _(M,L), _(M,L),
/* 1A70 */ _(M,L), _(M,L), _(M,L), _(M,T), _(M,T), _(TM,x), _(TM,x), _(TM,x),
/* 1A78 */ _(TM,x), _(TM,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 1A80 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 1A88 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 1A90 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 1A98 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 1AA0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 1AA8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1A80 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* 1A88 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1A90 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* 1A98 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-#define indic_offset_0x1b00 2640
+#define indic_offset_0x1b00u 2120
- /* Balinese (1B00..1B7F) */
+ /* Balinese */
- /* 1B00 */ _(Bi,x), _(Bi,x), _(Bi,x), _(CR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 1B00 */ _(Bi,x), _(Bi,x), _(Bi,x),_(CSR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x),
/* 1B08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 1B10 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1B18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@@ -490,36 +437,36 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 1B38 */ _(M,B), _(M,B), _(M,B), _(M,BR), _(M,TB),_(M,TBR), _(M,L), _(M,L),
/* 1B40 */ _(M,LR), _(M,LR), _(M,T), _(M,TR), _(V,R), _(C,x), _(C,x), _(C,x),
/* 1B48 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 1B50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 1B58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1B50 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* 1B58 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1B60 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1B68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1B70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1B78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Sundanese (1B80..1BBF) */
+ /* Sundanese */
- /* 1B80 */ _(Bi,x), _(CR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 1B80 */ _(Bi,x),_(CSR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 1B88 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1B90 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1B98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1BA0 */ _(C,x), _(CS,x), _(CS,x), _(CS,x), _(M,T), _(M,B), _(M,L), _(M,R),
- /* 1BA8 */ _(M,T), _(M,T), _(V,R), _(V,x), _(CS,x), _(CS,x), _(C,x), _(C,x),
- /* 1BB0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 1BB8 */ _(x,x), _(x,x), _(A,x), _(C,x), _(C,x), _(C,x), _(CF,x), _(CF,x),
+ /* 1BA8 */ _(M,T), _(M,T), _(PK,R), _(IS,x), _(CS,x), _(CS,x), _(C,x), _(C,x),
+ /* 1BB0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* 1BB8 */ _(Nd,x), _(Nd,x), _(A,x), _(C,x), _(C,x), _(C,x), _(CF,x), _(CF,x),
- /* Batak (1BC0..1BFF) */
+ /* Batak */
/* 1BC0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1BC8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1BD0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1BD8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1BE0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(N,x), _(M,x),
- /* 1BE8 */ _(M,x), _(M,x), _(M,x), _(M,x), _(M,x), _(M,x), _(M,x), _(M,x),
- /* 1BF0 */ _(CF,x), _(CF,x), _(V,R), _(V,R), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1BE0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(N,x), _(M,R),
+ /* 1BE8 */ _(M,T), _(M,T), _(M,R), _(M,R), _(M,R), _(M,T), _(M,R), _(M,T),
+ /* 1BF0 */ _(CF,x), _(CF,x), _(PK,R), _(PK,R), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1BF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Lepcha (1C00..1C4F) */
+ /* Lepcha */
/* 1C00 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1C08 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@@ -527,41 +474,45 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 1C18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1C20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(CS,x), _(CS,x), _(M,R), _(M,L),
/* 1C28 */ _(M,L), _(M,TL), _(M,R), _(M,R), _(M,B), _(CF,x), _(CF,x), _(CF,x),
- /* 1C30 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(Bi,x), _(Bi,x), _(x,x), _(N,x),
+ /* 1C30 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(Bi,L), _(Bi,L), _(x,x), _(N,x),
/* 1C38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 1C40 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 1C48 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(C,x),
+ /* 1C40 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* 1C48 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(C,x),
-#define indic_offset_0x1cd0 2976
+#define indic_offset_0x1cd0u 2456
- /* Vedic Extensions (1CD0..1CFF) */
+ /* Vedic Extensions */
- /* 1CD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 1CD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 1CE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1CD0 */ _(TM,x), _(TM,x), _(TM,x), _(x,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x),
+ /* 1CD8 */ _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x),
+ /* 1CE0 */ _(TM,x), _(TM,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1CE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 1CF0 */ _(x,x), _(x,x), _(Vs,x), _(Vs,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 1CF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1CF0 */ _(x,x), _(x,x), _(Vs,x), _(Vs,x), _(TM,x), _(x,x), _(x,x), _(x,x),
-#define indic_offset_0xa800 3024
+#define indic_offset_0x2008u 2496
- /* Syloti Nagri (A800..A82F) */
+ /* General Punctuation */
- /* A800 */ _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(V,T), _(C,x),
+ /* 2008 */ _(x,x), _(x,x), _(x,x), _(x,x),_(ZWNJ,x),_(ZWJ,x), _(x,x), _(x,x),
+ /* 2010 */ _(x,x), _(x,x), _(CP,x), _(CP,x), _(CP,x), _(x,x), _(x,x), _(x,x),
+
+#define indic_offset_0xa800u 2512
+
+
+ /* Syloti Nagri */
+
+ /* A800 */ _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(PK,T), _(C,x),
/* A808 */ _(C,x), _(C,x), _(C,x), _(Bi,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A810 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A818 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A820 */ _(C,x), _(C,x), _(C,x), _(M,R), _(M,R), _(M,B), _(M,T), _(M,R),
/* A828 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* FILLER (A830..A83F) */
-
/* A830 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A838 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Phags-pa (A840..A87F) */
+ /* Phags-pa */
/* A840 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A848 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@@ -572,7 +523,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* A870 */ _(C,x), _(CS,x), _(C,x), _(Bi,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A878 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Saurashtra (A880..A8DF) */
+ /* Saurashtra */
/* A880 */ _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* A888 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
@@ -584,44 +535,41 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* A8B8 */ _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R),
/* A8C0 */ _(M,R), _(M,R), _(M,R), _(M,R), _(V,B), _(x,x), _(x,x), _(x,x),
/* A8C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* A8D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* A8D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A8D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* A8D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* FILLER (A8E0..A8FF) */
+ /* Devanagari Extended */
- /* A8E0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* A8E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* A8F0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A8E0 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x),
+ /* A8E8 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x),
+ /* A8F0 */ _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A8F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Kayah Li (A900..A92F) */
+ /* Kayah Li */
- /* A900 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* A908 */ _(x,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A900 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* A908 */ _(Nd,x), _(Nd,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A910 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A920 */ _(C,x), _(C,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x),
/* A928 */ _(Vo,x), _(Vo,x), _(Vo,x), _(TM,x), _(TM,x), _(TM,x), _(x,x), _(x,x),
- /* Rejang (A930..A95F) */
+ /* Rejang */
/* A930 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A938 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A940 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,B),
/* A948 */ _(M,B), _(M,B), _(M,T), _(M,B), _(M,B), _(M,B), _(M,B), _(CF,x),
- /* A950 */ _(CF,x), _(CF,x), _(CF,x), _(V,R), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A950 */ _(CF,x), _(CF,x), _(CF,x), _(PK,R), _(x,x), _(x,x), _(x,x), _(x,x),
/* A958 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* FILLER (A960..A97F) */
-
/* A960 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A968 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A970 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A978 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Javanese (A980..A9DF) */
+ /* Javanese */
- /* A980 */ _(Bi,x), _(Bi,x), _(CR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* A980 */ _(Bi,x), _(Bi,x),_(CSR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* A988 */ _(VI,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(C,x),
/* A990 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A998 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@@ -631,17 +579,17 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* A9B8 */ _(M,B), _(M,B), _(M,L), _(M,L), _(M,T), _(CS,x), _(CM,x), _(CM,x),
/* A9C0 */ _(V,BR), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A9C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* A9D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* A9D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A9D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* A9D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* FILLER (A9E0..A9FF) */
+ /* Myanmar Extended-B */
- /* A9E0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* A9E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* A9F0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* A9F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A9E0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(C,x),
+ /* A9E8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A9F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* A9F8 */ _(Nd,x), _(Nd,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x),
- /* Cham (AA00..AA5F) */
+ /* Cham */
/* AA00 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x),
/* AA08 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@@ -649,21 +597,21 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* AA18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* AA20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* AA28 */ _(C,x), _(M,T), _(M,T), _(M,T), _(M,T), _(M,B), _(M,T), _(M,L),
- /* AA30 */ _(M,L), _(M,T), _(M,B), _(CM,x), _(CM,x), _(CM,x), _(CM,x), _(x,x),
+ /* AA30 */ _(M,L), _(M,T), _(M,B), _(CM,x), _(CM,L), _(CM,x), _(CM,x), _(x,x),
/* AA38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* AA40 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x),
/* AA48 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(x,x), _(x,x),
- /* AA50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* AA58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* AA50 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* AA58 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Myanmar Extended-A (AA60..AA7F) */
+ /* Myanmar Extended-A */
/* AA60 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* AA68 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* AA70 */ _(x,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* AA78 */ _(x,x), _(x,x), _(C,x), _(TM,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* AA78 */ _(x,x), _(x,x), _(C,x), _(TM,x), _(TM,x), _(TM,x), _(C,x), _(C,x),
- /* Tai Viet (AA80..AADF) */
+ /* Tai Viet */
/* AA80 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* AA88 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@@ -678,31 +626,30 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* AAD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* AAD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Meetei Mayek Extensions (AAE0..AAFF) */
+ /* Meetei Mayek Extensions */
/* AAE0 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* AAE8 */ _(C,x), _(C,x), _(C,x), _(M,L), _(M,B), _(M,T), _(M,L), _(M,R),
- /* AAF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Vs,x), _(V,I), _(x,x),
- /* AAF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* AAF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Vs,x), _(IS,x), _(x,x),
-#define indic_offset_0xabc0 3792
+#define indic_offset_0xabc0u 3272
- /* Meetei Mayek (ABC0..ABFF) */
+ /* Meetei Mayek */
/* ABC0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* ABC8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x),
/* ABD0 */ _(C,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* ABD8 */ _(C,x), _(C,x), _(C,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x),
/* ABE0 */ _(CF,x), _(CF,x), _(CF,x), _(M,R), _(M,R), _(M,T), _(M,R), _(M,R),
- /* ABE8 */ _(M,B), _(M,R), _(M,R), _(x,x), _(TM,x), _(V,B), _(x,x), _(x,x),
- /* ABF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* ABF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* ABE8 */ _(M,B), _(M,R), _(M,R), _(x,x), _(TM,x), _(PK,B), _(x,x), _(x,x),
+ /* ABF0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* ABF8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-#define indic_offset_0x10a00 3856
+#define indic_offset_0x10a00u 3336
- /* Kharoshthi (10A00..10A5F) */
+ /* Kharoshthi */
/* 10A00 */ _(C,x), _(M,O), _(M,B), _(M,B), _(x,x), _(M,T), _(M,O), _(x,x),
/* 10A08 */ _(x,x), _(x,x), _(x,x), _(x,x), _(M,B), _(x,x), _(Bi,x), _(Vs,x),
@@ -711,16 +658,13 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 10A20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 10A28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 10A30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 10A38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(V,I),
- /* 10A40 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 10A48 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 10A50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 10A58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 10A38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(IS,x),
+ /* 10A40 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
-#define indic_offset_0x11000 3952
+#define indic_offset_0x11000u 3408
- /* Brahmi (11000..1107F) */
+ /* Brahmi */
/* 11000 */ _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 11008 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
@@ -732,14 +676,14 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 11038 */ _(M,T), _(M,T), _(M,T), _(M,T), _(M,B), _(M,B), _(M,B), _(M,B),
/* 11040 */ _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), _(M,T), _(V,T), _(x,x),
/* 11048 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 11050 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 11058 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 11060 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 11068 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 11050 */ _(x,x), _(x,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),
+ /* 11058 */_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),
+ /* 11060 */_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x), _(Nd,x), _(Nd,x),
+ /* 11068 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 11070 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 11078 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 11078 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(NJ,x),
- /* Kaithi (11080..110CF) */
+ /* Kaithi */
/* 11080 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 11088 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
@@ -749,13 +693,11 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 110A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 110B0 */ _(M,R), _(M,L), _(M,R), _(M,B), _(M,B), _(M,T), _(M,T), _(M,R),
/* 110B8 */ _(M,R), _(V,B), _(N,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 110C0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 110C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-#define indic_offset_0x11100 4160
+#define indic_offset_0x11100u 3600
- /* Chakma (11100..1114F) */
+ /* Chakma */
/* 11100 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x),
/* 11108 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@@ -763,15 +705,21 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 11118 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11120 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,T),
/* 11128 */ _(M,T), _(M,T), _(M,B), _(M,B), _(M,L), _(M,T), _(M,TB), _(M,TB),
- /* 11130 */ _(M,T), _(M,B), _(M,B), _(V,I), _(V,T), _(x,x), _(x,x), _(x,x),
- /* 11138 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 11130 */ _(M,T), _(M,B), _(M,B), _(IS,x), _(PK,T), _(x,x), _(Nd,x), _(Nd,x),
+ /* 11138 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 11140 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 11148 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-#define indic_offset_0x11180 4240
+ /* Mahajani */
+ /* 11150 */ _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(C,x), _(C,x), _(C,x),
+ /* 11158 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11160 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11168 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11170 */ _(C,x), _(C,x), _(C,x), _(N,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 11178 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* Sharada (11180..111DF) */
+ /* Sharada */
/* 11180 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 11188 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
@@ -783,13 +731,116 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 111B8 */ _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), _(M,TR),
/* 111C0 */ _(V,R), _(A,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 111C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 111D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 111D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
-#define indic_offset_0x11680 4336
-
-
- /* Takri (11680..116CF) */
+ /* 111D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* 111D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Sinhala Archaic Numbers */
+
+ /* 111E0 */ _(x,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* 111E8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* 111F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x),
+ /* 111F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Khojki */
+
+ /* 11200 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 11208 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11210 */ _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11218 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11220 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11228 */ _(C,x), _(C,x), _(C,x), _(C,x), _(M,R), _(M,R), _(M,R), _(M,B),
+ /* 11230 */ _(M,T), _(M,T), _(M,TR), _(M,TR), _(Bi,x), _(V,R), _(N,x), _(GM,T),
+
+#define indic_offset_0x112b0u 3912
+
+
+ /* Khudawadi */
+
+ /* 112B0 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 112B8 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 112C0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 112C8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 112D0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 112D8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(Bi,x),
+ /* 112E0 */ _(M,R), _(M,L), _(M,R), _(M,B), _(M,B), _(M,T), _(M,T), _(M,T),
+ /* 112E8 */ _(M,T), _(N,x), _(PK,B), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 112F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* 112F8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Grantha */
+
+ /* 11300 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 11308 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x),
+ /* 11310 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
+ /* 11318 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11320 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11328 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11330 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
+ /* 11338 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,R),
+ /* 11340 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(x,x), _(M,L),
+ /* 11348 */ _(M,L), _(x,x), _(x,x), _(M,LR), _(M,LR), _(V,R), _(x,x), _(x,x),
+ /* 11350 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
+ /* 11358 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 11360 */ _(VI,x), _(VI,x), _(M,R), _(M,R), _(x,x), _(x,x), _(Ca,x), _(Ca,x),
+ /* 11368 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x),
+ /* 11370 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x),
+
+#define indic_offset_0x11480u 4112
+
+
+ /* Tirhuta */
+
+ /* 11480 */ _(x,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 11488 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x),
+ /* 11490 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11498 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 114A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 114A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 114B0 */ _(M,R), _(M,L), _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,B),
+ /* 114B8 */ _(M,B), _(M,L), _(M,T), _(M,TL), _(M,LR), _(M,R), _(M,LR), _(Bi,x),
+ /* 114C0 */ _(Bi,x), _(Vs,x), _(V,B), _(N,x), _(A,x), _(x,x), _(x,x), _(x,x),
+ /* 114C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 114D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* 114D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+#define indic_offset_0x11580u 4208
+
+
+ /* Siddham */
+
+ /* 11580 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 11588 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x),
+ /* 11590 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11598 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 115A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 115A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,R),
+ /* 115B0 */ _(M,L), _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x),
+ /* 115B8 */ _(M,L), _(M,TL), _(M,LR),_(M,TLR), _(Bi,x), _(Bi,x), _(Vs,x), _(V,B),
+ /* 115C0 */ _(N,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+#define indic_offset_0x11600u 4280
+
+
+ /* Modi */
+
+ /* 11600 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 11608 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x),
+ /* 11610 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11618 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11620 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11628 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11630 */ _(M,R), _(M,R), _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,B),
+ /* 11638 */ _(M,B), _(M,T), _(M,T), _(M,R), _(M,R), _(Bi,x), _(Vs,x), _(V,B),
+ /* 11640 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 11648 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 11650 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* 11658 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 11660 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 11668 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 11670 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 11678 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Takri */
/* 11680 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 11688 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@@ -799,30 +850,57 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 116A8 */ _(C,x), _(C,x), _(C,x), _(Bi,x), _(Vs,x), _(M,T), _(M,L), _(M,R),
/* 116B0 */ _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), _(M,T), _(V,T), _(N,x),
/* 116B8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 116C0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 116C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
-#define indic_offset_total 4416
+ /* 116C0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+ /* 116C8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-}; /* Table occupancy: 60% */
+}; /* Table items: 4488; occupancy: 73% */
INDIC_TABLE_ELEMENT_TYPE
hb_indic_get_categories (hb_codepoint_t u)
{
- if (0x0900 <= u && u <= 0x10A0) return indic_table[u - 0x0900 + indic_offset_0x0900];
- if (0x1700 <= u && u <= 0x1800) return indic_table[u - 0x1700 + indic_offset_0x1700];
- if (0x1900 <= u && u <= 0x1AB0) return indic_table[u - 0x1900 + indic_offset_0x1900];
- if (0x1B00 <= u && u <= 0x1C50) return indic_table[u - 0x1B00 + indic_offset_0x1b00];
- if (0x1CD0 <= u && u <= 0x1D00) return indic_table[u - 0x1CD0 + indic_offset_0x1cd0];
- if (0xA800 <= u && u <= 0xAB00) return indic_table[u - 0xA800 + indic_offset_0xa800];
- if (0xABC0 <= u && u <= 0xAC00) return indic_table[u - 0xABC0 + indic_offset_0xabc0];
- if (0x10A00 <= u && u <= 0x10A60) return indic_table[u - 0x10A00 + indic_offset_0x10a00];
- if (0x11000 <= u && u <= 0x110D0) return indic_table[u - 0x11000 + indic_offset_0x11000];
- if (0x11100 <= u && u <= 0x11150) return indic_table[u - 0x11100 + indic_offset_0x11100];
- if (0x11180 <= u && u <= 0x111E0) return indic_table[u - 0x11180 + indic_offset_0x11180];
- if (0x11680 <= u && u <= 0x116D0) return indic_table[u - 0x11680 + indic_offset_0x11680];
- if (unlikely (u == 0x00A0)) return _(CP,x);
- if (unlikely (u == 0x25CC)) return _(CP,x);
+ switch (u >> 12)
+ {
+ case 0x0u:
+ if (hb_in_range (u, 0x0028u, 0x0040u)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
+ if (hb_in_range (u, 0x00D0u, 0x00D8u)) return indic_table[u - 0x00D0u + indic_offset_0x00d0u];
+ if (hb_in_range (u, 0x0900u, 0x0DF8u)) return indic_table[u - 0x0900u + indic_offset_0x0900u];
+ if (unlikely (u == 0x00A0u)) return _(CP,x);
+ break;
+
+ case 0x1u:
+ if (hb_in_range (u, 0x1000u, 0x10A0u)) return indic_table[u - 0x1000u + indic_offset_0x1000u];
+ if (hb_in_range (u, 0x1700u, 0x17F0u)) return indic_table[u - 0x1700u + indic_offset_0x1700u];
+ if (hb_in_range (u, 0x1900u, 0x1AA0u)) return indic_table[u - 0x1900u + indic_offset_0x1900u];
+ if (hb_in_range (u, 0x1B00u, 0x1C50u)) return indic_table[u - 0x1B00u + indic_offset_0x1b00u];
+ if (hb_in_range (u, 0x1CD0u, 0x1CF8u)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
+ break;
+
+ case 0x2u:
+ if (hb_in_range (u, 0x2008u, 0x2018u)) return indic_table[u - 0x2008u + indic_offset_0x2008u];
+ if (unlikely (u == 0x25CCu)) return _(CP,x);
+ break;
+
+ case 0xAu:
+ if (hb_in_range (u, 0xA800u, 0xAAF8u)) return indic_table[u - 0xA800u + indic_offset_0xa800u];
+ if (hb_in_range (u, 0xABC0u, 0xAC00u)) return indic_table[u - 0xABC0u + indic_offset_0xabc0u];
+ break;
+
+ case 0x10u:
+ if (hb_in_range (u, 0x10A00u, 0x10A48u)) return indic_table[u - 0x10A00u + indic_offset_0x10a00u];
+ break;
+
+ case 0x11u:
+ if (hb_in_range (u, 0x11000u, 0x110C0u)) return indic_table[u - 0x11000u + indic_offset_0x11000u];
+ if (hb_in_range (u, 0x11100u, 0x11238u)) return indic_table[u - 0x11100u + indic_offset_0x11100u];
+ if (hb_in_range (u, 0x112B0u, 0x11378u)) return indic_table[u - 0x112B0u + indic_offset_0x112b0u];
+ if (hb_in_range (u, 0x11480u, 0x114E0u)) return indic_table[u - 0x11480u + indic_offset_0x11480u];
+ if (hb_in_range (u, 0x11580u, 0x115C8u)) return indic_table[u - 0x11580u + indic_offset_0x11580u];
+ if (hb_in_range (u, 0x11600u, 0x116D0u)) return indic_table[u - 0x11600u + indic_offset_0x11600u];
+ break;
+
+ default:
+ break;
+ }
return _(x,x);
}
@@ -830,17 +908,27 @@ hb_indic_get_categories (hb_codepoint_t u)
#undef ISC_A
#undef ISC_Bi
+#undef ISC_BJN
+#undef ISC_Ca
#undef ISC_C
#undef ISC_CD
#undef ISC_CF
#undef ISC_CHL
#undef ISC_CM
#undef ISC_CP
-#undef ISC_CR
+#undef ISC_CPR
#undef ISC_CS
+#undef ISC_CSR
+#undef ISC_GM
+#undef ISC_IS
+#undef ISC_ZWJ
#undef ISC_ML
+#undef ISC_ZWNJ
#undef ISC_N
+#undef ISC_Nd
+#undef ISC_NJ
#undef ISC_x
+#undef ISC_PK
#undef ISC_RS
#undef ISC_TL
#undef ISC_TM
@@ -852,7 +940,6 @@ hb_indic_get_categories (hb_codepoint_t u)
#undef IMC_B
#undef IMC_BR
-#undef IMC_I
#undef IMC_L
#undef IMC_LR
#undef IMC_x
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc
index 1e07d33177..33215a304f 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc
@@ -37,19 +37,19 @@
*/
-#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7F) == (Base))
+#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7Fu) == (Base))
-#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900))
-#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980))
-#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00))
-#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80))
-#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00))
-#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80))
-#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00))
-#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80))
-#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00))
-#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80))
-#define IS_KHMR(u) (IN_HALF_BLOCK (u, 0x1780))
+#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900u))
+#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980u))
+#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00u))
+#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80u))
+#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00u))
+#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80u))
+#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00u))
+#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80u))
+#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00u))
+#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80u))
+#define IS_KHMR(u) (IN_HALF_BLOCK (u, 0x1780u))
#define MATRA_POS_LEFT(u) POS_PRE_M
@@ -60,8 +60,8 @@
IS_GUJR(u) ? POS_AFTER_POST : \
IS_ORYA(u) ? POS_AFTER_POST : \
IS_TAML(u) ? POS_AFTER_POST : \
- IS_TELU(u) ? (u <= 0x0C42 ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
- IS_KNDA(u) ? (u < 0x0CC3 || u > 0xCD6 ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
+ IS_TELU(u) ? (u <= 0x0C42u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
+ IS_KNDA(u) ? (u < 0x0CC3u || u > 0xCD6u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
IS_MLYM(u) ? POS_AFTER_POST : \
IS_SINH(u) ? POS_AFTER_SUB : \
IS_KHMR(u) ? POS_AFTER_POST : \
@@ -112,20 +112,20 @@ matra_position (hb_codepoint_t u, indic_position_t side)
* Or completely remove it and just check in the tables.
*/
static const hb_codepoint_t ra_chars[] = {
- 0x0930, /* Devanagari */
- 0x09B0, /* Bengali */
- 0x09F0, /* Bengali */
- 0x0A30, /* Gurmukhi */ /* No Reph */
- 0x0AB0, /* Gujarati */
- 0x0B30, /* Oriya */
- 0x0BB0, /* Tamil */ /* No Reph */
- 0x0C30, /* Telugu */ /* Reph formed only with ZWJ */
- 0x0CB0, /* Kannada */
- 0x0D30, /* Malayalam */ /* No Reph, Logical Repha */
-
- 0x0DBB, /* Sinhala */ /* Reph formed only with ZWJ */
-
- 0x179A, /* Khmer */ /* No Reph, Visual Repha */
+ 0x0930u, /* Devanagari */
+ 0x09B0u, /* Bengali */
+ 0x09F0u, /* Bengali */
+ 0x0A30u, /* Gurmukhi */ /* No Reph */
+ 0x0AB0u, /* Gujarati */
+ 0x0B30u, /* Oriya */
+ 0x0BB0u, /* Tamil */ /* No Reph */
+ 0x0C30u, /* Telugu */ /* Reph formed only with ZWJ */
+ 0x0CB0u, /* Kannada */
+ 0x0D30u, /* Malayalam */ /* No Reph, Logical Repha */
+
+ 0x0DBBu, /* Sinhala */ /* Reph formed only with ZWJ */
+
+ 0x179Au, /* Khmer */ /* No Reph, Visual Repha */
};
static inline bool
@@ -145,28 +145,18 @@ is_one_of (const hb_glyph_info_t &info, unsigned int flags)
return !!(FLAG (info.indic_category()) & flags);
}
-#define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ))
static inline bool
is_joiner (const hb_glyph_info_t &info)
{
return is_one_of (info, JOINER_FLAGS);
}
-#define MEDIAL_FLAGS (FLAG (OT_CM) | FLAG (OT_CM2))
-
-/* Note:
- *
- * We treat Vowels and placeholders as if they were consonants. This is safe because Vowels
- * cannot happen in a consonant syllable. The plus side however is, we can call the
- * consonant syllable logic from the vowel syllable function and get it all right! */
-#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_Ra) | MEDIAL_FLAGS | FLAG (OT_V) | FLAG (OT_NBSP) | FLAG (OT_DOTTEDCIRCLE))
static inline bool
is_consonant (const hb_glyph_info_t &info)
{
return is_one_of (info, CONSONANT_FLAGS);
}
-#define HALANT_OR_COENG_FLAGS (FLAG (OT_H) | FLAG (OT_Coeng))
static inline bool
is_halant_or_coeng (const hb_glyph_info_t &info)
{
@@ -178,7 +168,7 @@ set_indic_properties (hb_glyph_info_t &info)
{
hb_codepoint_t u = info.codepoint;
unsigned int type = hb_indic_get_categories (u);
- indic_category_t cat = (indic_category_t) (type & 0x7F);
+ indic_category_t cat = (indic_category_t) (type & 0x7Fu);
indic_position_t pos = (indic_position_t) (type >> 8);
@@ -188,48 +178,59 @@ set_indic_properties (hb_glyph_info_t &info)
/* The spec says U+0952 is OT_A. However, testing shows that Uniscribe
- * treats U+0951..U+0954 all behave similarly.
- * TESTS:
+ * treats a whole bunch of characters similarly.
+ * TESTS: For example, for U+0951:
* U+092E,U+0947,U+0952
* U+092E,U+0952,U+0947
* U+092E,U+0947,U+0951
* U+092E,U+0951,U+0947
+ * U+092E,U+0951,U+0952
+ * U+092E,U+0952,U+0951
*/
- if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x0951, 0x0954)))
+ if (unlikely (hb_in_ranges (u, 0x0951u, 0x0952u,
+ 0x1CD0u, 0x1CD2u,
+ 0x1CD4u, 0x1CE1u) ||
+ u == 0x1CF4u))
cat = OT_A;
-
- if (unlikely (u == 0x17D1))
- cat = OT_X;
- if (cat == OT_X &&
- unlikely (hb_in_range<hb_codepoint_t> (u, 0x17CB, 0x17D3))) /* Khmer Various signs */
+ /* The following act more like the Bindus. */
+ else if (unlikely (hb_in_range (u, 0x0953u, 0x0954u)))
+ cat = OT_SM;
+ /* The following act like consonants. */
+ else if (unlikely (hb_in_ranges (u, 0x0A72u, 0x0A73u,
+ 0x1CF5u, 0x1CF6u)))
+ cat = OT_C;
+ /* TODO: The following should only be allowed after a Visarga.
+ * For now, just treat them like regular tone marks. */
+ else if (unlikely (hb_in_range (u, 0x1CE2u, 0x1CE8u)))
+ cat = OT_A;
+ /* TODO: The following should only be allowed after some of
+ * the nasalization marks, maybe only for U+1CE9..U+1CF1.
+ * For now, just treat them like tone marks. */
+ else if (unlikely (u == 0x1CEDu))
+ cat = OT_A;
+ /* The following take marks in standalone clusters, similar to Avagraha. */
+ else if (unlikely (hb_in_ranges (u, 0xA8F2u, 0xA8F7u,
+ 0x1CE9u, 0x1CECu,
+ 0x1CEEu, 0x1CF1u)))
+ {
+ cat = OT_Symbol;
+ ASSERT_STATIC ((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol);
+ }
+ else if (unlikely (hb_in_range (u, 0x17CDu, 0x17D1u) ||
+ u == 0x17CBu || u == 0x17D3u || u == 0x17DDu)) /* Khmer Various signs */
{
/* These are like Top Matras. */
cat = OT_M;
pos = POS_ABOVE_C;
}
- if (u == 0x17C6) /* Khmer Bindu doesn't like to be repositioned. */
- cat = OT_N;
-
- if (unlikely (u == 0x17D2)) cat = OT_Coeng; /* Khmer coeng */
- else if (unlikely (u == 0x200C)) cat = OT_ZWNJ;
- else if (unlikely (u == 0x200D)) cat = OT_ZWJ;
- else if (unlikely (u == 0x25CC)) cat = OT_DOTTEDCIRCLE;
- else if (unlikely (u == 0x0A71)) cat = OT_SM; /* GURMUKHI ADDAK. Move it to the end. */
- else if (unlikely (u == 0xA982)) cat = OT_SM; /* Javanese repha. */
- else if (unlikely (u == 0xA9BE)) cat = OT_CM2; /* Javanese medial ya. */
- else if (unlikely (u == 0xA9BD)) { cat = OT_M; pos = POS_POST_C; } /* Javanese vocalic r. */
-
- if (cat == OT_Repha) {
- /* There are two kinds of characters marked as Repha:
- * - The ones that are GenCat=Mn are already positioned visually, ie. after base. (eg. Khmer)
- * - The ones that are GenCat=Lo is encoded logically, ie. beginning of syllable. (eg. Malayalam)
- *
- * We recategorize the first kind to look like a Nukta and attached to the base directly.
- */
- if (_hb_glyph_info_get_general_category (&info) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
- cat = OT_N;
- }
-
+ else if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */
+ else if (unlikely (u == 0x17D2u)) cat = OT_Coeng; /* Khmer coeng */
+ else if (unlikely (hb_in_range (u, 0x2010u, 0x2011u)))
+ cat = OT_PLACEHOLDER;
+ else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
+ else if (unlikely (u == 0xA982u)) cat = OT_SM; /* Javanese repha. */
+ else if (unlikely (u == 0xA9BEu)) cat = OT_CM2; /* Javanese medial ya. */
+ else if (unlikely (u == 0xA9BDu)) { cat = OT_M; pos = POS_POST_C; } /* Javanese vocalic r. */
/*
@@ -246,12 +247,12 @@ set_indic_properties (hb_glyph_info_t &info)
{
pos = matra_position (u, pos);
}
- else if ((FLAG (cat) & (FLAG (OT_SM) | FLAG (OT_VD) | FLAG (OT_A) | FLAG (OT_Avag))))
+ else if ((FLAG (cat) & (FLAG (OT_SM) | FLAG (OT_VD) | FLAG (OT_A) | FLAG (OT_Symbol))))
{
pos = POS_SMVD;
}
- if (unlikely (u == 0x0B01)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */
+ if (unlikely (u == 0x0B01u)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */
@@ -315,20 +316,20 @@ struct indic_config_t
static const indic_config_t indic_configs[] =
{
/* Default. Should be first. */
- {HB_SCRIPT_INVALID, false, 0,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_1},
- {HB_SCRIPT_DEVANAGARI,true, 0x094D,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
- {HB_SCRIPT_BENGALI, true, 0x09CD,BASE_POS_LAST, REPH_POS_AFTER_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
- {HB_SCRIPT_GURMUKHI, true, 0x0A4D,BASE_POS_LAST, REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
- {HB_SCRIPT_GUJARATI, true, 0x0ACD,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
- {HB_SCRIPT_ORIYA, true, 0x0B4D,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
- {HB_SCRIPT_TAMIL, true, 0x0BCD,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_2},
- {HB_SCRIPT_TELUGU, true, 0x0C4D,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_POST_ONLY, PREF_LEN_2},
- {HB_SCRIPT_KANNADA, true, 0x0CCD,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY, PREF_LEN_2},
- {HB_SCRIPT_MALAYALAM, true, 0x0D4D,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_2},
- {HB_SCRIPT_SINHALA, false,0x0DCA,BASE_POS_LAST_SINHALA,
- REPH_POS_AFTER_MAIN, REPH_MODE_EXPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
- {HB_SCRIPT_KHMER, false,0x17D2,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_2},
- {HB_SCRIPT_JAVANESE, false,0xA9C0,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_1},
+ {HB_SCRIPT_INVALID, false, 0,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_1},
+ {HB_SCRIPT_DEVANAGARI,true, 0x094Du,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
+ {HB_SCRIPT_BENGALI, true, 0x09CDu,BASE_POS_LAST, REPH_POS_AFTER_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
+ {HB_SCRIPT_GURMUKHI, true, 0x0A4Du,BASE_POS_LAST, REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
+ {HB_SCRIPT_GUJARATI, true, 0x0ACDu,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
+ {HB_SCRIPT_ORIYA, true, 0x0B4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
+ {HB_SCRIPT_TAMIL, true, 0x0BCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_2},
+ {HB_SCRIPT_TELUGU, true, 0x0C4Du,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_POST_ONLY, PREF_LEN_2},
+ {HB_SCRIPT_KANNADA, true, 0x0CCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY, PREF_LEN_2},
+ {HB_SCRIPT_MALAYALAM, true, 0x0D4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_2},
+ {HB_SCRIPT_SINHALA, false,0x0DCAu,BASE_POS_LAST_SINHALA,
+ REPH_POS_AFTER_MAIN, REPH_MODE_EXPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
+ {HB_SCRIPT_KHMER, false,0x17D2u,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_2},
+ {HB_SCRIPT_JAVANESE, false,0xA9C0u,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_1},
};
@@ -552,12 +553,12 @@ data_create_indic (const hb_ot_shape_plan_t *plan)
break;
}
- indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FF) != '2');
+ indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FFu) != '2');
indic_plan->virama_glyph = (hb_codepoint_t) -1;
/* Use zero-context would_substitute() matching for new-spec of the main
- * Indic scripts, but not for old-spec or scripts with one spec only. */
- bool zero_context = indic_plan->config->has_old_spec || !indic_plan->is_old_spec;
+ * Indic scripts, and scripts with one spec only, but not for old-specs. */
+ bool zero_context = !indic_plan->is_old_spec;
indic_plan->rphf.init (&plan->map, HB_TAG('r','p','h','f'), zero_context);
indic_plan->pref.init (&plan->map, HB_TAG('p','r','e','f'), zero_context);
indic_plan->blwf.init (&plan->map, HB_TAG('b','l','w','f'), zero_context);
@@ -614,7 +615,7 @@ enum syllable_type_t {
consonant_syllable,
vowel_syllable,
standalone_cluster,
- avagraha_cluster,
+ symbol_cluster,
broken_cluster,
non_indic_cluster,
};
@@ -634,8 +635,9 @@ setup_masks_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
* and setup masks later on in a pause-callback. */
unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
- set_indic_properties (buffer->info[i]);
+ set_indic_properties (info[i]);
}
static void
@@ -672,10 +674,12 @@ update_consonant_positions (const hb_ot_shape_plan_t *plan,
{
hb_face_t *face = font->face;
unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
- if (buffer->info[i].indic_position() == POS_BASE_C) {
- hb_codepoint_t consonant = buffer->info[i].codepoint;
- buffer->info[i].indic_position() = consonant_position_from_face (indic_plan, consonant, virama, face);
+ if (info[i].indic_position() == POS_BASE_C)
+ {
+ hb_codepoint_t consonant = info[i].codepoint;
+ info[i].indic_position() = consonant_position_from_face (indic_plan, consonant, virama, face);
}
}
}
@@ -725,8 +729,13 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
))
{
/* See if it matches the 'rphf' feature. */
- hb_codepoint_t glyphs[2] = {info[start].codepoint, info[start + 1].codepoint};
- if (indic_plan->rphf.would_substitute (glyphs, ARRAY_LENGTH (glyphs), face))
+ hb_codepoint_t glyphs[3] = {info[start].codepoint,
+ info[start + 1].codepoint,
+ indic_plan->config->reph_mode == REPH_MODE_EXPLICIT ?
+ info[start + 2].codepoint : 0};
+ if (indic_plan->rphf.would_substitute (glyphs, 2, face) ||
+ (indic_plan->config->reph_mode == REPH_MODE_EXPLICIT &&
+ indic_plan->rphf.would_substitute (glyphs, 3, face)))
{
limit += 2;
while (limit < end && is_joiner (info[limit]))
@@ -801,7 +810,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
case BASE_POS_LAST_SINHALA:
{
/* Sinhala base positioning is slightly different from main Indic, in that:
- * 1. It's ZWJ behavior is different,
+ * 1. Its ZWJ behavior is different,
* 2. We don't need to look into the font for consonant positions.
*/
@@ -1151,8 +1160,8 @@ initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
- /* We treat NBSP/dotted-circle as if they are consonants, so we should just chain.
- * Only if not in compatibility mode that is... */
+ /* We treat placeholder/dotted-circle as if they are consonants, so we
+ * should just chain. Only if not in compatibility mode that is... */
if (hb_options ().uniscribe_bug_compatible)
{
@@ -1177,10 +1186,10 @@ initial_reordering_broken_cluster (const hb_ot_shape_plan_t *plan,
}
static void
-initial_reordering_avagraha_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_face_t *face HB_UNUSED,
- hb_buffer_t *buffer HB_UNUSED,
- unsigned int start HB_UNUSED, unsigned int end HB_UNUSED)
+initial_reordering_symbol_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_face_t *face HB_UNUSED,
+ hb_buffer_t *buffer HB_UNUSED,
+ unsigned int start HB_UNUSED, unsigned int end HB_UNUSED)
{
/* Nothing to do right now. If we ever switch to using the output
* buffer in the reordering process, we'd need to next_glyph() here. */
@@ -1208,7 +1217,7 @@ initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
case consonant_syllable: initial_reordering_consonant_syllable (plan, face, buffer, start, end); return;
case vowel_syllable: initial_reordering_vowel_syllable (plan, face, buffer, start, end); return;
case standalone_cluster: initial_reordering_standalone_cluster (plan, face, buffer, start, end); return;
- case avagraha_cluster: initial_reordering_avagraha_cluster (plan, face, buffer, start, end); return;
+ case symbol_cluster: initial_reordering_symbol_cluster (plan, face, buffer, start, end); return;
case broken_cluster: initial_reordering_broken_cluster (plan, face, buffer, start, end); return;
case non_indic_cluster: initial_reordering_non_indic_cluster (plan, face, buffer, start, end); return;
}
@@ -1222,8 +1231,10 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
/* Note: This loop is extra overhead, but should not be measurable. */
bool has_broken_syllables = false;
unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
- if ((buffer->info[i].syllable() & 0x0F) == broken_cluster) {
+ if ((info[i].syllable() & 0x0F) == broken_cluster)
+ {
has_broken_syllables = true;
break;
}
@@ -1232,11 +1243,11 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_codepoint_t dottedcircle_glyph;
- if (!font->get_glyph (0x25CC, 0, &dottedcircle_glyph))
+ if (!font->get_glyph (0x25CCu, 0, &dottedcircle_glyph))
return;
hb_glyph_info_t dottedcircle = {0};
- dottedcircle.codepoint = 0x25CC;
+ dottedcircle.codepoint = 0x25CCu;
set_indic_properties (dottedcircle);
dottedcircle.codepoint = dottedcircle_glyph;
@@ -1302,6 +1313,27 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
hb_glyph_info_t *info = buffer->info;
+
+ /* This function relies heavily on halant glyphs. Lots of ligation
+ * and possibly multiplication substitutions happened prior to this
+ * phase, and that might have messed up our properties. Recover
+ * from a particular case of that where we're fairly sure that a
+ * class of OT_H is desired but has been lost. */
+ if (indic_plan->virama_glyph)
+ {
+ unsigned int virama_glyph = indic_plan->virama_glyph;
+ for (unsigned int i = start; i < end; i++)
+ if (info[i].codepoint == virama_glyph &&
+ _hb_glyph_info_ligated (&info[i]) &&
+ _hb_glyph_info_multiplied (&info[i]))
+ {
+ /* This will make sure that this glyph passes is_halant_or_coeng() test. */
+ info[i].indic_category() = OT_H;
+ _hb_glyph_info_clear_ligated_and_multiplied (&info[i]);
+ }
+ }
+
+
/* 4. Final reordering:
*
* After the localized forms and basic shaping forms GSUB features have been
@@ -1310,21 +1342,45 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
* cluster.
*/
+ bool try_pref = !!indic_plan->mask_array[PREF];
+
/* Find base again */
unsigned int base;
for (base = start; base < end; base++)
- if (info[base].indic_position() >= POS_BASE_C) {
+ if (info[base].indic_position() >= POS_BASE_C)
+ {
+ if (try_pref && base + 1 < end && indic_plan->config->pref_len == 2)
+ {
+ for (unsigned int i = base + 1; i < end; i++)
+ if ((info[i].mask & indic_plan->mask_array[PREF]) != 0)
+ {
+ if (!(_hb_glyph_info_substituted (&info[i]) &&
+ _hb_glyph_info_ligated_and_didnt_multiply (&info[i])))
+ {
+ /* Ok, this was a 'pref' candidate but didn't form any.
+ * Base is around here... */
+ base = i;
+ while (base < end && is_halant_or_coeng (info[base]))
+ base++;
+ info[base].indic_position() = POS_BASE_C;
+
+ try_pref = false;
+ }
+ break;
+ }
+ }
+
if (start < base && info[base].indic_position() > POS_BASE_C)
base--;
break;
}
if (base == end && start < base &&
- info[base - 1].indic_category() != OT_ZWJ)
- base--;
- while (start < base &&
- (info[base].indic_category() == OT_H ||
- info[base].indic_category() == OT_N))
+ is_one_of (info[base - 1], FLAG (OT_ZWJ)))
base--;
+ if (base < end)
+ while (start < base &&
+ is_one_of (info[base], (FLAG (OT_N) | HALANT_OR_COENG_FLAGS)))
+ base--;
/* o Reorder matras:
@@ -1349,7 +1405,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
if (buffer->props.script != HB_SCRIPT_MALAYALAM && buffer->props.script != HB_SCRIPT_TAMIL)
{
while (new_pos > start &&
- !(is_one_of (info[new_pos], (FLAG (OT_M) | FLAG (OT_H) | FLAG (OT_Coeng)))))
+ !(is_one_of (info[new_pos], (FLAG (OT_M) | HALANT_OR_COENG_FLAGS))))
new_pos--;
/* If we found no Halant we are done.
@@ -1412,7 +1468,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
if (start + 1 < end &&
info[start].indic_position() == POS_RA_TO_BECOME_REPH &&
((info[start].indic_category() == OT_Repha) ^
- _hb_glyph_info_ligated (&info[start])))
+ _hb_glyph_info_ligated_and_didnt_multiply (&info[start])))
{
unsigned int new_reph_pos;
reph_position_t reph_pos = indic_plan->config->reph_pos;
@@ -1549,7 +1605,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
* the following rules:
*/
- if (indic_plan->mask_array[PREF] && base + 1 < end) /* Otherwise there can't be any pre-base reordering Ra. */
+ if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base reordering Ra. */
{
unsigned int pref_len = indic_plan->config->pref_len;
for (unsigned int i = base + 1; i < end; i++)
@@ -1565,7 +1621,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
* If pref len is longer than one, then only reorder if it ligated. If
* pref len is one, only reorder if it didn't ligate with other things. */
if (_hb_glyph_info_substituted (&info[i]) &&
- ((pref_len == 1) ^ _hb_glyph_info_ligated (&info[i])))
+ ((pref_len == 1) ^ _hb_glyph_info_ligated_and_didnt_multiply (&info[i])))
{
/*
* 2. Try to find a target position the same way as for pre-base matra.
@@ -1699,37 +1755,37 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c,
switch (ab)
{
/* Don't decompose these. */
- case 0x0931 : return false;
- case 0x0B94 : return false;
+ case 0x0931u : return false;
+ case 0x0B94u : return false;
/*
* Decompose split matras that don't have Unicode decompositions.
*/
- case 0x0F77 : *a = 0x0FB2; *b= 0x0F81; return true;
- case 0x0F79 : *a = 0x0FB3; *b= 0x0F81; return true;
- case 0x17BE : *a = 0x17C1; *b= 0x17BE; return true;
- case 0x17BF : *a = 0x17C1; *b= 0x17BF; return true;
- case 0x17C0 : *a = 0x17C1; *b= 0x17C0; return true;
- case 0x17C4 : *a = 0x17C1; *b= 0x17C4; return true;
- case 0x17C5 : *a = 0x17C1; *b= 0x17C5; return true;
- case 0x1925 : *a = 0x1920; *b= 0x1923; return true;
- case 0x1926 : *a = 0x1920; *b= 0x1924; return true;
- case 0x1B3C : *a = 0x1B42; *b= 0x1B3C; return true;
- case 0x1112E : *a = 0x11127; *b= 0x11131; return true;
- case 0x1112F : *a = 0x11127; *b= 0x11132; return true;
+ case 0x0F77u : *a = 0x0FB2u; *b= 0x0F81u; return true;
+ case 0x0F79u : *a = 0x0FB3u; *b= 0x0F81u; return true;
+ case 0x17BEu : *a = 0x17C1u; *b= 0x17BEu; return true;
+ case 0x17BFu : *a = 0x17C1u; *b= 0x17BFu; return true;
+ case 0x17C0u : *a = 0x17C1u; *b= 0x17C0u; return true;
+ case 0x17C4u : *a = 0x17C1u; *b= 0x17C4u; return true;
+ case 0x17C5u : *a = 0x17C1u; *b= 0x17C5u; return true;
+ case 0x1925u : *a = 0x1920u; *b= 0x1923u; return true;
+ case 0x1926u : *a = 0x1920u; *b= 0x1924u; return true;
+ case 0x1B3Cu : *a = 0x1B42u; *b= 0x1B3Cu; return true;
+ case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true;
+ case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true;
#if 0
/* This one has no decomposition in Unicode, but needs no decomposition either. */
- /* case 0x0AC9 : return false; */
- case 0x0B57 : *a = no decomp, -> RIGHT; return true;
- case 0x1C29 : *a = no decomp, -> LEFT; return true;
- case 0xA9C0 : *a = no decomp, -> RIGHT; return true;
- case 0x111BF : *a = no decomp, -> ABOVE; return true;
+ /* case 0x0AC9u : return false; */
+ case 0x0B57u : *a = no decomp, -> RIGHT; return true;
+ case 0x1C29u : *a = no decomp, -> LEFT; return true;
+ case 0xA9C0u : *a = no decomp, -> RIGHT; return true;
+ case 0x111BuF : *a = no decomp, -> ABOVE; return true;
#endif
}
- if ((ab == 0x0DDA || hb_in_range<hb_codepoint_t> (ab, 0x0DDC, 0x0DDE)))
+ if ((ab == 0x0DDAu || hb_in_range (ab, 0x0DDCu, 0x0DDEu)))
{
/*
* Sinhala split matras... Let the fun begin.
@@ -1766,7 +1822,7 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c,
indic_plan->pstf.would_substitute (&glyph, 1, c->font->face)))
{
/* Ok, safe to use Uniscribe-style decomposition. */
- *a = 0x0DD9;
+ *a = 0x0DD9u;
*b = ab;
return true;
}
@@ -1786,7 +1842,7 @@ compose_indic (const hb_ot_shape_normalize_context_t *c,
return false;
/* Composition-exclusion exceptions that we want to recompose. */
- if (a == 0x09AF && b == 0x09BC) { *ab = 0x09DF; return true; }
+ if (a == 0x09AFu && b == 0x09BCu) { *ab = 0x09DFu; return true; }
return c->unicode->compose (a, b, ab);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh
index a9c8dbeaac..29fdf9a1ae 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh
@@ -62,7 +62,7 @@ static const short _myanmar_syllable_machine_index_offsets[] = {
static const char _myanmar_syllable_machine_indicies[] = {
1, 1, 2, 3, 4, 4, 0, 5,
- 0, 6, 0, 1, 0, 0, 0, 7,
+ 0, 6, 1, 0, 0, 0, 0, 7,
0, 8, 1, 0, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 0,
21, 22, 23, 23, 20, 24, 20, 25,
@@ -119,14 +119,14 @@ static const char _myanmar_syllable_machine_indicies[] = {
20, 20, 20, 20, 20, 20, 20, 20,
20, 31, 20, 33, 20, 35, 20, 21,
20, 23, 23, 20, 24, 20, 25, 20,
- 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 34, 20,
20, 27, 20, 29, 20, 31, 32, 33,
34, 35, 20, 21, 20, 23, 23, 20,
24, 20, 25, 20, 20, 20, 20, 20,
20, 20, 34, 20, 20, 27, 20, 20,
20, 31, 32, 33, 34, 35, 20, 21,
20, 23, 23, 20, 24, 20, 25, 20,
- 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 34, 20,
20, 27, 28, 29, 20, 31, 32, 33,
34, 35, 20, 21, 22, 23, 23, 20,
24, 20, 25, 20, 20, 20, 20, 20,
@@ -169,8 +169,8 @@ static const char _myanmar_syllable_machine_indicies[] = {
25, 20, 20, 20, 20, 20, 20, 20,
26, 20, 20, 27, 28, 29, 30, 31,
32, 33, 34, 35, 20, 1, 1, 2,
- 3, 3, 3, 42, 5, 42, 6, 42,
- 1, 42, 42, 42, 1, 42, 8, 1,
+ 3, 3, 3, 42, 5, 42, 6, 1,
+ 42, 42, 42, 42, 1, 42, 8, 1,
42, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 42, 2, 42, 3, 3,
42, 5, 42, 6, 42, 42, 42, 42,
@@ -191,14 +191,14 @@ static const char _myanmar_syllable_machine_indicies[] = {
42, 42, 42, 42, 42, 42, 42, 42,
42, 42, 13, 42, 15, 42, 17, 42,
2, 42, 3, 3, 42, 5, 42, 6,
- 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 16,
42, 42, 9, 42, 11, 42, 13, 14,
15, 16, 17, 42, 2, 42, 3, 3,
42, 5, 42, 6, 42, 42, 42, 42,
42, 42, 42, 16, 42, 42, 9, 42,
42, 42, 13, 14, 15, 16, 17, 42,
2, 42, 3, 3, 42, 5, 42, 6,
- 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 16,
42, 42, 9, 10, 11, 42, 13, 14,
15, 16, 17, 42, 2, 3, 3, 3,
42, 5, 42, 6, 42, 42, 42, 42,
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc
index 50209ffb0e..258ccc470c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc
@@ -134,7 +134,7 @@ enum myanmar_category_t {
OT_D = 19, /* Digits except zero */
OT_D0 = 20, /* Digit zero */
OT_DB = OT_N, /* Dot below */
- OT_GB = OT_DOTTEDCIRCLE,
+ OT_GB = OT_PLACEHOLDER,
OT_MH = 21, /* Various consonant medial types */
OT_MR = 22, /* Various consonant medial types */
OT_MW = 23, /* Various consonant medial types */
@@ -157,12 +157,6 @@ is_one_of (const hb_glyph_info_t &info, unsigned int flags)
return !!(FLAG (info.myanmar_category()) & flags);
}
-/* Note:
- *
- * We treat Vowels and placeholders as if they were consonants. This is safe because Vowels
- * cannot happen in a consonant syllable. The plus side however is, we can call the
- * consonant syllable logic from the vowel syllable function and get it all right! */
-#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CM) | FLAG (OT_Ra) | FLAG (OT_V) | FLAG (OT_NBSP) | FLAG (OT_GB))
static inline bool
is_consonant (const hb_glyph_info_t &info)
{
@@ -175,82 +169,80 @@ set_myanmar_properties (hb_glyph_info_t &info)
{
hb_codepoint_t u = info.codepoint;
unsigned int type = hb_indic_get_categories (u);
- indic_category_t cat = (indic_category_t) (type & 0x7F);
+ indic_category_t cat = (indic_category_t) (type & 0x7Fu);
indic_position_t pos = (indic_position_t) (type >> 8);
/* Myanmar
* http://www.microsoft.com/typography/OpenTypeDev/myanmar/intro.htm#analyze
*/
- if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xFE00, 0xFE0F)))
+ if (unlikely (hb_in_range (u, 0xFE00u, 0xFE0Fu)))
cat = (indic_category_t) OT_VS;
- else if (unlikely (u == 0x200C)) cat = (indic_category_t) OT_ZWNJ;
- else if (unlikely (u == 0x200D)) cat = (indic_category_t) OT_ZWJ;
switch (u)
{
- case 0x104E:
+ case 0x104Eu:
cat = (indic_category_t) OT_C; /* The spec says C, IndicSyllableCategory doesn't have. */
break;
- case 0x002D: case 0x00A0: case 0x00D7: case 0x2012:
- case 0x2013: case 0x2014: case 0x2015: case 0x2022:
- case 0x25CC: case 0x25FB: case 0x25FC: case 0x25FD:
- case 0x25FE:
+ case 0x002Du: case 0x00A0u: case 0x00D7u: case 0x2012u:
+ case 0x2013u: case 0x2014u: case 0x2015u: case 0x2022u:
+ case 0x25CCu: case 0x25FBu: case 0x25FCu: case 0x25FDu:
+ case 0x25FEu:
cat = (indic_category_t) OT_GB;
break;
- case 0x1004: case 0x101B: case 0x105A:
+ case 0x1004u: case 0x101Bu: case 0x105Au:
cat = (indic_category_t) OT_Ra;
break;
- case 0x1032: case 0x1036:
+ case 0x1032u: case 0x1036u:
cat = (indic_category_t) OT_A;
break;
- case 0x103A:
+ case 0x103Au:
cat = (indic_category_t) OT_As;
break;
- case 0x1041: case 0x1042: case 0x1043: case 0x1044:
- case 0x1045: case 0x1046: case 0x1047: case 0x1048:
- case 0x1049: case 0x1090: case 0x1091: case 0x1092:
- case 0x1093: case 0x1094: case 0x1095: case 0x1096:
- case 0x1097: case 0x1098: case 0x1099:
+ case 0x1041u: case 0x1042u: case 0x1043u: case 0x1044u:
+ case 0x1045u: case 0x1046u: case 0x1047u: case 0x1048u:
+ case 0x1049u: case 0x1090u: case 0x1091u: case 0x1092u:
+ case 0x1093u: case 0x1094u: case 0x1095u: case 0x1096u:
+ case 0x1097u: case 0x1098u: case 0x1099u:
cat = (indic_category_t) OT_D;
break;
- case 0x1040:
+ case 0x1040u:
cat = (indic_category_t) OT_D; /* XXX The spec says D0, but Uniscribe doesn't seem to do. */
break;
- case 0x103E: case 0x1060:
+ case 0x103Eu: case 0x1060u:
cat = (indic_category_t) OT_MH;
break;
- case 0x103C:
+ case 0x103Cu:
cat = (indic_category_t) OT_MR;
break;
- case 0x103D: case 0x1082:
+ case 0x103Du: case 0x1082u:
cat = (indic_category_t) OT_MW;
break;
- case 0x103B: case 0x105E: case 0x105F:
+ case 0x103Bu: case 0x105Eu: case 0x105Fu:
cat = (indic_category_t) OT_MY;
break;
- case 0x1063: case 0x1064: case 0x1069: case 0x106A:
- case 0x106B: case 0x106C: case 0x106D: case 0xAA7B:
+ case 0x1063u: case 0x1064u: case 0x1069u: case 0x106Au:
+ case 0x106Bu: case 0x106Cu: case 0x106Du: case 0xAA7Bu:
cat = (indic_category_t) OT_PT;
break;
- case 0x1038: case 0x1087: case 0x1088: case 0x1089:
- case 0x108A: case 0x108B: case 0x108C: case 0x108D:
- case 0x108F: case 0x109A: case 0x109B: case 0x109C:
+ case 0x1038u: case 0x1087u: case 0x1088u: case 0x1089u:
+ case 0x108Au: case 0x108Bu: case 0x108Cu: case 0x108Du:
+ case 0x108Fu: case 0x109Au: case 0x109Bu: case 0x109Cu:
cat = (indic_category_t) OT_SM;
break;
- case 0x104A: case 0x104B:
+ case 0x104Au: case 0x104Bu:
cat = (indic_category_t) OT_P;
break;
}
@@ -285,8 +277,9 @@ setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
* and setup masks later on in a pause-callback. */
unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
- set_myanmar_properties (buffer->info[i]);
+ set_myanmar_properties (info[i]);
}
static void
@@ -459,8 +452,10 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
/* Note: This loop is extra overhead, but should not be measurable. */
bool has_broken_syllables = false;
unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
- if ((buffer->info[i].syllable() & 0x0F) == broken_cluster) {
+ if ((info[i].syllable() & 0x0F) == broken_cluster)
+ {
has_broken_syllables = true;
break;
}
@@ -469,11 +464,11 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_codepoint_t dottedcircle_glyph;
- if (!font->get_glyph (0x25CC, 0, &dottedcircle_glyph))
+ if (!font->get_glyph (0x25CCu, 0, &dottedcircle_glyph))
return;
hb_glyph_info_t dottedcircle = {0};
- dottedcircle.codepoint = 0x25CC;
+ dottedcircle.codepoint = 0x25CCu;
set_myanmar_properties (dottedcircle);
dottedcircle.codepoint = dottedcircle_glyph;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-private.hh
index 104726e8af..3e581afa9c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-private.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-private.hh
@@ -173,6 +173,10 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
/* Unicode-6.0 additions */
case HB_SCRIPT_MANDAIC:
+ /* Unicode-7.0 additions */
+ case HB_SCRIPT_MANICHAEAN:
+ case HB_SCRIPT_PSALTER_PAHLAVI:
+
/* For Arabic script, use the Arabic shaper even if no OT script tag was found.
* This is because we do fallback shaping for Arabic script (and not others). */
if (planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT ||
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-sea.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-sea.cc
index 6288a90c9a..f08b7ccb9f 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-sea.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-sea.cc
@@ -139,11 +139,11 @@ set_sea_properties (hb_glyph_info_t &info)
{
hb_codepoint_t u = info.codepoint;
unsigned int type = hb_indic_get_categories (u);
- indic_category_t cat = (indic_category_t) (type & 0x7F);
+ indic_category_t cat = (indic_category_t) (type & 0x7Fu);
indic_position_t pos = (indic_position_t) (type >> 8);
/* Medial Ra */
- if (u == 0x1A55 || u == 0xAA34)
+ if (u == 0x1A55u || u == 0xAA34u)
cat = (indic_category_t) OT_MR;
if (cat == OT_M)
@@ -174,8 +174,9 @@ setup_masks_sea (const hb_ot_shape_plan_t *plan HB_UNUSED,
* and setup masks later on in a pause-callback. */
unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
- set_sea_properties (buffer->info[i]);
+ set_sea_properties (info[i]);
}
static void
@@ -278,8 +279,10 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
/* Note: This loop is extra overhead, but should not be measurable. */
bool has_broken_syllables = false;
unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
- if ((buffer->info[i].syllable() & 0x0F) == broken_cluster) {
+ if ((info[i].syllable() & 0x0F) == broken_cluster)
+ {
has_broken_syllables = true;
break;
}
@@ -288,11 +291,11 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_codepoint_t dottedcircle_glyph;
- if (!font->get_glyph (0x25CC, 0, &dottedcircle_glyph))
+ if (!font->get_glyph (0x25CCu, 0, &dottedcircle_glyph))
return;
hb_glyph_info_t dottedcircle = {0};
- dottedcircle.codepoint = 0x25CC;
+ dottedcircle.codepoint = 0x25CCu;
set_sea_properties (dottedcircle);
dottedcircle.codepoint = dottedcircle_glyph;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc
index 8664eca45c..feb7fc7a14 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc
@@ -46,13 +46,13 @@ enum thai_consonant_type_t
static thai_consonant_type_t
get_consonant_type (hb_codepoint_t u)
{
- if (u == 0x0E1B || u == 0x0E1D || u == 0x0E1F/* || u == 0x0E2C*/)
+ if (u == 0x0E1Bu || u == 0x0E1Du || u == 0x0E1Fu/* || u == 0x0E2Cu*/)
return AC;
- if (u == 0x0E0D || u == 0x0E10)
+ if (u == 0x0E0Du || u == 0x0E10u)
return RC;
- if (u == 0x0E0E || u == 0x0E0F)
+ if (u == 0x0E0Eu || u == 0x0E0Fu)
return DC;
- if (hb_in_range<hb_codepoint_t> (u, 0x0E01, 0x0E2E))
+ if (hb_in_range (u, 0x0E01u, 0x0E2Eu))
return NC;
return NOT_CONSONANT;
}
@@ -70,12 +70,12 @@ enum thai_mark_type_t
static thai_mark_type_t
get_mark_type (hb_codepoint_t u)
{
- if (u == 0x0E31 || hb_in_range<hb_codepoint_t> (u, 0x0E34, 0x0E37) ||
- u == 0x0E47 || hb_in_range<hb_codepoint_t> (u, 0x0E4D, 0x0E4E))
+ if (u == 0x0E31u || hb_in_range (u, 0x0E34u, 0x0E37u) ||
+ u == 0x0E47u || hb_in_range (u, 0x0E4Du, 0x0E4Eu))
return AV;
- if (hb_in_range<hb_codepoint_t> (u, 0x0E38, 0x0E3A))
+ if (hb_in_range (u, 0x0E38u, 0x0E3Au))
return BV;
- if (hb_in_range<hb_codepoint_t> (u, 0x0E48, 0x0E4C))
+ if (hb_in_range (u, 0x0E48u, 0x0E4Cu))
return T;
return NOT_MARK;
}
@@ -99,43 +99,43 @@ thai_pua_shape (hb_codepoint_t u, thai_action_t action, hb_font_t *font)
hb_codepoint_t mac_pua;
} const *pua_mappings = NULL;
static const thai_pua_mapping_t SD_mappings[] = {
- {0x0E48, 0xF70A, 0xF88B}, /* MAI EK */
- {0x0E49, 0xF70B, 0xF88E}, /* MAI THO */
- {0x0E4A, 0xF70C, 0xF891}, /* MAI TRI */
- {0x0E4B, 0xF70D, 0xF894}, /* MAI CHATTAWA */
- {0x0E4C, 0xF70E, 0xF897}, /* THANTHAKHAT */
- {0x0E38, 0xF718, 0xF89B}, /* SARA U */
- {0x0E39, 0xF719, 0xF89C}, /* SARA UU */
- {0x0E3A, 0xF71A, 0xF89D}, /* PHINTHU */
- {0x0000, 0x0000, 0x0000}
+ {0x0E48u, 0xF70Au, 0xF88Bu}, /* MAI EK */
+ {0x0E49u, 0xF70Bu, 0xF88Eu}, /* MAI THO */
+ {0x0E4Au, 0xF70Cu, 0xF891u}, /* MAI TRI */
+ {0x0E4Bu, 0xF70Du, 0xF894u}, /* MAI CHATTAWA */
+ {0x0E4Cu, 0xF70Eu, 0xF897u}, /* THANTHAKHAT */
+ {0x0E38u, 0xF718u, 0xF89Bu}, /* SARA U */
+ {0x0E39u, 0xF719u, 0xF89Cu}, /* SARA UU */
+ {0x0E3Au, 0xF71Au, 0xF89Du}, /* PHINTHU */
+ {0x0000u, 0x0000u, 0x0000u}
};
static const thai_pua_mapping_t SDL_mappings[] = {
- {0x0E48, 0xF705, 0xF88C}, /* MAI EK */
- {0x0E49, 0xF706, 0xF88F}, /* MAI THO */
- {0x0E4A, 0xF707, 0xF892}, /* MAI TRI */
- {0x0E4B, 0xF708, 0xF895}, /* MAI CHATTAWA */
- {0x0E4C, 0xF709, 0xF898}, /* THANTHAKHAT */
- {0x0000, 0x0000, 0x0000}
+ {0x0E48u, 0xF705u, 0xF88Cu}, /* MAI EK */
+ {0x0E49u, 0xF706u, 0xF88Fu}, /* MAI THO */
+ {0x0E4Au, 0xF707u, 0xF892u}, /* MAI TRI */
+ {0x0E4Bu, 0xF708u, 0xF895u}, /* MAI CHATTAWA */
+ {0x0E4Cu, 0xF709u, 0xF898u}, /* THANTHAKHAT */
+ {0x0000u, 0x0000u, 0x0000u}
};
static const thai_pua_mapping_t SL_mappings[] = {
- {0x0E48, 0xF713, 0xF88A}, /* MAI EK */
- {0x0E49, 0xF714, 0xF88D}, /* MAI THO */
- {0x0E4A, 0xF715, 0xF890}, /* MAI TRI */
- {0x0E4B, 0xF716, 0xF893}, /* MAI CHATTAWA */
- {0x0E4C, 0xF717, 0xF896}, /* THANTHAKHAT */
- {0x0E31, 0xF710, 0xF884}, /* MAI HAN-AKAT */
- {0x0E34, 0xF701, 0xF885}, /* SARA I */
- {0x0E35, 0xF702, 0xF886}, /* SARA II */
- {0x0E36, 0xF703, 0xF887}, /* SARA UE */
- {0x0E37, 0xF704, 0xF888}, /* SARA UEE */
- {0x0E47, 0xF712, 0xF889}, /* MAITAIKHU */
- {0x0E4D, 0xF711, 0xF899}, /* NIKHAHIT */
- {0x0000, 0x0000, 0x0000}
+ {0x0E48u, 0xF713u, 0xF88Au}, /* MAI EK */
+ {0x0E49u, 0xF714u, 0xF88Du}, /* MAI THO */
+ {0x0E4Au, 0xF715u, 0xF890u}, /* MAI TRI */
+ {0x0E4Bu, 0xF716u, 0xF893u}, /* MAI CHATTAWA */
+ {0x0E4Cu, 0xF717u, 0xF896u}, /* THANTHAKHAT */
+ {0x0E31u, 0xF710u, 0xF884u}, /* MAI HAN-AKAT */
+ {0x0E34u, 0xF701u, 0xF885u}, /* SARA I */
+ {0x0E35u, 0xF702u, 0xF886u}, /* SARA II */
+ {0x0E36u, 0xF703u, 0xF887u}, /* SARA UE */
+ {0x0E37u, 0xF704u, 0xF888u}, /* SARA UEE */
+ {0x0E47u, 0xF712u, 0xF889u}, /* MAITAIKHU */
+ {0x0E4Du, 0xF711u, 0xF899u}, /* NIKHAHIT */
+ {0x0000u, 0x0000u, 0x0000u}
};
static const thai_pua_mapping_t RD_mappings[] = {
- {0x0E0D, 0xF70F, 0xF89A}, /* YO YING */
- {0x0E10, 0xF700, 0xF89E}, /* THO THAN */
- {0x0000, 0x0000, 0x0000}
+ {0x0E0Du, 0xF70Fu, 0xF89Au}, /* YO YING */
+ {0x0E10u, 0xF700u, 0xF89Eu}, /* THO THAN */
+ {0x0000u, 0x0000u, 0x0000u}
};
switch (action) {
@@ -308,10 +308,10 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
/* We only get one script at a time, so a script-agnostic implementation
* is adequate here. */
-#define IS_SARA_AM(x) (((x) & ~0x0080) == 0x0E33)
-#define NIKHAHIT_FROM_SARA_AM(x) ((x) - 0xE33 + 0xE4D)
+#define IS_SARA_AM(x) (((x) & ~0x0080u) == 0x0E33u)
+#define NIKHAHIT_FROM_SARA_AM(x) ((x) - 0x0E33u + 0x0E4Du)
#define SARA_AA_FROM_SARA_AM(x) ((x) - 1)
-#define IS_TONE_MARK(x) (hb_in_ranges<hb_codepoint_t> ((x) & ~0x0080, 0x0E34, 0x0E37, 0x0E47, 0x0E4E, 0x0E31, 0x0E31))
+#define IS_TONE_MARK(x) (hb_in_ranges ((x) & ~0x0080u, 0x0E34u, 0x0E37u, 0x0E47u, 0x0E4Eu, 0x0E31u, 0x0E31u))
buffer->clear_output ();
unsigned int count = buffer->len;
@@ -330,8 +330,11 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
if (unlikely (buffer->in_error))
return;
- /* Ok, let's see... */
+ /* Make Nikhahit be recognized as a mark when zeroing widths. */
unsigned int end = buffer->out_len;
+ _hb_glyph_info_set_general_category (&buffer->out_info[end - 2], HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK);
+
+ /* Ok, let's see... */
unsigned int start = end - 2;
while (start > 0 && IS_TONE_MARK (buffer->out_info[start - 1].codepoint))
start--;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-fallback.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-fallback.cc
index 5d526c3a8e..a774f95185 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-fallback.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-fallback.cc
@@ -35,42 +35,42 @@ recategorize_combining_class (hb_codepoint_t u,
return klass;
/* Thai / Lao need some per-character work. */
- if ((u & ~0xFF) == 0x0E00)
+ if ((u & ~0xFF) == 0x0E00u)
{
if (unlikely (klass == 0))
{
switch (u)
{
- case 0x0E31:
- case 0x0E34:
- case 0x0E35:
- case 0x0E36:
- case 0x0E37:
- case 0x0E47:
- case 0x0E4C:
- case 0x0E4D:
- case 0x0E4E:
+ case 0x0E31u:
+ case 0x0E34u:
+ case 0x0E35u:
+ case 0x0E36u:
+ case 0x0E37u:
+ case 0x0E47u:
+ case 0x0E4Cu:
+ case 0x0E4Du:
+ case 0x0E4Eu:
klass = HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;
break;
- case 0x0EB1:
- case 0x0EB4:
- case 0x0EB5:
- case 0x0EB6:
- case 0x0EB7:
- case 0x0EBB:
- case 0x0ECC:
- case 0x0ECD:
+ case 0x0EB1u:
+ case 0x0EB4u:
+ case 0x0EB5u:
+ case 0x0EB6u:
+ case 0x0EB7u:
+ case 0x0EBBu:
+ case 0x0ECCu:
+ case 0x0ECDu:
klass = HB_UNICODE_COMBINING_CLASS_ABOVE;
break;
- case 0x0EBC:
+ case 0x0EBCu:
klass = HB_UNICODE_COMBINING_CLASS_BELOW;
break;
}
} else {
/* Thai virama is below-right */
- if (u == 0x0E3A)
+ if (u == 0x0E3Au)
klass = HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT;
}
}
@@ -167,11 +167,12 @@ _hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_shape_plan_t *pla
hb_buffer_t *buffer)
{
unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
- if (_hb_glyph_info_get_general_category (&buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) {
- unsigned int combining_class = _hb_glyph_info_get_modified_combining_class (&buffer->info[i]);
- combining_class = recategorize_combining_class (buffer->info[i].codepoint, combining_class);
- _hb_glyph_info_set_modified_combining_class (&buffer->info[i], combining_class);
+ if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) {
+ unsigned int combining_class = _hb_glyph_info_get_modified_combining_class (&info[i]);
+ combining_class = recategorize_combining_class (info[i].codepoint, combining_class);
+ _hb_glyph_info_set_modified_combining_class (&info[i], combining_class);
}
}
@@ -181,8 +182,9 @@ zero_mark_advances (hb_buffer_t *buffer,
unsigned int start,
unsigned int end)
{
+ hb_glyph_info_t *info = buffer->info;
for (unsigned int i = start; i < end; i++)
- if (_hb_glyph_info_get_general_category (&buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
+ if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
{
buffer->pos[i].x_advance = 0;
buffer->pos[i].y_advance = 0;
@@ -327,12 +329,13 @@ position_around_base (const hb_ot_shape_plan_t *plan,
unsigned int last_lig_component = (unsigned int) -1;
unsigned int last_combining_class = 255;
hb_glyph_extents_t cluster_extents = base_extents; /* Initialization is just to shut gcc up. */
+ hb_glyph_info_t *info = buffer->info;
for (unsigned int i = base + 1; i < end; i++)
- if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]))
+ if (_hb_glyph_info_get_modified_combining_class (&info[i]))
{
if (num_lig_components > 1) {
- unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[i]);
- unsigned int this_lig_component = _hb_glyph_info_get_lig_comp (&buffer->info[i]) - 1;
+ unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&info[i]);
+ unsigned int this_lig_component = _hb_glyph_info_get_lig_comp (&info[i]) - 1;
/* Conditions for attaching to the last component. */
if (!lig_id || lig_id != this_lig_id || this_lig_component >= num_lig_components)
this_lig_component = num_lig_components - 1;
@@ -355,7 +358,7 @@ position_around_base (const hb_ot_shape_plan_t *plan,
}
}
- unsigned int this_combining_class = _hb_glyph_info_get_modified_combining_class (&buffer->info[i]);
+ unsigned int this_combining_class = _hb_glyph_info_get_modified_combining_class (&info[i]);
if (last_combining_class != this_combining_class)
{
last_combining_class = this_combining_class;
@@ -391,13 +394,14 @@ position_cluster (const hb_ot_shape_plan_t *plan,
return;
/* Find the base glyph */
+ hb_glyph_info_t *info = buffer->info;
for (unsigned int i = start; i < end; i++)
- if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[i])))
+ if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))
{
/* Find mark glyphs */
unsigned int j;
for (j = i + 1; j < end; j++)
- if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[j])))
+ if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[j])))
break;
position_around_base (plan, font, buffer, i, j);
@@ -432,15 +436,13 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
{
if (!plan->has_kern) return;
- unsigned int count = buffer->len;
-
OT::hb_apply_context_t c (1, font, buffer);
c.set_lookup_mask (plan->kern_mask);
c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
+ unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
hb_glyph_position_t *pos = buffer->pos;
-
for (unsigned int idx = 0; idx < count;)
{
OT::hb_apply_context_t::skipping_forward_iterator_t skippy_iter (&c, idx, 1);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-private.hh
index df81fa25d9..54ac2c3cf7 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-private.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-private.hh
@@ -44,6 +44,7 @@ struct hb_ot_shape_plan_t
hb_mask_t kern_mask;
unsigned int has_frac : 1;
unsigned int has_kern : 1;
+ unsigned int has_mark : 1;
inline void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const
{
@@ -92,6 +93,7 @@ struct hb_ot_shape_planner_t
plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask);
plan.has_kern = !!plan.kern_mask;
+ plan.has_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k'));
}
private:
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
index 3080a1d03d..1f99014c62 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
@@ -37,6 +37,7 @@
#include "hb-ot-shape-normalize-private.hh"
#include "hb-ot-layout-private.hh"
+#include "hb-unicode-private.hh"
#include "hb-set-private.hh"
@@ -226,8 +227,9 @@ static void
hb_set_unicode_props (hb_buffer_t *buffer)
{
unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
- _hb_glyph_info_set_unicode_props (&buffer->info[i], buffer->unicode);
+ _hb_glyph_info_set_unicode_props (&info[i], buffer->unicode);
}
static void
@@ -238,11 +240,11 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
return;
- if (!font->has_glyph (0x25CC))
+ if (!font->has_glyph (0x25CCu))
return;
hb_glyph_info_t dottedcircle;
- dottedcircle.codepoint = 0x25CC;
+ dottedcircle.codepoint = 0x25CCu;
_hb_glyph_info_set_unicode_props (&dottedcircle, buffer->unicode);
buffer->clear_output ();
@@ -262,8 +264,9 @@ static void
hb_form_clusters (hb_buffer_t *buffer)
{
unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 1; i < count; i++)
- if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[i])))
+ if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))
buffer->merge_clusters (i - 1, i + 1);
}
@@ -321,7 +324,7 @@ hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c)
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
{
- if (info[i].codepoint == 0x2044) /* FRACTION SLASH */
+ if (info[i].codepoint == 0x2044u) /* FRACTION SLASH */
{
unsigned int start = i, end = i + 1;
while (start &&
@@ -381,8 +384,9 @@ hb_ot_map_glyphs_fast (hb_buffer_t *buffer)
{
/* Normalization process sets up glyph_index(), we just copy it. */
unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
- buffer->info[i].codepoint = buffer->info[i].glyph_index();
+ info[i].codepoint = info[i].glyph_index();
}
static inline void
@@ -391,11 +395,24 @@ hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
unsigned int count = c->buffer->len;
hb_glyph_info_t *info = c->buffer->info;
for (unsigned int i = 0; i < count; i++)
- _hb_glyph_info_set_glyph_props (&info[i],
- _hb_glyph_info_get_general_category (&info[i])
- == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ?
- HB_OT_LAYOUT_GLYPH_PROPS_MARK :
- HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH);
+ {
+ hb_ot_layout_glyph_class_mask_t klass;
+
+ /* Never mark default-ignorables as marks.
+ * They won't get in the way of lookups anyway,
+ * but having them as mark will cause them to be skipped
+ * over if the lookup-flag says so, but at least for the
+ * Mongolian variation selectors, looks like Uniscribe
+ * marks them as non-mark. Some Mongolian fonts without
+ * GDEF rely on this. Another notable character that
+ * this applies to is COMBINING GRAPHEME JOINER. */
+ klass = (_hb_glyph_info_get_general_category (&info[i]) !=
+ HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ||
+ _hb_glyph_info_is_default_ignorable (&info[i])) ?
+ HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH :
+ HB_OT_LAYOUT_GLYPH_PROPS_MARK;
+ _hb_glyph_info_set_glyph_props (&info[i], klass);
+ }
}
static inline void
@@ -452,26 +469,44 @@ hb_ot_substitute (hb_ot_shape_context_t *c)
/* Position */
static inline void
-zero_mark_widths_by_unicode (hb_buffer_t *buffer)
+adjust_mark_offsets (hb_glyph_position_t *pos)
+{
+ pos->x_offset -= pos->x_advance;
+ pos->y_offset -= pos->y_advance;
+}
+
+static inline void
+zero_mark_width (hb_glyph_position_t *pos)
+{
+ pos->x_advance = 0;
+ pos->y_advance = 0;
+}
+
+static inline void
+zero_mark_widths_by_unicode (hb_buffer_t *buffer, bool adjust_offsets)
{
unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
- if (_hb_glyph_info_get_general_category (&buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
+ if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
{
- buffer->pos[i].x_advance = 0;
- buffer->pos[i].y_advance = 0;
+ if (adjust_offsets)
+ adjust_mark_offsets (&buffer->pos[i]);
+ zero_mark_width (&buffer->pos[i]);
}
}
static inline void
-zero_mark_widths_by_gdef (hb_buffer_t *buffer)
+zero_mark_widths_by_gdef (hb_buffer_t *buffer, bool adjust_offsets)
{
unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
- if (_hb_glyph_info_is_mark (&buffer->info[i]))
+ if (_hb_glyph_info_is_mark (&info[i]))
{
- buffer->pos[i].x_advance = 0;
- buffer->pos[i].y_advance = 0;
+ if (adjust_offsets)
+ adjust_mark_offsets (&buffer->pos[i]);
+ zero_mark_width (&buffer->pos[i]);
}
}
@@ -501,16 +536,28 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
{
bool ret = false;
unsigned int count = c->buffer->len;
+ bool has_positioning = hb_ot_layout_has_positioning (c->face);
+ /* If the font has no GPOS, AND, no fallback positioning will
+ * happen, AND, direction is forward, then when zeroing mark
+ * widths, we shift the mark with it, such that the mark
+ * is positioned hanging over the previous glyph. When
+ * direction is backward we don't shift and it will end up
+ * hanging over the next glyph after the final reordering.
+ * If fallback positinoing happens or GPOS is present, we don't
+ * care.
+ */
+ bool adjust_offsets_when_zeroing = !(has_positioning || c->plan->shaper->fallback_position ||
+ HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction));
switch (c->plan->shaper->zero_width_marks)
{
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
- zero_mark_widths_by_gdef (c->buffer);
+ zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
break;
/* Not currently used for any shaper:
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY:
- zero_mark_widths_by_unicode (c->buffer);
+ zero_mark_widths_by_unicode (c->buffer, adjust_offsets_when_zeroing);
break;
*/
@@ -521,7 +568,7 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
break;
}
- if (hb_ot_layout_has_positioning (c->face))
+ if (has_positioning)
{
hb_glyph_info_t *info = c->buffer->info;
hb_glyph_position_t *pos = c->buffer->pos;
@@ -550,11 +597,11 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
switch (c->plan->shaper->zero_width_marks)
{
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE:
- zero_mark_widths_by_unicode (c->buffer);
+ zero_mark_widths_by_unicode (c->buffer, adjust_offsets_when_zeroing);
break;
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
- zero_mark_widths_by_gdef (c->buffer);
+ zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
break;
default:
@@ -731,8 +778,9 @@ hb_ot_shape_glyphs_closure (hb_font_t *font,
bool mirror = hb_script_get_horizontal_direction (buffer->props.script) == HB_DIRECTION_RTL;
unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
- add_char (font, buffer->unicode, mirror, buffer->info[i].codepoint, glyphs);
+ add_char (font, buffer->unicode, mirror, info[i].codepoint, glyphs);
hb_set_t lookups;
lookups.init ();
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.h b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.h
index afe6fe9618..1402f54acc 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.h
@@ -24,31 +24,30 @@
* Red Hat Author(s): Behdad Esfahbod
*/
+#ifndef HB_OT_H_IN
+#error "Include <hb-ot.h> instead."
+#endif
+
#ifndef HB_OT_SHAPE_H
#define HB_OT_SHAPE_H
-#define HB_OT_SHAPE_H_IN
#include "hb.h"
-#include "hb-ot-layout.h"
-#include "hb-ot-tag.h"
-
HB_BEGIN_DECLS
/* TODO port to shape-plan / set. */
void
hb_ot_shape_glyphs_closure (hb_font_t *font,
- hb_buffer_t *buffer,
- const hb_feature_t *features,
- unsigned int num_features,
- hb_set_t *glyphs);
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ hb_set_t *glyphs);
void
hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan,
- hb_tag_t table_tag,
- hb_set_t *lookup_indexes /* OUT */);
+ hb_tag_t table_tag,
+ hb_set_t *lookup_indexes /* OUT */);
HB_END_DECLS
-#undef HB_OT_SHAPE_H_IN
#endif /* HB_OT_SHAPE_H */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc
index 5594ef5074..878dd79b62 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc
@@ -57,7 +57,7 @@ hb_ot_old_tag_from_script (hb_script_t script)
}
/* Else, just change first char to lowercase and return */
- return ((hb_tag_t) script) | 0x20000000;
+ return ((hb_tag_t) script) | 0x20000000u;
}
static hb_script_t
@@ -70,13 +70,13 @@ hb_ot_old_tag_to_script (hb_tag_t tag)
/* Any spaces at the end of the tag are replaced by repeating the last
* letter. Eg 'nko ' -> 'Nkoo' */
- if (unlikely ((tag & 0x0000FF00) == 0x00002000))
- tag |= (tag >> 8) & 0x0000FF00; /* Copy second letter to third */
- if (unlikely ((tag & 0x000000FF) == 0x00000020))
- tag |= (tag >> 8) & 0x000000FF; /* Copy third letter to fourth */
+ if (unlikely ((tag & 0x0000FF00u) == 0x00002000u))
+ tag |= (tag >> 8) & 0x0000FF00u; /* Copy second letter to third */
+ if (unlikely ((tag & 0x000000FFu) == 0x00000020u))
+ tag |= (tag >> 8) & 0x000000FFu; /* Copy third letter to fourth */
/* Change first char to uppercase and return */
- return (hb_script_t) (tag & ~0x20000000);
+ return (hb_script_t) (tag & ~0x20000000u);
}
static hb_tag_t
@@ -146,7 +146,7 @@ hb_ot_tags_from_script (hb_script_t script,
hb_script_t
hb_ot_tag_to_script (hb_tag_t tag)
{
- if (unlikely ((tag & 0x000000FF) == '2'))
+ if (unlikely ((tag & 0x000000FFu) == '2'))
return hb_ot_new_tag_to_script (tag);
return hb_ot_old_tag_to_script (tag);
@@ -156,7 +156,7 @@ hb_ot_tag_to_script (hb_tag_t tag)
/* hb_language_t */
typedef struct {
- char language[6];
+ char language[4];
hb_tag_t tag;
} LangTag;
@@ -763,12 +763,18 @@ static const LangTag ot_languages[] = {
/*{"??", HB_TAG('Z','H','P',' ')},*/ /* Chinese Phonetic */
};
-static const LangTag ot_languages_zh[] = {
+typedef struct {
+ char language[8];
+ hb_tag_t tag;
+} LangTagLong;
+static const LangTagLong ot_languages_zh[] = {
{"zh-cn", HB_TAG('Z','H','S',' ')}, /* Chinese (China) */
{"zh-hk", HB_TAG('Z','H','H',' ')}, /* Chinese (Hong Kong) */
{"zh-mo", HB_TAG('Z','H','T',' ')}, /* Chinese (Macao) */
{"zh-sg", HB_TAG('Z','H','S',' ')}, /* Chinese (Singapore) */
- {"zh-tw", HB_TAG('Z','H','T',' ')} /* Chinese (Taiwan) */
+ {"zh-tw", HB_TAG('Z','H','T',' ')}, /* Chinese (Taiwan) */
+ {"zh-hans", HB_TAG('Z','H','S',' ')}, /* Chinese (Simplified) */
+ {"zh-hant", HB_TAG('Z','H','T',' ')}, /* Chinese (Traditional) */
};
static int
@@ -800,7 +806,6 @@ hb_tag_t
hb_ot_tag_from_language (hb_language_t language)
{
const char *lang_str, *s;
- const LangTag *lang_tag;
if (language == HB_LANGUAGE_INVALID)
return HB_OT_TAG_DEFAULT_LANGUAGE;
@@ -822,11 +827,14 @@ hb_ot_tag_from_language (hb_language_t language)
}
/* Find a language matching in the first component */
- lang_tag = (LangTag *) bsearch (lang_str, ot_languages,
- ARRAY_LENGTH (ot_languages), sizeof (LangTag),
- (hb_compare_func_t) lang_compare_first_component);
- if (lang_tag)
- return lang_tag->tag;
+ {
+ const LangTag *lang_tag;
+ lang_tag = (LangTag *) bsearch (lang_str, ot_languages,
+ ARRAY_LENGTH (ot_languages), sizeof (LangTag),
+ (hb_compare_func_t) lang_compare_first_component);
+ if (lang_tag)
+ return lang_tag->tag;
+ }
/* Otherwise, check the Chinese ones */
if (0 == lang_compare_first_component (lang_str, "zh"))
@@ -835,8 +843,9 @@ hb_ot_tag_from_language (hb_language_t language)
for (i = 0; i < ARRAY_LENGTH (ot_languages_zh); i++)
{
+ const LangTagLong *lang_tag;
lang_tag = &ot_languages_zh[i];
- if (lang_matches (lang_tag->language, lang_str))
+ if (lang_matches (lang_str, lang_tag->language))
return lang_tag->tag;
}
@@ -849,7 +858,7 @@ hb_ot_tag_from_language (hb_language_t language)
s = lang_str + strlen (lang_str);
if (s - lang_str == 3) {
/* Assume it's ISO-639-3 and upper-case and use it. */
- return hb_tag_from_string (lang_str, s - lang_str) & ~0x20202000;
+ return hb_tag_from_string (lang_str, s - lang_str) & ~0x20202000u;
}
return HB_OT_TAG_DEFAULT_LANGUAGE;
@@ -868,21 +877,12 @@ hb_ot_tag_to_language (hb_tag_t tag)
return hb_language_from_string (ot_languages[i].language, -1);
/* If tag starts with ZH, it's Chinese */
- if ((tag & 0xFFFF0000) == 0x5A480000) {
+ if ((tag & 0xFFFF0000u) == 0x5A480000u) {
switch (tag) {
case HB_TAG('Z','H','H',' '): return hb_language_from_string ("zh-hk", -1); /* Hong Kong */
- default: {
- /* Encode the tag... */
- unsigned char buf[14] = "zh-x-hbot";
- buf[9] = tag >> 24;
- buf[10] = (tag >> 16) & 0xFF;
- buf[11] = (tag >> 8) & 0xFF;
- buf[12] = tag & 0xFF;
- if (buf[12] == 0x20)
- buf[12] = '\0';
- buf[13] = '\0';
- return hb_language_from_string ((char *) buf, -1);
- }
+ case HB_TAG('Z','H','S',' '): return hb_language_from_string ("zh-Hans", -1); /* Simplified */
+ case HB_TAG('Z','H','T',' '): return hb_language_from_string ("zh-Hant", -1); /* Traditional */
+ default: break; /* Fall through */
}
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot.h b/src/3rdparty/harfbuzz-ng/src/hb-ot.h
index e9a280b7dd..47c92a58e4 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot.h
@@ -30,6 +30,7 @@
#include "hb.h"
+#include "hb-ot-font.h"
#include "hb-ot-layout.h"
#include "hb-ot-tag.h"
#include "hb-ot-shape.h"
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-private.hh
index 680b21e2cc..a451d164f9 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-private.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-private.hh
@@ -54,23 +54,77 @@
#include <stdarg.h>
+/* Compiler attributes */
-/* Essentials */
-#ifndef NULL
-# define NULL ((void *) 0)
+#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
+#define _HB_BOOLEAN_EXPR(expr) ((expr) ? 1 : 0)
+#define likely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 1))
+#define unlikely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 0))
+#else
+#define likely(expr) (expr)
+#define unlikely(expr) (expr)
#endif
+#ifndef __GNUC__
+#undef __attribute__
+#define __attribute__(x)
+#endif
+
+#if __GNUC__ >= 3
+#define HB_PURE_FUNC __attribute__((pure))
+#define HB_CONST_FUNC __attribute__((const))
+#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
+#else
+#define HB_PURE_FUNC
+#define HB_CONST_FUNC
+#define HB_PRINTF_FUNC(format_idx, arg_idx)
+#endif
+#if __GNUC__ >= 4
+#define HB_UNUSED __attribute__((unused))
+#else
+#define HB_UNUSED
+#endif
+
+#ifndef HB_INTERNAL
+# ifndef __MINGW32__
+# define HB_INTERNAL __attribute__((__visibility__("hidden")))
+# else
+# define HB_INTERNAL
+# endif
+#endif
+
+#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
+#define snprintf _snprintf
+#endif
+
+#ifdef _MSC_VER
+#undef inline
+#define inline __inline
+#endif
+
+#ifdef __STRICT_ANSI__
+#undef inline
+#define inline __inline__
+#endif
+
+#if __GNUC__ >= 3
+#define HB_FUNC __PRETTY_FUNCTION__
+#elif defined(_MSC_VER)
+#define HB_FUNC __FUNCSIG__
+#else
+#define HB_FUNC __func__
+#endif
-/* Void! */
-struct _hb_void_t {};
-typedef const _hb_void_t &hb_void_t;
-#define HB_VOID (* (const _hb_void_t *) NULL)
/* Basics */
+#ifndef NULL
+# define NULL ((void *) 0)
+#endif
+
#undef MIN
template <typename Type>
static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
@@ -92,7 +146,7 @@ static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
#define HB_STMT_START do
#define HB_STMT_END while (0)
-#define _ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1]
+#define _ASSERT_STATIC1(_line, _cond) HB_UNUSED typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1]
#define _ASSERT_STATIC0(_line, _cond) _ASSERT_STATIC1 (_line, (_cond))
#define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond))
@@ -139,7 +193,7 @@ ASSERT_STATIC (sizeof (hb_var_int_t) == 4);
/* Check _assertion in a method environment */
#define _ASSERT_POD1(_line) \
- inline void _static_assertion_on_line_##_line (void) const \
+ HB_UNUSED inline void _static_assertion_on_line_##_line (void) const \
{ _ASSERT_INSTANCE_POD1 (_line, *this); /* Make sure it's POD. */ }
# define _ASSERT_POD0(_line) _ASSERT_POD1 (_line)
# define ASSERT_POD() _ASSERT_POD0 (__LINE__)
@@ -148,68 +202,10 @@ ASSERT_STATIC (sizeof (hb_var_int_t) == 4);
/* Misc */
-
-#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
-#define _HB_BOOLEAN_EXPR(expr) ((expr) ? 1 : 0)
-#define likely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 1))
-#define unlikely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 0))
-#else
-#define likely(expr) (expr)
-#define unlikely(expr) (expr)
-#endif
-
-#ifndef __GNUC__
-#undef __attribute__
-#define __attribute__(x)
-#endif
-
-#if __GNUC__ >= 3
-#define HB_PURE_FUNC __attribute__((pure))
-#define HB_CONST_FUNC __attribute__((const))
-#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
-#else
-#define HB_PURE_FUNC
-#define HB_CONST_FUNC
-#define HB_PRINTF_FUNC(format_idx, arg_idx)
-#endif
-#if __GNUC__ >= 4
-#define HB_UNUSED __attribute__((unused))
-#else
-#define HB_UNUSED
-#endif
-
-#ifndef HB_INTERNAL
-# ifndef __MINGW32__
-# define HB_INTERNAL __attribute__((__visibility__("hidden")))
-# else
-# define HB_INTERNAL
-# endif
-#endif
-
-
-#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
-#define snprintf _snprintf
-#endif
-
-#ifdef _MSC_VER
-#undef inline
-#define inline __inline
-#endif
-
-#ifdef __STRICT_ANSI__
-#undef inline
-#define inline __inline__
-#endif
-
-
-#if __GNUC__ >= 3
-#define HB_FUNC __PRETTY_FUNCTION__
-#elif defined(_MSC_VER)
-#define HB_FUNC __FUNCSIG__
-#else
-#define HB_FUNC __func__
-#endif
-
+/* Void! */
+struct _hb_void_t {};
+typedef const _hb_void_t &hb_void_t;
+#define HB_VOID (* (const _hb_void_t *) NULL)
/* Return the number of 1 bits in mask. */
static inline HB_CONST_FUNC unsigned int
@@ -219,7 +215,7 @@ _hb_popcount32 (uint32_t mask)
return __builtin_popcount (mask);
#else
/* "HACKMEM 169" */
- register uint32_t y;
+ uint32_t y;
y = (mask >> 1) &033333333333;
y = mask - y - ((y >>1) & 033333333333);
return (((y + (y >> 3)) & 030707070707) % 077);
@@ -233,7 +229,7 @@ _hb_bit_storage (unsigned int number)
#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
return likely (number) ? (sizeof (unsigned int) * 8 - __builtin_clz (number)) : 0;
#else
- register unsigned int n_bits = 0;
+ unsigned int n_bits = 0;
while (number) {
n_bits++;
number >>= 1;
@@ -249,7 +245,7 @@ _hb_ctz (unsigned int number)
#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
return likely (number) ? __builtin_ctz (number) : 0;
#else
- register unsigned int n_bits = 0;
+ unsigned int n_bits = 0;
if (unlikely (!number)) return 0;
while (!(number & 1)) {
n_bits++;
@@ -276,7 +272,7 @@ typedef int (*hb_compare_func_t) (const void *, const void *);
#define HB_PREALLOCED_ARRAY_INIT {0}
-template <typename Type, unsigned int StaticSize>
+template <typename Type, unsigned int StaticSize=16>
struct hb_prealloced_array_t
{
unsigned int len;
@@ -357,14 +353,14 @@ struct hb_prealloced_array_t
return NULL;
}
- inline void sort (void)
+ inline void qsort (void)
{
- qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
+ ::qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
}
- inline void sort (unsigned int start, unsigned int end)
+ inline void qsort (unsigned int start, unsigned int end)
{
- qsort (array + start, end - start, sizeof (Type), (hb_compare_func_t) Type::cmp);
+ ::qsort (array + start, end - start, sizeof (Type), (hb_compare_func_t) Type::cmp);
}
template <typename T>
@@ -387,12 +383,11 @@ struct hb_prealloced_array_t
}
};
-#define HB_AUTO_ARRAY_PREALLOCED 16
template <typename Type>
-struct hb_auto_array_t : hb_prealloced_array_t <Type, HB_AUTO_ARRAY_PREALLOCED>
+struct hb_auto_array_t : hb_prealloced_array_t <Type>
{
- hb_auto_array_t (void) { hb_prealloced_array_t<Type, HB_AUTO_ARRAY_PREALLOCED>::init (); }
- ~hb_auto_array_t (void) { hb_prealloced_array_t<Type, HB_AUTO_ARRAY_PREALLOCED>::finish (); }
+ hb_auto_array_t (void) { hb_prealloced_array_t<Type>::init (); }
+ ~hb_auto_array_t (void) { hb_prealloced_array_t<Type>::finish (); }
};
@@ -725,7 +720,7 @@ static inline void _hb_warn_no_return (bool returned)
}
}
template <>
-inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
+/*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
{}
template <int max_level, typename ret_t>
@@ -791,20 +786,23 @@ struct hb_auto_trace_t<0, ret_t> {
/* Misc */
+template <typename T> class hb_assert_unsigned_t;
+template <> class hb_assert_unsigned_t<unsigned char> {};
+template <> class hb_assert_unsigned_t<unsigned short> {};
+template <> class hb_assert_unsigned_t<unsigned int> {};
+template <> class hb_assert_unsigned_t<unsigned long> {};
-/* Pre-mature optimization:
- * Checks for lo <= u <= hi but with an optimization if lo and hi
- * are only different in a contiguous set of lower-most bits.
- */
template <typename T> static inline bool
hb_in_range (T u, T lo, T hi)
{
- if ( ((lo^hi) & lo) == 0 &&
- ((lo^hi) & hi) == (lo^hi) &&
- ((lo^hi) & ((lo^hi) + 1)) == 0 )
- return (u & ~(lo^hi)) == lo;
- else
- return lo <= u && u <= hi;
+ /* The sizeof() is here to force template instantiation.
+ * I'm sure there are better ways to do this but can't think of
+ * one right now. Declaring a variable won't work as HB_UNUSED
+ * is unsable on some platforms and unused types are less likely
+ * to generate a warning than unused variables. */
+ ASSERT_STATIC (sizeof (hb_assert_unsigned_t<T>) >= 0);
+
+ return (u - lo) <= (hi - lo);
}
template <typename T> static inline bool
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc b/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc
index e354f29176..5ffc6b1362 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc
@@ -104,8 +104,6 @@ hb_shape_plan_create (hb_face_t *face,
unsigned int num_user_features,
const char * const *shaper_list)
{
- assert (props->direction != HB_DIRECTION_INVALID);
-
hb_shape_plan_t *shape_plan;
hb_feature_t *features = NULL;
@@ -120,6 +118,8 @@ hb_shape_plan_create (hb_face_t *face,
return hb_shape_plan_get_empty ();
}
+ assert (props->direction != HB_DIRECTION_INVALID);
+
hb_face_make_immutable (face);
shape_plan->default_shaper_list = shaper_list == NULL;
shape_plan->face_unsafe = face;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shaper-list.hh b/src/3rdparty/harfbuzz-ng/src/hb-shaper-list.hh
index 5713e057a0..6c537d4921 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-shaper-list.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-shaper-list.hh
@@ -34,25 +34,21 @@
/* Only picks up fonts that have a "Silf" table. */
HB_SHAPER_IMPLEMENT (graphite2)
#endif
-
#ifdef HAVE_CORETEXT
/* Only picks up fonts that have a "mort" or "morx" table. */
-HB_SHAPER_IMPLEMENT (coretext)
+HB_SHAPER_IMPLEMENT (coretext_aat)
#endif
#ifdef HAVE_OT
HB_SHAPER_IMPLEMENT (ot) /* <--- This is our main OpenType shaper. */
#endif
-#ifdef HAVE_HB_OLD
-HB_SHAPER_IMPLEMENT (old)
-#endif
-#ifdef HAVE_ICU_LE
-HB_SHAPER_IMPLEMENT (icu_le)
-#endif
#ifdef HAVE_UNISCRIBE
HB_SHAPER_IMPLEMENT (uniscribe)
#endif
+#ifdef HAVE_CORETEXT
+HB_SHAPER_IMPLEMENT (coretext)
+#endif
#ifdef HAVE_FALLBACK
HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-unicode-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-unicode-private.hh
index ba193e8fa5..a2c59da274 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-unicode-private.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-unicode-private.hh
@@ -102,72 +102,70 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
}
- unsigned int
+ inline unsigned int
modified_combining_class (hb_codepoint_t unicode)
{
/* XXX This hack belongs to the Myanmar shaper. */
- if (unlikely (unicode == 0x1037)) unicode = 0x103A;
+ if (unlikely (unicode == 0x1037u)) unicode = 0x103Au;
/* XXX This hack belongs to the SEA shaper (for Tai Tham):
* Reorder SAKOT to ensure it comes after any tone marks. */
- if (unlikely (unicode == 0x1A60)) return 254;
+ if (unlikely (unicode == 0x1A60u)) return 254;
+
+ /* XXX This hack belongs to the Tibetan shaper:
+ * Reorder PADMA to ensure it comes after any vowel marks. */
+ if (unlikely (unicode == 0x0FC6u)) return 254;
return _hb_modified_combining_class[combining_class (unicode)];
}
- inline hb_bool_t
+ static inline hb_bool_t
is_variation_selector (hb_codepoint_t unicode)
{
- return unlikely (hb_in_ranges<hb_codepoint_t> (unicode,
- 0x180B, 0x180D, /* MONGOLIAN FREE VARIATION SELECTOR ONE..THREE */
- 0xFE00, 0xFE0F, /* VARIATION SELECTOR-1..16 */
- 0xE0100, 0xE01EF)); /* VARIATION SELECTOR-17..256 */
+ /* U+180B..180D MONGOLIAN FREE VARIATION SELECTORs are handled in the
+ * Arabic shaper. No need to match them here. */
+ return unlikely (hb_in_ranges (unicode,
+ 0xFE00u, 0xFE0Fu, /* VARIATION SELECTOR-1..16 */
+ 0xE0100u, 0xE01EFu)); /* VARIATION SELECTOR-17..256 */
}
/* Default_Ignorable codepoints:
*
- * Note that as of Oct 2012 (Unicode 6.2), U+180E MONGOLIAN VOWEL SEPARATOR
- * is NOT Default_Ignorable, but it really behaves in a way that it should
- * be. That has been reported to the Unicode Technical Committee for
- * consideration. As such, we include it here, since Uniscribe removes it.
- * It *is* in Unicode 6.3 however. U+061C ARABIC LETTER MARK from Unicode
- * 6.3 is also added manually. The new Unicode 6.3 bidi formatting
- * characters are encoded in a block that was Default_Ignorable already.
- *
* Note: While U+115F, U+1160, U+3164 and U+FFA0 are Default_Ignorable,
* we do NOT want to hide them, as the way Uniscribe has implemented them
* is with regular spacing glyphs, and that's the way fonts are made to work.
* As such, we make exceptions for those four.
*
- * Gathered from:
- * http://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:DI:]&abb=on&ucd=on&esc=on
- *
- * Last updated to the page with the following versions:
- * Version 3.6; ICU version: 50.0.1.0; Unicode version: 6.1.0.0
- *
- * 4,167 Code Points
- *
- * [\u00AD\u034F\u115F\u1160\u17B4\u17B5\u180B-\u180D\u200B-\u200F\u202A-\u202E\u2060-\u206F\u3164\uFE00-\uFE0F\uFEFF\uFFA0\uFFF0-\uFFF8\U0001D173-\U0001D17A\U000E0000-\U000E0FFF]
- *
- * 00AD ;SOFT HYPHEN
- * 034F ;COMBINING GRAPHEME JOINER
- * #115F ;HANGUL CHOSEONG FILLER
- * #1160 ;HANGUL JUNGSEONG FILLER
- * 17B4 ;KHMER VOWEL INHERENT AQ
- * 17B5 ;KHMER VOWEL INHERENT AA
- * 180B..180D ;MONGOLIAN FREE VARIATION SELECTOR THREE
- * 200B..200F ;RIGHT-TO-LEFT MARK
- * 202A..202E ;RIGHT-TO-LEFT OVERRIDE
- * 2060..206F ;NOMINAL DIGIT SHAPES
- * #3164 ;HANGUL FILLER
- * FE00..FE0F ;VARIATION SELECTOR-16
- * FEFF ;ZERO WIDTH NO-BREAK SPACE
- * #FFA0 ;HALFWIDTH HANGUL FILLER
- * FFF0..FFF8 ;<unassigned-FFF8>
- * 1D173..1D17A ;MUSICAL SYMBOL END PHRASE
- * E0000..E0FFF ;<unassigned-E0FFF>
+ * Unicode 7.0:
+ * $ grep '; Default_Ignorable_Code_Point ' DerivedCoreProperties.txt | sed 's/;.*#/#/'
+ * 00AD # Cf SOFT HYPHEN
+ * 034F # Mn COMBINING GRAPHEME JOINER
+ * 061C # Cf ARABIC LETTER MARK
+ * 115F..1160 # Lo [2] HANGUL CHOSEONG FILLER..HANGUL JUNGSEONG FILLER
+ * 17B4..17B5 # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
+ * 180B..180D # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
+ * 180E # Cf MONGOLIAN VOWEL SEPARATOR
+ * 200B..200F # Cf [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK
+ * 202A..202E # Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
+ * 2060..2064 # Cf [5] WORD JOINER..INVISIBLE PLUS
+ * 2065 # Cn <reserved-2065>
+ * 2066..206F # Cf [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES
+ * 3164 # Lo HANGUL FILLER
+ * FE00..FE0F # Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
+ * FEFF # Cf ZERO WIDTH NO-BREAK SPACE
+ * FFA0 # Lo HALFWIDTH HANGUL FILLER
+ * FFF0..FFF8 # Cn [9] <reserved-FFF0>..<reserved-FFF8>
+ * 1BCA0..1BCA3 # Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
+ * 1D173..1D17A # Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
+ * E0000 # Cn <reserved-E0000>
+ * E0001 # Cf LANGUAGE TAG
+ * E0002..E001F # Cn [30] <reserved-E0002>..<reserved-E001F>
+ * E0020..E007F # Cf [96] TAG SPACE..CANCEL TAG
+ * E0080..E00FF # Cn [128] <reserved-E0080>..<reserved-E00FF>
+ * E0100..E01EF # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
+ * E01F0..E0FFF # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
*/
- inline hb_bool_t
+ static inline hb_bool_t
is_default_ignorable (hb_codepoint_t ch)
{
hb_codepoint_t plane = ch >> 16;
@@ -176,16 +174,16 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
/* BMP */
hb_codepoint_t page = ch >> 8;
switch (page) {
- case 0x00: return unlikely (ch == 0x00AD);
- case 0x03: return unlikely (ch == 0x034F);
- case 0x06: return unlikely (ch == 0x061C);
- case 0x17: return hb_in_range<hb_codepoint_t> (ch, 0x17B4, 0x17B5);
- case 0x18: return hb_in_range<hb_codepoint_t> (ch, 0x180B, 0x180E);
- case 0x20: return hb_in_ranges<hb_codepoint_t> (ch, 0x200B, 0x200F,
- 0x202A, 0x202E,
- 0x2060, 0x206F);
- case 0xFE: return hb_in_range<hb_codepoint_t> (ch, 0xFE00, 0xFE0F) || ch == 0xFEFF;
- case 0xFF: return hb_in_range<hb_codepoint_t> (ch, 0xFFF0, 0xFFF8);
+ case 0x00: return unlikely (ch == 0x00ADu);
+ case 0x03: return unlikely (ch == 0x034Fu);
+ case 0x06: return unlikely (ch == 0x061Cu);
+ case 0x17: return hb_in_range (ch, 0x17B4u, 0x17B5u);
+ case 0x18: return hb_in_range (ch, 0x180Bu, 0x180Eu);
+ case 0x20: return hb_in_ranges (ch, 0x200Bu, 0x200Fu,
+ 0x202Au, 0x202Eu,
+ 0x2060u, 0x206Fu);
+ case 0xFE: return hb_in_range (ch, 0xFE00u, 0xFE0Fu) || ch == 0xFEFFu;
+ case 0xFF: return hb_in_range (ch, 0xFFF0u, 0xFFF8u);
default: return false;
}
}
@@ -193,8 +191,9 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
{
/* Other planes */
switch (plane) {
- case 0x01: return hb_in_range<hb_codepoint_t> (ch, 0x0001D173, 0x0001D17A);
- case 0x0E: return hb_in_range<hb_codepoint_t> (ch, 0x000E0000, 0x000E0FFF);
+ case 0x01: return hb_in_ranges (ch, 0x1BCA0u, 0x1BCA3u,
+ 0x1D173u, 0x1D17Au);
+ case 0x0E: return hb_in_range (ch, 0xE0000u, 0xE0FFFu);
default: return false;
}
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-unicode.cc b/src/3rdparty/harfbuzz-ng/src/hb-unicode.cc
index 5b44913bd3..84e5c06fd3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-unicode.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-unicode.cc
@@ -133,7 +133,7 @@ hb_unicode_funcs_get_default (void)
#ifdef HAVE_GLIB
HB_UNICODE_FUNCS_IMPLEMENT(glib)
-#elif 0 && defined(HAVE_ICU)
+#elif defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN)
HB_UNICODE_FUNCS_IMPLEMENT(icu)
#elif defined(HAVE_UCDN)
HB_UNICODE_FUNCS_IMPLEMENT(ucdn)
@@ -146,8 +146,13 @@ hb_unicode_funcs_get_default (void)
}
#if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL)
-#pragma message("Could not find any Unicode functions implementation, you have to provide your own.")
-#pragma message("To suppress this warnings, define HB_NO_UNICODE_FUNCS.")
+#ifdef _MSC_VER
+#pragma message("Could not find any Unicode functions implementation, you have to provide your own")
+#pragma message("To suppress this warnings, define HB_NO_UNICODE_FUNCS")
+#else
+#warning "Could not find any Unicode functions implementation, you have to provide your own"
+#warning "To suppress this warning, define HB_NO_UNICODE_FUNCS"
+#endif
#endif
/**
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-utf-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-utf-private.hh
index b9a6519d28..0b798a05c3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-utf-private.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-utf-private.hh
@@ -1,5 +1,5 @@
/*
- * Copyright © 2011,2012 Google, Inc.
+ * Copyright © 2011,2012,2014 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -29,176 +29,221 @@
#include "hb-private.hh"
+template <typename T, bool validate=true> struct hb_utf_t;
+
/* UTF-8 */
-#define HB_UTF8_COMPUTE(Char, Mask, Len) \
- if (Char < 128) { Len = 1; Mask = 0x7f; } \
- else if ((Char & 0xe0) == 0xc0) { Len = 2; Mask = 0x1f; } \
- else if ((Char & 0xf0) == 0xe0) { Len = 3; Mask = 0x0f; } \
- else if ((Char & 0xf8) == 0xf0) { Len = 4; Mask = 0x07; } \
- else Len = 0;
-
-static inline const uint8_t *
-hb_utf_next (const uint8_t *text,
- const uint8_t *end,
- hb_codepoint_t *unicode)
+template <>
+struct hb_utf_t<uint8_t, true>
{
- hb_codepoint_t c = *text, mask;
- unsigned int len;
-
- /* TODO check for overlong sequences? */
-
- HB_UTF8_COMPUTE (c, mask, len);
- if (unlikely (!len || (unsigned int) (end - text) < len)) {
- *unicode = -1;
- return text + 1;
- } else {
- hb_codepoint_t result;
- unsigned int i;
- result = c & mask;
- for (i = 1; i < len; i++)
+ static inline const uint8_t *
+ next (const uint8_t *text,
+ const uint8_t *end,
+ hb_codepoint_t *unicode,
+ hb_codepoint_t replacement)
+ {
+ /* Written to only accept well-formed sequences.
+ * Based on ideas from ICU's U8_NEXT.
+ * Generates one "replacement" for each ill-formed byte. */
+
+ hb_codepoint_t c = *text++;
+
+ if (c > 0x7Fu)
+ {
+ if (hb_in_range (c, 0xC2u, 0xDFu)) /* Two-byte */
{
- if (unlikely ((text[i] & 0xc0) != 0x80))
- {
- *unicode = -1;
- return text + 1;
- }
- result <<= 6;
- result |= (text[i] & 0x3f);
+ unsigned int t1;
+ if (likely (text < end &&
+ (t1 = text[0] - 0x80u) <= 0x3Fu))
+ {
+ c = ((c&0x1Fu)<<6) | t1;
+ text++;
+ }
+ else
+ goto error;
}
- *unicode = result;
- return text + len;
- }
-}
+ else if (hb_in_range (c, 0xE0u, 0xEFu)) /* Three-byte */
+ {
+ unsigned int t1, t2;
+ if (likely (1 < end - text &&
+ (t1 = text[0] - 0x80u) <= 0x3Fu &&
+ (t2 = text[1] - 0x80u) <= 0x3Fu))
+ {
+ c = ((c&0xFu)<<12) | (t1<<6) | t2;
+ if (unlikely (c < 0x0800u || hb_in_range (c, 0xD800u, 0xDFFFu)))
+ goto error;
+ text += 2;
+ }
+ else
+ goto error;
+ }
+ else if (hb_in_range (c, 0xF0u, 0xF4u)) /* Four-byte */
+ {
+ unsigned int t1, t2, t3;
+ if (likely (2 < end - text &&
+ (t1 = text[0] - 0x80u) <= 0x3Fu &&
+ (t2 = text[1] - 0x80u) <= 0x3Fu &&
+ (t3 = text[2] - 0x80u) <= 0x3Fu))
+ {
+ c = ((c&0x7u)<<18) | (t1<<12) | (t2<<6) | t3;
+ if (unlikely (!hb_in_range (c, 0x10000u, 0x10FFFFu)))
+ goto error;
+ text += 3;
+ }
+ else
+ goto error;
+ }
+ else
+ goto error;
+ }
-static inline const uint8_t *
-hb_utf_prev (const uint8_t *text,
- const uint8_t *start,
- hb_codepoint_t *unicode)
-{
- const uint8_t *end = text--;
- while (start < text && (*text & 0xc0) == 0x80 && end - text < 4)
- text--;
+ *unicode = c;
+ return text;
+
+ error:
+ *unicode = replacement;
+ return text;
+ }
- hb_codepoint_t c = *text, mask;
- unsigned int len;
+ static inline const uint8_t *
+ prev (const uint8_t *text,
+ const uint8_t *start,
+ hb_codepoint_t *unicode,
+ hb_codepoint_t replacement)
+ {
+ const uint8_t *end = text--;
+ while (start < text && (*text & 0xc0) == 0x80 && end - text < 4)
+ text--;
- /* TODO check for overlong sequences? */
+ if (likely (next (text, end, unicode, replacement) == end))
+ return text;
- HB_UTF8_COMPUTE (c, mask, len);
- if (unlikely (!len || (unsigned int) (end - text) != len)) {
- *unicode = -1;
+ *unicode = replacement;
return end - 1;
- } else {
- hb_codepoint_t result;
- unsigned int i;
- result = c & mask;
- for (i = 1; i < len; i++)
- {
- result <<= 6;
- result |= (text[i] & 0x3f);
- }
- *unicode = result;
- return text;
}
-}
-
-static inline unsigned int
-hb_utf_strlen (const uint8_t *text)
-{
- return strlen ((const char *) text);
-}
+ static inline unsigned int
+ strlen (const uint8_t *text)
+ {
+ return ::strlen ((const char *) text);
+ }
+};
/* UTF-16 */
-static inline const uint16_t *
-hb_utf_next (const uint16_t *text,
- const uint16_t *end,
- hb_codepoint_t *unicode)
+template <>
+struct hb_utf_t<uint16_t, true>
{
- hb_codepoint_t c = *text++;
-
- if (unlikely (hb_in_range<hb_codepoint_t> (c, 0xd800, 0xdbff)))
+ static inline const uint16_t *
+ next (const uint16_t *text,
+ const uint16_t *end,
+ hb_codepoint_t *unicode,
+ hb_codepoint_t replacement)
{
- /* high surrogate */
- hb_codepoint_t l;
- if (text < end && ((l = *text), likely (hb_in_range<hb_codepoint_t> (l, 0xdc00, 0xdfff))))
+ hb_codepoint_t c = *text++;
+
+ if (likely (!hb_in_range (c, 0xD800u, 0xDFFFu)))
{
- /* low surrogate */
- *unicode = (c << 10) + l - ((0xd800 << 10) - 0x10000 + 0xdc00);
- text++;
- } else
- *unicode = -1;
- } else
- *unicode = c;
+ *unicode = c;
+ return text;
+ }
- return text;
-}
+ if (likely (hb_in_range (c, 0xD800u, 0xDBFFu)))
+ {
+ /* High-surrogate in c */
+ hb_codepoint_t l;
+ if (text < end && ((l = *text), likely (hb_in_range (l, 0xDC00u, 0xDFFFu))))
+ {
+ /* Low-surrogate in l */
+ *unicode = (c << 10) + l - ((0xD800u << 10) - 0x10000u + 0xDC00u);
+ text++;
+ return text;
+ }
+ }
-static inline const uint16_t *
-hb_utf_prev (const uint16_t *text,
- const uint16_t *start,
- hb_codepoint_t *unicode)
-{
- hb_codepoint_t c = *--text;
+ /* Lonely / out-of-order surrogate. */
+ *unicode = replacement;
+ return text;
+ }
- if (unlikely (hb_in_range<hb_codepoint_t> (c, 0xdc00, 0xdfff)))
+ static inline const uint16_t *
+ prev (const uint16_t *text,
+ const uint16_t *start,
+ hb_codepoint_t *unicode,
+ hb_codepoint_t replacement)
{
- /* low surrogate */
- hb_codepoint_t h;
- if (start < text && ((h = *(text - 1)), likely (hb_in_range<hb_codepoint_t> (h, 0xd800, 0xdbff))))
+ const uint16_t *end = text--;
+ hb_codepoint_t c = *text;
+
+ if (likely (!hb_in_range (c, 0xD800u, 0xDFFFu)))
{
- /* high surrogate */
- *unicode = (h << 10) + c - ((0xd800 << 10) - 0x10000 + 0xdc00);
- text--;
- } else
- *unicode = -1;
- } else
- *unicode = c;
+ *unicode = c;
+ return text;
+ }
- return text;
-}
+ if (likely (start < text && hb_in_range (c, 0xDC00u, 0xDFFFu)))
+ text--;
+ if (likely (next (text, end, unicode, replacement) == end))
+ return text;
-static inline unsigned int
-hb_utf_strlen (const uint16_t *text)
-{
- unsigned int l = 0;
- while (*text++) l++;
- return l;
-}
+ *unicode = replacement;
+ return end - 1;
+ }
+
+
+ static inline unsigned int
+ strlen (const uint16_t *text)
+ {
+ unsigned int l = 0;
+ while (*text++) l++;
+ return l;
+ }
+};
/* UTF-32 */
-static inline const uint32_t *
-hb_utf_next (const uint32_t *text,
- const uint32_t *end HB_UNUSED,
- hb_codepoint_t *unicode)
+template <bool validate>
+struct hb_utf_t<uint32_t, validate>
{
- *unicode = *text++;
- return text;
-}
-
-static inline const uint32_t *
-hb_utf_prev (const uint32_t *text,
- const uint32_t *start HB_UNUSED,
- hb_codepoint_t *unicode)
-{
- *unicode = *--text;
- return text;
-}
+ static inline const uint32_t *
+ next (const uint32_t *text,
+ const uint32_t *end HB_UNUSED,
+ hb_codepoint_t *unicode,
+ hb_codepoint_t replacement)
+ {
+ hb_codepoint_t c = *text++;
+ if (validate && unlikely (c > 0x10FFFFu || hb_in_range (c, 0xD800u, 0xDFFFu)))
+ goto error;
+ *unicode = c;
+ return text;
-static inline unsigned int
-hb_utf_strlen (const uint32_t *text)
-{
- unsigned int l = 0;
- while (*text++) l++;
- return l;
-}
+ error:
+ *unicode = replacement;
+ return text;
+ }
+
+ static inline const uint32_t *
+ prev (const uint32_t *text,
+ const uint32_t *start HB_UNUSED,
+ hb_codepoint_t *unicode,
+ hb_codepoint_t replacement)
+ {
+ next (text - 1, text, unicode, replacement);
+ return text - 1;
+ }
+
+ static inline unsigned int
+ strlen (const uint32_t *text)
+ {
+ unsigned int l = 0;
+ while (*text++) l++;
+ return l;
+ }
+};
#endif /* HB_UTF_PRIVATE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-version.h b/src/3rdparty/harfbuzz-ng/src/hb-version.h
index 790e0ecbae..517cc8f26e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-version.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-version.h
@@ -38,12 +38,12 @@ HB_BEGIN_DECLS
#define HB_VERSION_MAJOR 0
#define HB_VERSION_MINOR 9
-#define HB_VERSION_MICRO 25
+#define HB_VERSION_MICRO 32
-#define HB_VERSION_STRING "0.9.25"
+#define HB_VERSION_STRING "0.9.32"
-#define HB_VERSION_CHECK(major,minor,micro) \
- ((major)*10000+(minor)*100+(micro) >= \
+#define HB_VERSION_ATLEAST(major,minor,micro) \
+ ((major)*10000+(minor)*100+(micro) <= \
HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO)
@@ -56,9 +56,9 @@ const char *
hb_version_string (void);
hb_bool_t
-hb_version_check (unsigned int major,
- unsigned int minor,
- unsigned int micro);
+hb_version_atleast (unsigned int major,
+ unsigned int minor,
+ unsigned int micro);
HB_END_DECLS
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-warning.cc b/src/3rdparty/harfbuzz-ng/src/hb-warning.cc
index 4f1f65f5a2..e0f88e2d4a 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-warning.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-warning.cc
@@ -53,14 +53,3 @@
#endif
-#include "hb-unicode-private.hh"
-
-#if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL)
-#ifdef _MSC_VER
-#pragma message("Could not find any Unicode functions implementation, you have to provide your own")
-#pragma message("To suppress this warnings, define HB_NO_UNICODE_FUNCS")
-#else
-#warning "Could not find any Unicode functions implementation, you have to provide your own"
-#warning "To suppress this warning, define HB_NO_UNICODE_FUNCS"
-#endif
-#endif
diff --git a/src/3rdparty/pcre/AUTHORS b/src/3rdparty/pcre/AUTHORS
index 97d8c71dd6..5eee1af4c6 100644
--- a/src/3rdparty/pcre/AUTHORS
+++ b/src/3rdparty/pcre/AUTHORS
@@ -8,7 +8,7 @@ Email domain: cam.ac.uk
University of Cambridge Computing Service,
Cambridge, England.
-Copyright (c) 1997-2013 University of Cambridge
+Copyright (c) 1997-2014 University of Cambridge
All rights reserved
@@ -19,7 +19,7 @@ Written by: Zoltan Herczeg
Email local part: hzmester
Emain domain: freemail.hu
-Copyright(c) 2010-2013 Zoltan Herczeg
+Copyright(c) 2010-2014 Zoltan Herczeg
All rights reserved.
@@ -30,7 +30,7 @@ Written by: Zoltan Herczeg
Email local part: hzmester
Emain domain: freemail.hu
-Copyright(c) 2009-2013 Zoltan Herczeg
+Copyright(c) 2009-2014 Zoltan Herczeg
All rights reserved.
diff --git a/src/3rdparty/pcre/LICENCE b/src/3rdparty/pcre/LICENCE
index 3aff6a62c0..602e4ae680 100644
--- a/src/3rdparty/pcre/LICENCE
+++ b/src/3rdparty/pcre/LICENCE
@@ -24,7 +24,7 @@ Email domain: cam.ac.uk
University of Cambridge Computing Service,
Cambridge, England.
-Copyright (c) 1997-2013 University of Cambridge
+Copyright (c) 1997-2014 University of Cambridge
All rights reserved.
@@ -35,7 +35,7 @@ Written by: Zoltan Herczeg
Email local part: hzmester
Emain domain: freemail.hu
-Copyright(c) 2010-2013 Zoltan Herczeg
+Copyright(c) 2010-2014 Zoltan Herczeg
All rights reserved.
@@ -46,7 +46,7 @@ Written by: Zoltan Herczeg
Email local part: hzmester
Emain domain: freemail.hu
-Copyright(c) 2009-2013 Zoltan Herczeg
+Copyright(c) 2009-2014 Zoltan Herczeg
All rights reserved.
diff --git a/src/3rdparty/pcre/config.h b/src/3rdparty/pcre/config.h
index d45d88abd1..de3832a8e2 100644
--- a/src/3rdparty/pcre/config.h
+++ b/src/3rdparty/pcre/config.h
@@ -16,10 +16,11 @@
/*
man 3 pcrejit for a list of supported platforms;
- as PCRE 8.30, stable JIT support is available for:
+ as PCRE 8.35, stable JIT support is available for:
- ARM v5, v7, and Thumb2 (__GNUC__ compilers only)
- x86/x86-64
- MIPS 32bit (__GNUC__ compilers only)
+ - Power PC 32-bit and 64-bit (__GNUC__ compilers only)
*/
#if !defined(PCRE_DISABLE_JIT) && (\
/* ARM */ \
@@ -30,6 +31,11 @@
/* MIPS32 */ \
|| (defined(__GNUC__) \
&& (defined(__mips) || defined(__mips__)) \
- && !(defined(_MIPS_ARCH_MIPS64) || defined(__mips64))))
+ && !(defined(_MIPS_ARCH_MIPS64) || defined(__mips64))) \
+ || (defined(__GNUC__) \
+ && (defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \
+ || defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \
+ || defined(_M_MPPC) || defined(_M_PPC))) \
+ )
# define SUPPORT_JIT
#endif
diff --git a/src/3rdparty/pcre/import_from_pcre_tarball.sh b/src/3rdparty/pcre/import_from_pcre_tarball.sh
index 5710e36a0f..ead4ac8c88 100755
--- a/src/3rdparty/pcre/import_from_pcre_tarball.sh
+++ b/src/3rdparty/pcre/import_from_pcre_tarball.sh
@@ -136,15 +136,19 @@ FILES="
sljit/sljitExecAllocator.c
sljit/sljitLir.c
sljit/sljitLir.h
- sljit/sljitNativeARM_Thumb2.c
- sljit/sljitNativeARM_v5.c
+ sljit/sljitNativeARM_32.c
+ sljit/sljitNativeARM_64.c
+ sljit/sljitNativeARM_T2_32.c
sljit/sljitNativeMIPS_32.c
+ sljit/sljitNativeMIPS_64.c
sljit/sljitNativeMIPS_common.c
sljit/sljitNativePPC_32.c
sljit/sljitNativePPC_64.c
sljit/sljitNativePPC_common.c
sljit/sljitNativeSPARC_32.c
sljit/sljitNativeSPARC_common.c
+ sljit/sljitNativeTILEGX_64.c
+ sljit/sljitNativeTILEGX-encoder.c
sljit/sljitNativeX86_32.c
sljit/sljitNativeX86_64.c
sljit/sljitNativeX86_common.c
diff --git a/src/3rdparty/pcre/patches/bug_1423_jit_condition_misoptimization_fix.diff b/src/3rdparty/pcre/patches/bug_1423_jit_condition_misoptimization_fix.diff
deleted file mode 100644
index 4fd46d57a1..0000000000
--- a/src/3rdparty/pcre/patches/bug_1423_jit_condition_misoptimization_fix.diff
+++ /dev/null
@@ -1,15 +0,0 @@
-Index: pcre_jit_compile.c
-===================================================================
---- pcre_jit_compile.c (revision 1413)
-+++ pcre_jit_compile.c (working copy)
-@@ -3546,7 +3546,9 @@
- }
- return TRUE;
- }
-- if ((ranges[3] - ranges[2]) == (ranges[5] - ranges[4]) && is_powerof2(ranges[4] - ranges[2]))
-+ if ((ranges[3] - ranges[2]) == (ranges[5] - ranges[4])
-+ && (ranges[2] | (ranges[4] - ranges[2])) == ranges[4]
-+ && is_powerof2(ranges[4] - ranges[2]))
- {
- if (readch)
- read_char(common);
diff --git a/src/3rdparty/pcre/pcre.h b/src/3rdparty/pcre/pcre.h
index c85f36b6bc..ce4251c8e6 100644
--- a/src/3rdparty/pcre/pcre.h
+++ b/src/3rdparty/pcre/pcre.h
@@ -5,7 +5,7 @@
/* This is the public header file for the PCRE library, to be #included by
applications that call the PCRE functions.
- Copyright (c) 1997-2013 University of Cambridge
+ Copyright (c) 1997-2014 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
/* The current PCRE version information. */
#define PCRE_MAJOR 8
-#define PCRE_MINOR 34
+#define PCRE_MINOR 35
#define PCRE_PRERELEASE
-#define PCRE_DATE 2013-12-15
+#define PCRE_DATE 2014-04-04
/* When an application links to a PCRE DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE, the appropriate
@@ -491,36 +491,42 @@ PCRE_EXP_DECL void (*pcre_free)(void *);
PCRE_EXP_DECL void *(*pcre_stack_malloc)(size_t);
PCRE_EXP_DECL void (*pcre_stack_free)(void *);
PCRE_EXP_DECL int (*pcre_callout)(pcre_callout_block *);
+PCRE_EXP_DECL int (*pcre_stack_guard)(void);
PCRE_EXP_DECL void *(*pcre16_malloc)(size_t);
PCRE_EXP_DECL void (*pcre16_free)(void *);
PCRE_EXP_DECL void *(*pcre16_stack_malloc)(size_t);
PCRE_EXP_DECL void (*pcre16_stack_free)(void *);
PCRE_EXP_DECL int (*pcre16_callout)(pcre16_callout_block *);
+PCRE_EXP_DECL int (*pcre16_stack_guard)(void);
PCRE_EXP_DECL void *(*pcre32_malloc)(size_t);
PCRE_EXP_DECL void (*pcre32_free)(void *);
PCRE_EXP_DECL void *(*pcre32_stack_malloc)(size_t);
PCRE_EXP_DECL void (*pcre32_stack_free)(void *);
PCRE_EXP_DECL int (*pcre32_callout)(pcre32_callout_block *);
+PCRE_EXP_DECL int (*pcre32_stack_guard)(void);
#else /* VPCOMPAT */
PCRE_EXP_DECL void *pcre_malloc(size_t);
PCRE_EXP_DECL void pcre_free(void *);
PCRE_EXP_DECL void *pcre_stack_malloc(size_t);
PCRE_EXP_DECL void pcre_stack_free(void *);
PCRE_EXP_DECL int pcre_callout(pcre_callout_block *);
+PCRE_EXP_DECL int pcre_stack_guard(void);
PCRE_EXP_DECL void *pcre16_malloc(size_t);
PCRE_EXP_DECL void pcre16_free(void *);
PCRE_EXP_DECL void *pcre16_stack_malloc(size_t);
PCRE_EXP_DECL void pcre16_stack_free(void *);
PCRE_EXP_DECL int pcre16_callout(pcre16_callout_block *);
+PCRE_EXP_DECL int pcre16_stack_guard(void);
PCRE_EXP_DECL void *pcre32_malloc(size_t);
PCRE_EXP_DECL void pcre32_free(void *);
PCRE_EXP_DECL void *pcre32_stack_malloc(size_t);
PCRE_EXP_DECL void pcre32_stack_free(void *);
PCRE_EXP_DECL int pcre32_callout(pcre32_callout_block *);
+PCRE_EXP_DECL int pcre32_stack_guard(void);
#endif /* VPCOMPAT */
/* User defined callback which provides a stack just before the match starts. */
diff --git a/src/3rdparty/pcre/pcre_byte_order.c b/src/3rdparty/pcre/pcre_byte_order.c
index 02b8050327..4ce674b0c0 100644
--- a/src/3rdparty/pcre/pcre_byte_order.c
+++ b/src/3rdparty/pcre/pcre_byte_order.c
@@ -6,7 +6,7 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
- Copyright (c) 1997-2013 University of Cambridge
+ Copyright (c) 1997-2014 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -311,9 +311,9 @@ while(TRUE)
ptr++;
}
/* Control should never reach here in 16/32 bit mode. */
-#endif /* !COMPILE_PCRE8 */
-
+#else /* In 8-bit mode, the pattern does not need to be processed. */
return 0;
+#endif /* !COMPILE_PCRE8 */
}
/* End of pcre_byte_order.c */
diff --git a/src/3rdparty/pcre/pcre_compile.c b/src/3rdparty/pcre/pcre_compile.c
index 9708b93923..5ce6b73c44 100644
--- a/src/3rdparty/pcre/pcre_compile.c
+++ b/src/3rdparty/pcre/pcre_compile.c
@@ -6,7 +6,7 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
- Copyright (c) 1997-2013 University of Cambridge
+ Copyright (c) 1997-2014 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -547,6 +547,8 @@ static const char error_texts[] =
"parentheses are too deeply nested\0"
"invalid range in character class\0"
"group name must start with a non-digit\0"
+ /* 85 */
+ "parentheses are too deeply nested (stack check)\0"
;
/* Table to identify digits and hex digits. This is used when compiling
@@ -3070,8 +3072,11 @@ const pcre_uint32 *chr_ptr;
const pcre_uint32 *ochr_ptr;
const pcre_uint32 *list_ptr;
const pcre_uchar *next_code;
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+const pcre_uchar *xclass_flags;
+#endif
const pcre_uint8 *class_bitset;
-const pcre_uint32 *set1, *set2, *set_end;
+const pcre_uint8 *set1, *set2, *set_end;
pcre_uint32 chr;
BOOL accepted, invert_bits;
@@ -3202,12 +3207,12 @@ for(;;)
if (base_list[0] == OP_CLASS)
#endif
{
- set1 = (pcre_uint32 *)(base_end - base_list[2]);
+ set1 = (pcre_uint8 *)(base_end - base_list[2]);
list_ptr = list;
}
else
{
- set1 = (pcre_uint32 *)(code - list[2]);
+ set1 = (pcre_uint8 *)(code - list[2]);
list_ptr = base_list;
}
@@ -3216,41 +3221,53 @@ for(;;)
{
case OP_CLASS:
case OP_NCLASS:
- set2 = (pcre_uint32 *)
+ set2 = (pcre_uint8 *)
((list_ptr == list ? code : base_end) - list_ptr[2]);
break;
- /* OP_XCLASS cannot be supported here, because its bitset
- is not necessarily complete. E.g: [a-\0x{200}] is stored
- as a character range, and the appropriate bits are not set. */
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ case OP_XCLASS:
+ xclass_flags = (list_ptr == list ? code : base_end) - list_ptr[2] + LINK_SIZE;
+ if ((*xclass_flags & XCL_HASPROP) != 0) return FALSE;
+ if ((*xclass_flags & XCL_MAP) == 0)
+ {
+ /* No bits are set for characters < 256. */
+ if (list[1] == 0) return TRUE;
+ /* Might be an empty repeat. */
+ continue;
+ }
+ set2 = (pcre_uint8 *)(xclass_flags + 1);
+ break;
+#endif
case OP_NOT_DIGIT:
- invert_bits = TRUE;
- /* Fall through */
+ invert_bits = TRUE;
+ /* Fall through */
case OP_DIGIT:
- set2 = (pcre_uint32 *)(cd->cbits + cbit_digit);
- break;
+ set2 = (pcre_uint8 *)(cd->cbits + cbit_digit);
+ break;
case OP_NOT_WHITESPACE:
- invert_bits = TRUE;
- /* Fall through */
+ invert_bits = TRUE;
+ /* Fall through */
case OP_WHITESPACE:
- set2 = (pcre_uint32 *)(cd->cbits + cbit_space);
- break;
+ set2 = (pcre_uint8 *)(cd->cbits + cbit_space);
+ break;
case OP_NOT_WORDCHAR:
- invert_bits = TRUE;
- /* Fall through */
+ invert_bits = TRUE;
+ /* Fall through */
case OP_WORDCHAR:
- set2 = (pcre_uint32 *)(cd->cbits + cbit_word);
- break;
+ set2 = (pcre_uint8 *)(cd->cbits + cbit_word);
+ break;
default:
return FALSE;
}
- /* Compare 4 bytes to improve speed. */
- set_end = set1 + (32 / 4);
+ /* Because the sets are unaligned, we need
+ to perform byte comparison here. */
+ set_end = set1 + 32;
if (invert_bits)
{
do
@@ -3551,7 +3568,9 @@ for(;;)
if (list[1] == 0) return TRUE;
}
-return FALSE;
+/* Control never reaches here. There used to be a fail-save return FALSE; here,
+but some compilers complain about an unreachable statement. */
+
}
@@ -3623,7 +3642,7 @@ for (;;)
break;
case OP_MINUPTO:
- *code += OP_MINUPTO - OP_UPTO;
+ *code += OP_POSUPTO - OP_MINUPTO;
break;
}
}
@@ -4062,12 +4081,16 @@ for (c = *cptr; c <= d; c++)
if (c > d) return -1; /* Reached end of range */
+/* Found a character that has a single other case. Search for the end of the
+range, which is either the end of the input range, or a character that has zero
+or more than one other cases. */
+
*ocptr = othercase;
next = othercase + 1;
for (++c; c <= d; c++)
{
- if (UCD_OTHERCASE(c) != next) break;
+ if ((co = UCD_CASESET(c)) != 0 || UCD_OTHERCASE(c) != next) break;
next++;
}
@@ -4105,6 +4128,7 @@ add_to_class(pcre_uint8 *classbits, pcre_uchar **uchardptr, int options,
compile_data *cd, pcre_uint32 start, pcre_uint32 end)
{
pcre_uint32 c;
+pcre_uint32 classbits_end = (end <= 0xff ? end : 0xff);
int n8 = 0;
/* If caseless matching is required, scan the range and process alternate
@@ -4148,7 +4172,7 @@ if ((options & PCRE_CASELESS) != 0)
/* Not UTF-mode, or no UCP */
- for (c = start; c <= end && c < 256; c++)
+ for (c = start; c <= classbits_end; c++)
{
SETBIT(classbits, cd->fcc[c]);
n8++;
@@ -4173,22 +4197,21 @@ in all cases. */
#endif /* COMPILE_PCRE[8|16] */
-/* If all characters are less than 256, use the bit map. Otherwise use extra
-data. */
+/* Use the bitmap for characters < 256. Otherwise use extra data.*/
-if (end < 0x100)
+for (c = start; c <= classbits_end; c++)
{
- for (c = start; c <= end; c++)
- {
- n8++;
- SETBIT(classbits, c);
- }
+ /* Regardless of start, c will always be <= 255. */
+ SETBIT(classbits, c);
+ n8++;
}
-else
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+if (start <= 0xff) start = 0xff + 1;
+
+if (end >= start)
{
pcre_uchar *uchardata = *uchardptr;
-
#ifdef SUPPORT_UTF
if ((options & PCRE_UTF8) != 0) /* All UTFs use the same flag bit */
{
@@ -4228,6 +4251,7 @@ else
*uchardptr = uchardata; /* Updata extra data pointer */
}
+#endif /* SUPPORT_UTF || !COMPILE_PCRE8 */
return n8; /* Number of 8-bit characters */
}
@@ -4449,6 +4473,9 @@ for (;; ptr++)
BOOL reset_bracount;
int class_has_8bitchar;
int class_one_char;
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ BOOL xclass_has_prop;
+#endif
int newoptions;
int recno;
int refsign;
@@ -4783,13 +4810,26 @@ for (;; ptr++)
should_flip_negation = FALSE;
+ /* Extended class (xclass) will be used when characters > 255
+ might match. */
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ xclass = FALSE;
+ class_uchardata = code + LINK_SIZE + 2; /* For XCLASS items */
+ class_uchardata_base = class_uchardata; /* Save the start */
+#endif
+
/* For optimization purposes, we track some properties of the class:
class_has_8bitchar will be non-zero if the class contains at least one <
256 character; class_one_char will be 1 if the class contains just one
- character. */
+ character; xclass_has_prop will be TRUE if unicode property checks
+ are present in the class. */
class_has_8bitchar = 0;
class_one_char = 0;
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ xclass_has_prop = FALSE;
+#endif
/* Initialize the 32-char bit map to all zeros. We build the map in a
temporary bit of memory, in case the class contains fewer than two
@@ -4798,12 +4838,6 @@ for (;; ptr++)
memset(classbits, 0, 32 * sizeof(pcre_uint8));
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
- xclass = FALSE;
- class_uchardata = code + LINK_SIZE + 2; /* For XCLASS items */
- class_uchardata_base = class_uchardata; /* Save the start */
-#endif
-
/* Process characters until ] is reached. By writing this as a "do" it
means that an initial ] is taken as a data character. At the start of the
loop, c contains the first byte of the character. */
@@ -4927,6 +4961,7 @@ for (;; ptr++)
*class_uchardata++ = local_negate? XCL_NOTPROP : XCL_PROP;
*class_uchardata++ = ptype;
*class_uchardata++ = 0;
+ xclass_has_prop = TRUE;
ptr = tempptr + 1;
continue;
@@ -5109,6 +5144,7 @@ for (;; ptr++)
XCL_PROP : XCL_NOTPROP;
*class_uchardata++ = ptype;
*class_uchardata++ = pdata;
+ xclass_has_prop = TRUE;
class_has_8bitchar--; /* Undo! */
continue;
}
@@ -5403,6 +5439,7 @@ for (;; ptr++)
*code++ = OP_XCLASS;
code += LINK_SIZE;
*code = negate_class? XCL_NOT:0;
+ if (xclass_has_prop) *code |= XCL_HASPROP;
/* If the map is required, move up the extra data to make room for it;
otherwise just move the code pointer to the end of the extra data. */
@@ -5412,6 +5449,8 @@ for (;; ptr++)
*code++ |= XCL_MAP;
memmove(code + (32 / sizeof(pcre_uchar)), code,
IN_UCHARS(class_uchardata - code));
+ if (negate_class && !xclass_has_prop)
+ for (c = 0; c < 32; c++) classbits[c] = ~classbits[c];
memcpy(code, classbits, 32);
code = class_uchardata + (32 / sizeof(pcre_uchar));
}
@@ -6580,7 +6619,10 @@ for (;; ptr++)
code[1+LINK_SIZE] = OP_CREF;
skipbytes = 1+IMM2_SIZE;
- refsign = -1;
+ refsign = -1; /* => not a number */
+ namelen = -1; /* => not a name; must set to avoid warning */
+ name = NULL; /* Always set to avoid warning */
+ recno = 0; /* Always set to avoid warning */
/* Check for a test for recursion in a named group. */
@@ -6617,7 +6659,6 @@ for (;; ptr++)
if (refsign >= 0)
{
- recno = 0;
while (IS_DIGIT(*ptr))
{
recno = recno * 10 + (int)(*ptr - CHAR_0);
@@ -7994,6 +8035,16 @@ unsigned int orig_bracount;
unsigned int max_bracount;
branch_chain bc;
+/* If set, call the external function that checks for stack availability. */
+
+if (PUBL(stack_guard) != NULL && PUBL(stack_guard)())
+ {
+ *errorcodeptr= ERR85;
+ return FALSE;
+ }
+
+/* Miscellaneous initialization */
+
bc.outer = bcptr;
bc.current_branch = code;
diff --git a/src/3rdparty/pcre/pcre_dfa_exec.c b/src/3rdparty/pcre/pcre_dfa_exec.c
index 243309789e..886df525cc 100644
--- a/src/3rdparty/pcre/pcre_dfa_exec.c
+++ b/src/3rdparty/pcre/pcre_dfa_exec.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language (but see
below for why this module is different).
Written by Philip Hazel
- Copyright (c) 1997-2013 University of Cambridge
+ Copyright (c) 1997-2014 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -1473,7 +1473,7 @@ for (;;)
goto ANYNL01;
case CHAR_CR:
- if (ptr + 1 < end_subject && RAWUCHARTEST(ptr + 1) == CHAR_LF) ncount = 1;
+ if (ptr + 1 < end_subject && UCHAR21TEST(ptr + 1) == CHAR_LF) ncount = 1;
/* Fall through */
ANYNL01:
@@ -1742,7 +1742,7 @@ for (;;)
goto ANYNL02;
case CHAR_CR:
- if (ptr + 1 < end_subject && RAWUCHARTEST(ptr + 1) == CHAR_LF) ncount = 1;
+ if (ptr + 1 < end_subject && UCHAR21TEST(ptr + 1) == CHAR_LF) ncount = 1;
/* Fall through */
ANYNL02:
@@ -2012,7 +2012,7 @@ for (;;)
goto ANYNL03;
case CHAR_CR:
- if (ptr + 1 < end_subject && RAWUCHARTEST(ptr + 1) == CHAR_LF) ncount = 1;
+ if (ptr + 1 < end_subject && UCHAR21TEST(ptr + 1) == CHAR_LF) ncount = 1;
/* Fall through */
ANYNL03:
@@ -2210,7 +2210,7 @@ for (;;)
if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
reset_could_continue = TRUE;
}
- else if (RAWUCHARTEST(ptr + 1) == CHAR_LF)
+ else if (UCHAR21TEST(ptr + 1) == CHAR_LF)
{
ADD_NEW_DATA(-(state_offset + 1), 0, 1);
}
@@ -3466,7 +3466,7 @@ for (;;)
if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0)
{
- /* Advance to a known first char. */
+ /* Advance to a known first pcre_uchar (i.e. data item) */
if (has_first_char)
{
@@ -3474,12 +3474,12 @@ for (;;)
{
pcre_uchar csc;
while (current_subject < end_subject &&
- (csc = RAWUCHARTEST(current_subject)) != first_char && csc != first_char2)
+ (csc = UCHAR21TEST(current_subject)) != first_char && csc != first_char2)
current_subject++;
}
else
while (current_subject < end_subject &&
- RAWUCHARTEST(current_subject) != first_char)
+ UCHAR21TEST(current_subject) != first_char)
current_subject++;
}
@@ -3509,36 +3509,26 @@ for (;;)
ANYCRLF, and we are now at a LF, advance the match position by one
more character. */
- if (RAWUCHARTEST(current_subject - 1) == CHAR_CR &&
+ if (UCHAR21TEST(current_subject - 1) == CHAR_CR &&
(md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
current_subject < end_subject &&
- RAWUCHARTEST(current_subject) == CHAR_NL)
+ UCHAR21TEST(current_subject) == CHAR_NL)
current_subject++;
}
}
- /* Or to a non-unique first char after study */
+ /* Advance to a non-unique first pcre_uchar after study */
else if (start_bits != NULL)
{
while (current_subject < end_subject)
{
- register pcre_uint32 c = RAWUCHARTEST(current_subject);
+ register pcre_uint32 c = UCHAR21TEST(current_subject);
#ifndef COMPILE_PCRE8
if (c > 255) c = 255;
#endif
- if ((start_bits[c/8] & (1 << (c&7))) == 0)
- {
- current_subject++;
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
- /* In non 8-bit mode, the iteration will stop for
- characters > 255 at the beginning or not stop at all. */
- if (utf)
- ACROSSCHAR(current_subject < end_subject, *current_subject,
- current_subject++);
-#endif
- }
- else break;
+ if ((start_bits[c/8] & (1 << (c&7))) != 0) break;
+ current_subject++;
}
}
}
@@ -3557,19 +3547,20 @@ for (;;)
/* If the pattern was studied, a minimum subject length may be set. This
is a lower bound; no actual string of that length may actually match the
pattern. Although the value is, strictly, in characters, we treat it as
- bytes to avoid spending too much time in this optimization. */
+ in pcre_uchar units to avoid spending too much time in this optimization.
+ */
if (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0 &&
(pcre_uint32)(end_subject - current_subject) < study->minlength)
return PCRE_ERROR_NOMATCH;
- /* If req_char is set, we know that that character must appear in the
- subject for the match to succeed. If the first character is set, req_char
- must be later in the subject; otherwise the test starts at the match
- point. This optimization can save a huge amount of work in patterns with
- nested unlimited repeats that aren't going to match. Writing separate
- code for cased/caseless versions makes it go faster, as does using an
- autoincrement and backing off on a match.
+ /* If req_char is set, we know that that pcre_uchar must appear in the
+ subject for the match to succeed. If the first pcre_uchar is set,
+ req_char must be later in the subject; otherwise the test starts at the
+ match point. This optimization can save a huge amount of work in patterns
+ with nested unlimited repeats that aren't going to match. Writing
+ separate code for cased/caseless versions makes it go faster, as does
+ using an autoincrement and backing off on a match.
HOWEVER: when the subject string is very, very long, searching to its end
can take a long time, and give bad performance on quite ordinary
@@ -3589,7 +3580,7 @@ for (;;)
{
while (p < end_subject)
{
- register pcre_uint32 pp = RAWUCHARINCTEST(p);
+ register pcre_uint32 pp = UCHAR21INCTEST(p);
if (pp == req_char || pp == req_char2) { p--; break; }
}
}
@@ -3597,18 +3588,18 @@ for (;;)
{
while (p < end_subject)
{
- if (RAWUCHARINCTEST(p) == req_char) { p--; break; }
+ if (UCHAR21INCTEST(p) == req_char) { p--; break; }
}
}
- /* If we can't find the required character, break the matching loop,
+ /* If we can't find the required pcre_uchar, break the matching loop,
which will cause a return or PCRE_ERROR_NOMATCH. */
if (p >= end_subject) break;
- /* If we have found the required character, save the point where we
+ /* If we have found the required pcre_uchar, save the point where we
found it, so that we don't search again next time round the loop if
- the start hasn't passed this character yet. */
+ the start hasn't passed this point yet. */
req_char_ptr = p;
}
@@ -3665,9 +3656,9 @@ for (;;)
not contain any explicit matches for \r or \n, and the newline option is CRLF
or ANY or ANYCRLF, advance the match position by one more character. */
- if (RAWUCHARTEST(current_subject - 1) == CHAR_CR &&
+ if (UCHAR21TEST(current_subject - 1) == CHAR_CR &&
current_subject < end_subject &&
- RAWUCHARTEST(current_subject) == CHAR_NL &&
+ UCHAR21TEST(current_subject) == CHAR_NL &&
(re->flags & PCRE_HASCRORLF) == 0 &&
(md->nltype == NLTYPE_ANY ||
md->nltype == NLTYPE_ANYCRLF ||
diff --git a/src/3rdparty/pcre/pcre_exec.c b/src/3rdparty/pcre/pcre_exec.c
index 913521ff0c..b0101da351 100644
--- a/src/3rdparty/pcre/pcre_exec.c
+++ b/src/3rdparty/pcre/pcre_exec.c
@@ -6,7 +6,7 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
- Copyright (c) 1997-2013 University of Cambridge
+ Copyright (c) 1997-2014 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -134,7 +134,7 @@ pcre_uint32 c;
BOOL utf = md->utf;
if (is_subject && length > md->end_subject - p) length = md->end_subject - p;
while (length-- > 0)
- if (isprint(c = RAWUCHARINCTEST(p))) printf("%c", (char)c); else printf("\\x{%02x}", c);
+ if (isprint(c = UCHAR21INCTEST(p))) printf("%c", (char)c); else printf("\\x{%02x}", c);
}
#endif
@@ -237,8 +237,8 @@ if (caseless)
{
pcre_uint32 cc, cp;
if (eptr >= md->end_subject) return -2; /* Partial match */
- cc = RAWUCHARTEST(eptr);
- cp = RAWUCHARTEST(p);
+ cc = UCHAR21TEST(eptr);
+ cp = UCHAR21TEST(p);
if (TABLE_GET(cp, md->lcc, cp) != TABLE_GET(cc, md->lcc, cc)) return -1;
p++;
eptr++;
@@ -254,7 +254,7 @@ else
while (length-- > 0)
{
if (eptr >= md->end_subject) return -2; /* Partial match */
- if (RAWUCHARINCTEST(p) != RAWUCHARINCTEST(eptr)) return -1;
+ if (UCHAR21INCTEST(p) != UCHAR21INCTEST(eptr)) return -1;
}
}
@@ -2103,7 +2103,7 @@ for (;;)
eptr + 1 >= md->end_subject &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
- RAWUCHARTEST(eptr) == NLBLOCK->nl[0])
+ UCHAR21TEST(eptr) == NLBLOCK->nl[0])
{
md->hitend = TRUE;
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
@@ -2147,7 +2147,7 @@ for (;;)
eptr + 1 >= md->end_subject &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
- RAWUCHARTEST(eptr) == NLBLOCK->nl[0])
+ UCHAR21TEST(eptr) == NLBLOCK->nl[0])
{
md->hitend = TRUE;
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
@@ -2290,7 +2290,7 @@ for (;;)
eptr + 1 >= md->end_subject &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
- RAWUCHARTEST(eptr) == NLBLOCK->nl[0])
+ UCHAR21TEST(eptr) == NLBLOCK->nl[0])
{
md->hitend = TRUE;
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
@@ -2444,7 +2444,7 @@ for (;;)
{
SCHECK_PARTIAL();
}
- else if (RAWUCHARTEST(eptr) == CHAR_LF) eptr++;
+ else if (UCHAR21TEST(eptr) == CHAR_LF) eptr++;
break;
case CHAR_LF:
@@ -2691,16 +2691,22 @@ for (;;)
pcre_uchar *slot = md->name_table + GET2(ecode, 1) * md->name_entry_size;
ecode += 1 + 2*IMM2_SIZE;
+ /* Setting the default length first and initializing 'offset' avoids
+ compiler warnings in the REF_REPEAT code. */
+
+ length = (md->jscript_compat)? 0 : -1;
+ offset = 0;
+
while (count-- > 0)
{
offset = GET2(slot, 0) << 1;
- if (offset < offset_top && md->offset_vector[offset] >= 0) break;
+ if (offset < offset_top && md->offset_vector[offset] >= 0)
+ {
+ length = md->offset_vector[offset+1] - md->offset_vector[offset];
+ break;
+ }
slot += md->name_entry_size;
}
- if (count < 0)
- length = (md->jscript_compat)? 0 : -1;
- else
- length = md->offset_vector[offset+1] - md->offset_vector[offset];
}
goto REF_REPEAT;
@@ -3212,7 +3218,7 @@ for (;;)
CHECK_PARTIAL(); /* Not SCHECK_PARTIAL() */
RRETURN(MATCH_NOMATCH);
}
- while (length-- > 0) if (*ecode++ != RAWUCHARINC(eptr)) RRETURN(MATCH_NOMATCH);
+ while (length-- > 0) if (*ecode++ != UCHAR21INC(eptr)) RRETURN(MATCH_NOMATCH);
}
else
#endif
@@ -3252,7 +3258,7 @@ for (;;)
if (fc < 128)
{
- pcre_uint32 cc = RAWUCHAR(eptr);
+ pcre_uint32 cc = UCHAR21(eptr);
if (md->lcc[fc] != TABLE_GET(cc, md->lcc, cc)) RRETURN(MATCH_NOMATCH);
ecode++;
eptr++;
@@ -3521,7 +3527,7 @@ for (;;)
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
- cc = RAWUCHARTEST(eptr);
+ cc = UCHAR21TEST(eptr);
if (fc != cc && foc != cc) RRETURN(MATCH_NOMATCH);
eptr++;
}
@@ -3539,7 +3545,7 @@ for (;;)
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
- cc = RAWUCHARTEST(eptr);
+ cc = UCHAR21TEST(eptr);
if (fc != cc && foc != cc) RRETURN(MATCH_NOMATCH);
eptr++;
}
@@ -3556,7 +3562,7 @@ for (;;)
SCHECK_PARTIAL();
break;
}
- cc = RAWUCHARTEST(eptr);
+ cc = UCHAR21TEST(eptr);
if (fc != cc && foc != cc) break;
eptr++;
}
@@ -3583,7 +3589,7 @@ for (;;)
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
- if (fc != RAWUCHARINCTEST(eptr)) RRETURN(MATCH_NOMATCH);
+ if (fc != UCHAR21INCTEST(eptr)) RRETURN(MATCH_NOMATCH);
}
if (min == max) continue;
@@ -3600,7 +3606,7 @@ for (;;)
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
- if (fc != RAWUCHARINCTEST(eptr)) RRETURN(MATCH_NOMATCH);
+ if (fc != UCHAR21INCTEST(eptr)) RRETURN(MATCH_NOMATCH);
}
/* Control never gets here */
}
@@ -3614,7 +3620,7 @@ for (;;)
SCHECK_PARTIAL();
break;
}
- if (fc != RAWUCHARTEST(eptr)) break;
+ if (fc != UCHAR21TEST(eptr)) break;
eptr++;
}
if (possessive) continue; /* No backtracking */
@@ -4369,7 +4375,7 @@ for (;;)
eptr + 1 >= md->end_subject &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
- RAWUCHAR(eptr) == NLBLOCK->nl[0])
+ UCHAR21(eptr) == NLBLOCK->nl[0])
{
md->hitend = TRUE;
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
@@ -4411,7 +4417,7 @@ for (;;)
default: RRETURN(MATCH_NOMATCH);
case CHAR_CR:
- if (eptr < md->end_subject && RAWUCHAR(eptr) == CHAR_LF) eptr++;
+ if (eptr < md->end_subject && UCHAR21(eptr) == CHAR_LF) eptr++;
break;
case CHAR_LF:
@@ -4521,7 +4527,7 @@ for (;;)
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
- cc = RAWUCHAR(eptr);
+ cc = UCHAR21(eptr);
if (cc >= 128 || (md->ctypes[cc] & ctype_digit) == 0)
RRETURN(MATCH_NOMATCH);
eptr++;
@@ -4538,7 +4544,7 @@ for (;;)
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
- cc = RAWUCHAR(eptr);
+ cc = UCHAR21(eptr);
if (cc < 128 && (md->ctypes[cc] & ctype_space) != 0)
RRETURN(MATCH_NOMATCH);
eptr++;
@@ -4555,7 +4561,7 @@ for (;;)
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
- cc = RAWUCHAR(eptr);
+ cc = UCHAR21(eptr);
if (cc >= 128 || (md->ctypes[cc] & ctype_space) == 0)
RRETURN(MATCH_NOMATCH);
eptr++;
@@ -4572,7 +4578,7 @@ for (;;)
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
- cc = RAWUCHAR(eptr);
+ cc = UCHAR21(eptr);
if (cc < 128 && (md->ctypes[cc] & ctype_word) != 0)
RRETURN(MATCH_NOMATCH);
eptr++;
@@ -4589,7 +4595,7 @@ for (;;)
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
- cc = RAWUCHAR(eptr);
+ cc = UCHAR21(eptr);
if (cc >= 128 || (md->ctypes[cc] & ctype_word) == 0)
RRETURN(MATCH_NOMATCH);
eptr++;
@@ -5150,7 +5156,7 @@ for (;;)
{
default: RRETURN(MATCH_NOMATCH);
case CHAR_CR:
- if (eptr < md->end_subject && RAWUCHAR(eptr) == CHAR_LF) eptr++;
+ if (eptr < md->end_subject && UCHAR21(eptr) == CHAR_LF) eptr++;
break;
case CHAR_LF:
@@ -5689,7 +5695,7 @@ for (;;)
eptr + 1 >= md->end_subject &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
- RAWUCHAR(eptr) == NLBLOCK->nl[0])
+ UCHAR21(eptr) == NLBLOCK->nl[0])
{
md->hitend = TRUE;
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
@@ -5715,7 +5721,7 @@ for (;;)
eptr + 1 >= md->end_subject &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
- RAWUCHAR(eptr) == NLBLOCK->nl[0])
+ UCHAR21(eptr) == NLBLOCK->nl[0])
{
md->hitend = TRUE;
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
@@ -5772,7 +5778,7 @@ for (;;)
if (c == CHAR_CR)
{
if (++eptr >= md->end_subject) break;
- if (RAWUCHAR(eptr) == CHAR_LF) eptr++;
+ if (UCHAR21(eptr) == CHAR_LF) eptr++;
}
else
{
@@ -5935,8 +5941,8 @@ for (;;)
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
BACKCHAR(eptr);
- if (ctype == OP_ANYNL && eptr > pp && RAWUCHAR(eptr) == CHAR_NL &&
- RAWUCHAR(eptr - 1) == CHAR_CR) eptr--;
+ if (ctype == OP_ANYNL && eptr > pp && UCHAR21(eptr) == CHAR_NL &&
+ UCHAR21(eptr - 1) == CHAR_CR) eptr--;
}
}
else
@@ -6783,10 +6789,10 @@ for(;;)
if (first_char != first_char2)
while (start_match < end_subject &&
- (smc = RAWUCHARTEST(start_match)) != first_char && smc != first_char2)
+ (smc = UCHAR21TEST(start_match)) != first_char && smc != first_char2)
start_match++;
else
- while (start_match < end_subject && RAWUCHARTEST(start_match) != first_char)
+ while (start_match < end_subject && UCHAR21TEST(start_match) != first_char)
start_match++;
}
@@ -6818,7 +6824,7 @@ for(;;)
if (start_match[-1] == CHAR_CR &&
(md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
start_match < end_subject &&
- RAWUCHARTEST(start_match) == CHAR_NL)
+ UCHAR21TEST(start_match) == CHAR_NL)
start_match++;
}
}
@@ -6829,22 +6835,12 @@ for(;;)
{
while (start_match < end_subject)
{
- register pcre_uint32 c = RAWUCHARTEST(start_match);
+ register pcre_uint32 c = UCHAR21TEST(start_match);
#ifndef COMPILE_PCRE8
if (c > 255) c = 255;
#endif
- if ((start_bits[c/8] & (1 << (c&7))) == 0)
- {
- start_match++;
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
- /* In non 8-bit mode, the iteration will stop for
- characters > 255 at the beginning or not stop at all. */
- if (utf)
- ACROSSCHAR(start_match < end_subject, *start_match,
- start_match++);
-#endif
- }
- else break;
+ if ((start_bits[c/8] & (1 << (c&7))) != 0) break;
+ start_match++;
}
}
} /* Starting optimizations */
@@ -6897,7 +6893,7 @@ for(;;)
{
while (p < end_subject)
{
- register pcre_uint32 pp = RAWUCHARINCTEST(p);
+ register pcre_uint32 pp = UCHAR21INCTEST(p);
if (pp == req_char || pp == req_char2) { p--; break; }
}
}
@@ -6905,7 +6901,7 @@ for(;;)
{
while (p < end_subject)
{
- if (RAWUCHARINCTEST(p) == req_char) { p--; break; }
+ if (UCHAR21INCTEST(p) == req_char) { p--; break; }
}
}
diff --git a/src/3rdparty/pcre/pcre_globals.c b/src/3rdparty/pcre/pcre_globals.c
index d5b6286fc2..8e02bbc728 100644
--- a/src/3rdparty/pcre/pcre_globals.c
+++ b/src/3rdparty/pcre/pcre_globals.c
@@ -6,7 +6,7 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
- Copyright (c) 1997-2012 University of Cambridge
+ Copyright (c) 1997-2014 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -72,6 +72,7 @@ PCRE_EXP_DATA_DEFN void (*PUBL(free))(void *) = LocalPcreFree;
PCRE_EXP_DATA_DEFN void *(*PUBL(stack_malloc))(size_t) = LocalPcreMalloc;
PCRE_EXP_DATA_DEFN void (*PUBL(stack_free))(void *) = LocalPcreFree;
PCRE_EXP_DATA_DEFN int (*PUBL(callout))(PUBL(callout_block) *) = NULL;
+PCRE_EXP_DATA_DEFN int (*PUBL(stack_guard))(void) = NULL;
#elif !defined VPCOMPAT
PCRE_EXP_DATA_DEFN void *(*PUBL(malloc))(size_t) = malloc;
@@ -79,6 +80,7 @@ PCRE_EXP_DATA_DEFN void (*PUBL(free))(void *) = free;
PCRE_EXP_DATA_DEFN void *(*PUBL(stack_malloc))(size_t) = malloc;
PCRE_EXP_DATA_DEFN void (*PUBL(stack_free))(void *) = free;
PCRE_EXP_DATA_DEFN int (*PUBL(callout))(PUBL(callout_block) *) = NULL;
+PCRE_EXP_DATA_DEFN int (*PUBL(stack_guard))(void) = NULL;
#endif
/* End of pcre_globals.c */
diff --git a/src/3rdparty/pcre/pcre_internal.h b/src/3rdparty/pcre/pcre_internal.h
index 0b9798c554..6e915a0e45 100644
--- a/src/3rdparty/pcre/pcre_internal.h
+++ b/src/3rdparty/pcre/pcre_internal.h
@@ -7,7 +7,7 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
- Copyright (c) 1997-2013 University of Cambridge
+ Copyright (c) 1997-2014 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -316,8 +316,8 @@ start/end of string field names are. */
&(NLBLOCK->nllen), utf)) \
: \
((p) <= NLBLOCK->PSEND - NLBLOCK->nllen && \
- RAWUCHARTEST(p) == NLBLOCK->nl[0] && \
- (NLBLOCK->nllen == 1 || RAWUCHARTEST(p+1) == NLBLOCK->nl[1]) \
+ UCHAR21TEST(p) == NLBLOCK->nl[0] && \
+ (NLBLOCK->nllen == 1 || UCHAR21TEST(p+1) == NLBLOCK->nl[1]) \
) \
)
@@ -330,8 +330,8 @@ start/end of string field names are. */
&(NLBLOCK->nllen), utf)) \
: \
((p) >= NLBLOCK->PSSTART + NLBLOCK->nllen && \
- RAWUCHARTEST(p - NLBLOCK->nllen) == NLBLOCK->nl[0] && \
- (NLBLOCK->nllen == 1 || RAWUCHARTEST(p - NLBLOCK->nllen + 1) == NLBLOCK->nl[1]) \
+ UCHAR21TEST(p - NLBLOCK->nllen) == NLBLOCK->nl[0] && \
+ (NLBLOCK->nllen == 1 || UCHAR21TEST(p - NLBLOCK->nllen + 1) == NLBLOCK->nl[1]) \
) \
)
@@ -582,12 +582,27 @@ changed in future to be a fixed number of bytes or to depend on LINK_SIZE. */
#define MAX_MARK ((1u << 8) - 1)
#endif
+/* There is a proposed future special "UTF-21" mode, in which only the lowest
+21 bits of a 32-bit character are interpreted as UTF, with the remaining 11
+high-order bits available to the application for other uses. In preparation for
+the future implementation of this mode, there are macros that load a data item
+and, if in this special mode, mask it to 21 bits. These macros all have names
+starting with UCHAR21. In all other modes, including the normal 32-bit
+library, the macros all have the same simple definitions. When the new mode is
+implemented, it is expected that these definitions will be varied appropriately
+using #ifdef when compiling the library that supports the special mode. */
+
+#define UCHAR21(eptr) (*(eptr))
+#define UCHAR21TEST(eptr) (*(eptr))
+#define UCHAR21INC(eptr) (*(eptr)++)
+#define UCHAR21INCTEST(eptr) (*(eptr)++)
+
/* When UTF encoding is being used, a character is no longer just a single
-byte. The macros for character handling generate simple sequences when used in
-character-mode, and more complicated ones for UTF characters. GETCHARLENTEST
-and other macros are not used when UTF is not supported, so they are not
-defined. To make sure they can never even appear when UTF support is omitted,
-we don't even define them. */
+byte in 8-bit mode or a single short in 16-bit mode. The macros for character
+handling generate simple sequences when used in the basic mode, and more
+complicated ones for UTF characters. GETCHARLENTEST and other macros are not
+used when UTF is not supported. To make sure they can never even appear when
+UTF support is omitted, we don't even define them. */
#ifndef SUPPORT_UTF
@@ -600,10 +615,6 @@ we don't even define them. */
#define GETCHARINC(c, eptr) c = *eptr++;
#define GETCHARINCTEST(c, eptr) c = *eptr++;
#define GETCHARLEN(c, eptr, len) c = *eptr;
-#define RAWUCHAR(eptr) (*(eptr))
-#define RAWUCHARINC(eptr) (*(eptr)++)
-#define RAWUCHARTEST(eptr) (*(eptr))
-#define RAWUCHARINCTEST(eptr) (*(eptr)++)
/* #define GETCHARLENTEST(c, eptr, len) */
/* #define BACKCHAR(eptr) */
/* #define FORWARDCHAR(eptr) */
@@ -776,30 +787,6 @@ do not know if we are in UTF-8 mode. */
c = *eptr; \
if (utf && c >= 0xc0) GETUTF8LEN(c, eptr, len);
-/* Returns the next uchar, not advancing the pointer. This is called when
-we know we are in UTF mode. */
-
-#define RAWUCHAR(eptr) \
- (*(eptr))
-
-/* Returns the next uchar, advancing the pointer. This is called when
-we know we are in UTF mode. */
-
-#define RAWUCHARINC(eptr) \
- (*((eptr)++))
-
-/* Returns the next uchar, testing for UTF mode, and not advancing the
-pointer. */
-
-#define RAWUCHARTEST(eptr) \
- (*(eptr))
-
-/* Returns the next uchar, testing for UTF mode, advancing the
-pointer. */
-
-#define RAWUCHARINCTEST(eptr) \
- (*((eptr)++))
-
/* If the pointer is not at the start of a character, move it back until
it is. This is called only in UTF-8 mode - we don't put a test within the macro
because almost all calls are already within a block of UTF-8 only code. */
@@ -895,30 +882,6 @@ we do not know if we are in UTF-16 mode. */
c = *eptr; \
if (utf && (c & 0xfc00) == 0xd800) GETUTF16LEN(c, eptr, len);
-/* Returns the next uchar, not advancing the pointer. This is called when
-we know we are in UTF mode. */
-
-#define RAWUCHAR(eptr) \
- (*(eptr))
-
-/* Returns the next uchar, advancing the pointer. This is called when
-we know we are in UTF mode. */
-
-#define RAWUCHARINC(eptr) \
- (*((eptr)++))
-
-/* Returns the next uchar, testing for UTF mode, and not advancing the
-pointer. */
-
-#define RAWUCHARTEST(eptr) \
- (*(eptr))
-
-/* Returns the next uchar, testing for UTF mode, advancing the
-pointer. */
-
-#define RAWUCHARINCTEST(eptr) \
- (*((eptr)++))
-
/* If the pointer is not at the start of a character, move it back until
it is. This is called only in UTF-16 mode - we don't put a test within the
macro because almost all calls are already within a block of UTF-16 only
@@ -980,30 +943,6 @@ This is called when we do not know if we are in UTF-32 mode. */
#define GETCHARLENTEST(c, eptr, len) \
GETCHARTEST(c, eptr)
-/* Returns the next uchar, not advancing the pointer. This is called when
-we know we are in UTF mode. */
-
-#define RAWUCHAR(eptr) \
- (*(eptr))
-
-/* Returns the next uchar, advancing the pointer. This is called when
-we know we are in UTF mode. */
-
-#define RAWUCHARINC(eptr) \
- (*((eptr)++))
-
-/* Returns the next uchar, testing for UTF mode, and not advancing the
-pointer. */
-
-#define RAWUCHARTEST(eptr) \
- (*(eptr))
-
-/* Returns the next uchar, testing for UTF mode, advancing the
-pointer. */
-
-#define RAWUCHARINCTEST(eptr) \
- (*((eptr)++))
-
/* If the pointer is not at the start of a character, move it back until
it is. This is called only in UTF-32 mode - we don't put a test within the
macro because almost all calls are already within a block of UTF-32 only
@@ -1874,8 +1813,9 @@ table. */
/* Flag bits and data types for the extended class (OP_XCLASS) for classes that
contain characters with values greater than 255. */
-#define XCL_NOT 0x01 /* Flag: this is a negative class */
-#define XCL_MAP 0x02 /* Flag: a 32-byte map is present */
+#define XCL_NOT 0x01 /* Flag: this is a negative class */
+#define XCL_MAP 0x02 /* Flag: a 32-byte map is present */
+#define XCL_HASPROP 0x04 /* Flag: property checks are present. */
#define XCL_END 0 /* Marks end of individual items */
#define XCL_SINGLE 1 /* Single item (one multibyte char) follows */
@@ -2341,7 +2281,7 @@ enum { ERR0, ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9,
ERR50, ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59,
ERR60, ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69,
ERR70, ERR71, ERR72, ERR73, ERR74, ERR75, ERR76, ERR77, ERR78, ERR79,
- ERR80, ERR81, ERR82, ERR83, ERR84, ERRCOUNT };
+ ERR80, ERR81, ERR82, ERR83, ERR84, ERR85, ERRCOUNT };
/* JIT compiling modes. The function list is indexed by them. */
diff --git a/src/3rdparty/pcre/pcre_jit_compile.c b/src/3rdparty/pcre/pcre_jit_compile.c
index a318708b46..42a0a2278e 100644
--- a/src/3rdparty/pcre/pcre_jit_compile.c
+++ b/src/3rdparty/pcre/pcre_jit_compile.c
@@ -179,11 +179,12 @@ typedef struct jit_arguments {
typedef struct executable_functions {
void *executable_funcs[JIT_NUMBER_OF_COMPILE_MODES];
+ sljit_uw *read_only_data[JIT_NUMBER_OF_COMPILE_MODES];
+ sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES];
PUBL(jit_callback) callback;
void *userdata;
pcre_uint32 top_bracket;
pcre_uint32 limit_match;
- sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES];
} executable_functions;
typedef struct jump_list {
@@ -197,6 +198,12 @@ typedef struct stub_list {
struct stub_list *next;
} stub_list;
+typedef struct label_addr_list {
+ struct sljit_label *label;
+ sljit_uw *addr;
+ struct label_addr_list *next;
+} label_addr_list;
+
enum frame_types {
no_frame = -1,
no_stack = -2
@@ -306,7 +313,7 @@ typedef struct then_trap_backtrack {
int framesize;
} then_trap_backtrack;
-#define MAX_RANGE_SIZE 6
+#define MAX_RANGE_SIZE 4
typedef struct compiler_common {
/* The sljit ceneric compiler. */
@@ -315,6 +322,12 @@ typedef struct compiler_common {
pcre_uchar *start;
/* Maps private data offset to each opcode. */
sljit_si *private_data_ptrs;
+ /* This read-only data is available during runtime. */
+ sljit_uw *read_only_data;
+ /* The total size of the read-only data. */
+ sljit_uw read_only_data_size;
+ /* The next free entry of the read_only_data. */
+ sljit_uw *read_only_data_ptr;
/* Tells whether the capturing bracket is optimized. */
pcre_uint8 *optimized_cbracket;
/* Tells whether the starting offset is a target of then. */
@@ -349,6 +362,8 @@ typedef struct compiler_common {
sljit_sw lcc;
/* Mode can be PCRE_STUDY_JIT_COMPILE and others. */
int mode;
+ /* TRUE, when minlength is greater than 0. */
+ BOOL might_be_empty;
/* \K is found in the pattern. */
BOOL has_set_som;
/* (*SKIP:arg) is found in the pattern. */
@@ -363,13 +378,16 @@ typedef struct compiler_common {
BOOL positive_assert;
/* Newline control. */
int nltype;
+ pcre_uint32 nlmax;
+ pcre_uint32 nlmin;
int newline;
int bsr_nltype;
+ pcre_uint32 bsr_nlmax;
+ pcre_uint32 bsr_nlmin;
/* Dollar endonly. */
int endonly;
/* Tables. */
sljit_sw ctypes;
- int digits[2 + MAX_RANGE_SIZE];
/* Named capturing brackets. */
pcre_uchar *name_table;
sljit_sw name_count;
@@ -380,7 +398,9 @@ typedef struct compiler_common {
struct sljit_label *quit_label;
struct sljit_label *forced_quit_label;
struct sljit_label *accept_label;
+ struct sljit_label *ff_newline_shortcut;
stub_list *stubs;
+ label_addr_list *label_addrs;
recurse_entry *entries;
recurse_entry *currententry;
jump_list *partialmatch;
@@ -404,10 +424,9 @@ typedef struct compiler_common {
#ifdef SUPPORT_UCP
BOOL use_ucp;
#endif
-#ifndef COMPILE_PCRE32
- jump_list *utfreadchar;
-#endif
#ifdef COMPILE_PCRE8
+ jump_list *utfreadchar;
+ jump_list *utfreadchar16;
jump_list *utfreadtype8;
#endif
#endif /* SUPPORT_UTF */
@@ -524,6 +543,8 @@ the start pointers when the end of the capturing group has not yet reached. */
#define GET_LOCAL_BASE(dst, dstw, offset) \
sljit_get_local_base(compiler, (dst), (dstw), (offset))
+#define READ_CHAR_MAX 0x7fffffff
+
static pcre_uchar* bracketend(pcre_uchar* cc)
{
SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND));
@@ -533,6 +554,25 @@ cc += 1 + LINK_SIZE;
return cc;
}
+static int no_alternatives(pcre_uchar* cc)
+{
+int count = 0;
+SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND));
+do
+ {
+ cc += GET(cc, 1);
+ count++;
+ }
+while (*cc == OP_ALT);
+SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS);
+return count;
+}
+
+static int ones_in_half_byte[16] = {
+ /* 0 */ 0, 1, 1, 2, /* 4 */ 1, 2, 2, 3,
+ /* 8 */ 1, 2, 2, 3, /* 12 */ 2, 3, 3, 4
+};
+
/* Functions whose might need modification for all new supported opcodes:
next_opcode
check_opcode_types
@@ -752,6 +792,7 @@ while (cc < ccend)
{
case OP_SET_SOM:
common->has_set_som = TRUE;
+ common->might_be_empty = TRUE;
cc += 1;
break;
@@ -761,6 +802,16 @@ while (cc < ccend)
cc += 1 + IMM2_SIZE;
break;
+ case OP_BRA:
+ case OP_CBRA:
+ case OP_SBRA:
+ case OP_SCBRA:
+ count = no_alternatives(cc);
+ if (count > 4)
+ common->read_only_data_size += count * sizeof(sljit_uw);
+ cc += 1 + LINK_SIZE + (*cc == OP_CBRA || *cc == OP_SCBRA ? IMM2_SIZE : 0);
+ break;
+
case OP_CBRAPOS:
case OP_SCBRAPOS:
common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] = 0;
@@ -2019,6 +2070,21 @@ while (list_item)
common->stubs = NULL;
}
+static void add_label_addr(compiler_common *common)
+{
+DEFINE_COMPILER;
+label_addr_list *label_addr;
+
+label_addr = sljit_alloc_memory(compiler, sizeof(label_addr_list));
+if (label_addr == NULL)
+ return;
+label_addr->label = LABEL();
+label_addr->addr = common->read_only_data_ptr;
+label_addr->next = common->label_addrs;
+common->label_addrs = label_addr;
+common->read_only_data_ptr++;
+}
+
static SLJIT_INLINE void count_match(compiler_common *common)
{
DEFINE_COMPILER;
@@ -2457,107 +2523,290 @@ else
JUMPHERE(jump);
}
-static void read_char(compiler_common *common)
+static void peek_char(compiler_common *common, pcre_uint32 max)
{
-/* Reads the character into TMP1, updates STR_PTR.
+/* Reads the character into TMP1, keeps STR_PTR.
Does not check STR_END. TMP2 Destroyed. */
DEFINE_COMPILER;
#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
struct sljit_jump *jump;
#endif
+SLJIT_UNUSED_ARG(max);
+
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
if (common->utf)
{
-#if defined COMPILE_PCRE8
+ if (max < 128) return;
+
jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
-#elif defined COMPILE_PCRE16
- jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
-#endif /* COMPILE_PCRE[8|16] */
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL));
+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
JUMPHERE(jump);
}
#endif /* SUPPORT_UTF && !COMPILE_PCRE32 */
+
+#if defined SUPPORT_UTF && defined COMPILE_PCRE16
+if (common->utf)
+ {
+ if (max < 0xd800) return;
+
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1);
+ /* TMP2 contains the high surrogate. */
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x40);
+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);
+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3ff);
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+ JUMPHERE(jump);
+ }
+#endif
+}
+
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+
+static BOOL is_char7_bitset(const pcre_uint8 *bitset, BOOL nclass)
+{
+/* Tells whether the character codes below 128 are enough
+to determine a match. */
+const pcre_uint8 value = nclass ? 0xff : 0;
+const pcre_uint8* end = bitset + 32;
+
+bitset += 16;
+do
+ {
+ if (*bitset++ != value)
+ return FALSE;
+ }
+while (bitset < end);
+return TRUE;
+}
+
+static void read_char7_type(compiler_common *common, BOOL full_read)
+{
+/* Reads the precise character type of a character into TMP1, if the character
+is less than 128. Otherwise it returns with zero. Does not check STR_END. The
+full_read argument tells whether characters above max are accepted or not. */
+DEFINE_COMPILER;
+struct sljit_jump *jump;
+
+SLJIT_ASSERT(common->utf);
+
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
+OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
+
+if (full_read)
+ {
+ jump = CMP(SLJIT_C_LESS, TMP2, 0, SLJIT_IMM, 0xc0);
+ OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+ JUMPHERE(jump);
+ }
}
-static void peek_char(compiler_common *common)
+#endif /* SUPPORT_UTF && COMPILE_PCRE8 */
+
+static void read_char_range(compiler_common *common, pcre_uint32 min, pcre_uint32 max, BOOL update_str_ptr)
{
-/* Reads the character into TMP1, keeps STR_PTR.
-Does not check STR_END. TMP2 Destroyed. */
+/* Reads the precise value of a character into TMP1, if the character is
+between min and max (c >= min && c <= max). Otherwise it returns with a value
+outside the range. Does not check STR_END. */
DEFINE_COMPILER;
#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
struct sljit_jump *jump;
#endif
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+struct sljit_jump *jump2;
+#endif
-OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+SLJIT_UNUSED_ARG(update_str_ptr);
+SLJIT_UNUSED_ARG(min);
+SLJIT_UNUSED_ARG(max);
+SLJIT_ASSERT(min <= max);
+
+OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
if (common->utf)
{
-#if defined COMPILE_PCRE8
+ if (max < 128 && !update_str_ptr) return;
+
jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
-#elif defined COMPILE_PCRE16
- jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
-#endif /* COMPILE_PCRE[8|16] */
- add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL));
- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+ if (min >= 0x10000)
+ {
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xf0);
+ if (update_str_ptr)
+ OP1(SLJIT_MOV_UB, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+ jump2 = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 0x7);
+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
+ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));
+ if (!update_str_ptr)
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));
+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
+ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+ JUMPHERE(jump2);
+ if (update_str_ptr)
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0);
+ }
+ else if (min >= 0x800 && max <= 0xffff)
+ {
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xe0);
+ if (update_str_ptr)
+ OP1(SLJIT_MOV_UB, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+ jump2 = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 0xf);
+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
+ if (!update_str_ptr)
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
+ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+ JUMPHERE(jump2);
+ if (update_str_ptr)
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0);
+ }
+ else if (max >= 0x800)
+ add_jump(compiler, (max < 0x10000) ? &common->utfreadchar16 : &common->utfreadchar, JUMP(SLJIT_FAST_CALL));
+ else if (max < 128)
+ {
+ OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+ }
+ else
+ {
+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+ if (!update_str_ptr)
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ else
+ OP1(SLJIT_MOV_UB, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
+ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+ if (update_str_ptr)
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0);
+ }
JUMPHERE(jump);
}
-#endif /* SUPPORT_UTF && !COMPILE_PCRE32 */
+#endif
+
+#if defined SUPPORT_UTF && defined COMPILE_PCRE16
+if (common->utf)
+ {
+ if (max >= 0x10000)
+ {
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1);
+ /* TMP2 contains the high surrogate. */
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x40);
+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3ff);
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+ JUMPHERE(jump);
+ return;
+ }
+
+ if (max < 0xd800 && !update_str_ptr) return;
+
+ /* Skip low surrogate if necessary. */
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1);
+ if (update_str_ptr)
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ if (max >= 0xd800)
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0x10000);
+ JUMPHERE(jump);
+ }
+#endif
+}
+
+static SLJIT_INLINE void read_char(compiler_common *common)
+{
+read_char_range(common, 0, READ_CHAR_MAX, TRUE);
}
-static void read_char8_type(compiler_common *common)
+static void read_char8_type(compiler_common *common, BOOL update_str_ptr)
{
/* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */
DEFINE_COMPILER;
-#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
struct sljit_jump *jump;
#endif
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+struct sljit_jump *jump2;
+#endif
-#ifdef SUPPORT_UTF
+SLJIT_UNUSED_ARG(update_str_ptr);
+
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
if (common->utf)
{
- OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
-#if defined COMPILE_PCRE8
/* This can be an extra read in some situations, but hopefully
it is needed in most cases. */
OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
jump = CMP(SLJIT_C_LESS, TMP2, 0, SLJIT_IMM, 0xc0);
- add_jump(compiler, &common->utfreadtype8, JUMP(SLJIT_FAST_CALL));
- JUMPHERE(jump);
-#elif defined COMPILE_PCRE16
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
- jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
- OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
- JUMPHERE(jump);
- /* Skip low surrogate if necessary. */
- OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xfc00);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0xd800);
- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
- OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
-#elif defined COMPILE_PCRE32
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
- jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
- OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
+ if (!update_str_ptr)
+ {
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
+ OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
+ jump2 = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
+ JUMPHERE(jump2);
+ }
+ else
+ add_jump(compiler, &common->utfreadtype8, JUMP(SLJIT_FAST_CALL));
JUMPHERE(jump);
-#endif /* COMPILE_PCRE[8|16|32] */
return;
}
-#endif /* SUPPORT_UTF */
-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#endif /* SUPPORT_UTF && COMPILE_PCRE8 */
+
+#if !defined COMPILE_PCRE8
/* The ctypes array contains only 256 values. */
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
#endif
OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if !defined COMPILE_PCRE8
JUMPHERE(jump);
#endif
+
+#if defined SUPPORT_UTF && defined COMPILE_PCRE16
+if (common->utf && update_str_ptr)
+ {
+ /* Skip low surrogate if necessary. */
+ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xd800);
+ jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ JUMPHERE(jump);
+ }
+#endif /* SUPPORT_UTF && COMPILE_PCRE16 */
}
static void skip_char_back(compiler_common *common)
@@ -2595,28 +2844,35 @@ if (common->utf)
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
}
-static void check_newlinechar(compiler_common *common, int nltype, jump_list **backtracks, BOOL jumpiftrue)
+static void check_newlinechar(compiler_common *common, int nltype, jump_list **backtracks, BOOL jumpifmatch)
{
/* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */
DEFINE_COMPILER;
+struct sljit_jump *jump;
if (nltype == NLTYPE_ANY)
{
add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
- add_jump(compiler, backtracks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
+ add_jump(compiler, backtracks, JUMP(jumpifmatch ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
}
else if (nltype == NLTYPE_ANYCRLF)
{
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_CR);
- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
- OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
- add_jump(compiler, backtracks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
+ if (jumpifmatch)
+ {
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR));
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));
+ }
+ else
+ {
+ jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));
+ JUMPHERE(jump);
+ }
}
else
{
SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256);
- add_jump(compiler, backtracks, CMP(jumpiftrue ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
+ add_jump(compiler, backtracks, CMP(jumpifmatch ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
}
}
@@ -2626,58 +2882,84 @@ else
static void do_utfreadchar(compiler_common *common)
{
/* Fast decoding a UTF-8 character. TMP1 contains the first byte
-of the character (>= 0xc0). Return char value in TMP1, length - 1 in TMP2. */
+of the character (>= 0xc0). Return char value in TMP1, length in TMP2. */
DEFINE_COMPILER;
struct sljit_jump *jump;
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+
/* Searching for the first zero. */
-OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
+OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
jump = JUMP(SLJIT_C_NOT_ZERO);
/* Two byte sequence. */
-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
-OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1f);
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(2));
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+JUMPHERE(jump);
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
+OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x800);
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
-OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
-sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
-JUMPHERE(jump);
-OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10);
+OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10000);
jump = JUMP(SLJIT_C_NOT_ZERO);
/* Three byte sequence. */
-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
-OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0f);
-OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 12);
-OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
-OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
-OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
-OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
-OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(2));
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(3));
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
-JUMPHERE(jump);
/* Four byte sequence. */
-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
-OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x07);
-OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 18);
+JUMPHERE(jump);
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));
+OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000);
+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(4));
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+
+static void do_utfreadchar16(compiler_common *common)
+{
+/* Fast decoding a UTF-8 character. TMP1 contains the first byte
+of the character (>= 0xc0). Return value in TMP1. */
+DEFINE_COMPILER;
+struct sljit_jump *jump;
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(3));
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));
+
+/* Searching for the first zero. */
+OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
+jump = JUMP(SLJIT_C_NOT_ZERO);
+/* Two byte sequence. */
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+JUMPHERE(jump);
+OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x400);
+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_NOT_ZERO);
+/* This code runs only in 8 bit mode. No need to shift the value. */
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
+OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x800);
+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
-OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(3));
+/* Three byte sequence. */
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
}
@@ -2697,53 +2979,27 @@ jump = JUMP(SLJIT_C_NOT_ZERO);
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x1f);
+/* The upper 5 bits are known at this point. */
+compare = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 0x3);
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0);
-compare = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
JUMPHERE(compare);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
-JUMPHERE(jump);
/* We only have types for characters less than 256. */
-OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0);
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
-OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
-sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
-}
-
-#elif defined COMPILE_PCRE16
-
-static void do_utfreadchar(compiler_common *common)
-{
-/* Fast decoding a UTF-16 character. TMP1 contains the first 16 bit char
-of the character (>= 0xd800). Return char value in TMP1, length - 1 in TMP2. */
-DEFINE_COMPILER;
-struct sljit_jump *jump;
-
-sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
-jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xdc00);
-/* Do nothing, only return. */
-sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
-
JUMPHERE(jump);
-/* Combine two 16 bit characters. */
-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
-OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3ff);
-OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 10);
-OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3ff);
-OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
-OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000);
+OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
}
-#endif /* COMPILE_PCRE[8|16] */
+#endif /* COMPILE_PCRE8 */
#endif /* SUPPORT_UTF */
@@ -2818,7 +3074,7 @@ if (firstline)
mainloop = LABEL();
/* Continual stores does not cause data dependency. */
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0);
- read_char(common);
+ read_char_range(common, common->nlmin, common->nlmax, TRUE);
check_newlinechar(common, common->nltype, &newline, TRUE);
CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop);
JUMPHERE(end);
@@ -2894,37 +3150,66 @@ if (newlinecheck)
return mainloop;
}
-#define MAX_N_CHARS 3
+#define MAX_N_CHARS 16
+#define MAX_N_BYTES 8
-static SLJIT_INLINE BOOL fast_forward_first_n_chars(compiler_common *common, BOOL firstline)
+static SLJIT_INLINE void add_prefix_byte(pcre_uint8 byte, pcre_uint8 *bytes)
{
-DEFINE_COMPILER;
-struct sljit_label *start;
-struct sljit_jump *quit;
-pcre_uint32 chars[MAX_N_CHARS * 2];
-pcre_uchar *cc = common->start + 1 + LINK_SIZE;
-int location = 0;
-pcre_int32 len, c, bit, caseless;
-int must_stop;
+pcre_uint8 len = bytes[0];
+int i;
-/* We do not support alternatives now. */
-if (*(common->start + GET(common->start, 1)) == OP_ALT)
- return FALSE;
+if (len == 255)
+ return;
+
+if (len == 0)
+ {
+ bytes[0] = 1;
+ bytes[1] = byte;
+ return;
+ }
+
+for (i = len; i > 0; i--)
+ if (bytes[i] == byte)
+ return;
+if (len >= MAX_N_BYTES - 1)
+ {
+ bytes[0] = 255;
+ return;
+ }
+
+len++;
+bytes[len] = byte;
+bytes[0] = len;
+}
+
+static int scan_prefix(compiler_common *common, pcre_uchar *cc, pcre_uint32 *chars, pcre_uint8 *bytes, int max_chars)
+{
+/* Recursive function, which scans prefix literals. */
+BOOL last, any, caseless;
+int len, repeat, len_save, consumed = 0;
+pcre_uint32 chr, mask;
+pcre_uchar *alternative, *cc_save, *oc;
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+pcre_uchar othercase[8];
+#elif defined SUPPORT_UTF && defined COMPILE_PCRE16
+pcre_uchar othercase[2];
+#else
+pcre_uchar othercase[1];
+#endif
+
+repeat = 1;
while (TRUE)
{
- caseless = 0;
- must_stop = 1;
- switch(*cc)
+ last = TRUE;
+ any = FALSE;
+ caseless = FALSE;
+ switch (*cc)
{
- case OP_CHAR:
- must_stop = 0;
- cc++;
- break;
-
case OP_CHARI:
- caseless = 1;
- must_stop = 0;
+ caseless = TRUE;
+ case OP_CHAR:
+ last = FALSE;
cc++;
break;
@@ -2943,125 +3228,546 @@ while (TRUE)
cc++;
continue;
+ case OP_ASSERT:
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ cc = bracketend(cc);
+ continue;
+
+ case OP_PLUSI:
+ case OP_MINPLUSI:
+ case OP_POSPLUSI:
+ caseless = TRUE;
case OP_PLUS:
case OP_MINPLUS:
case OP_POSPLUS:
cc++;
break;
+ case OP_EXACTI:
+ caseless = TRUE;
case OP_EXACT:
+ repeat = GET2(cc, 1);
+ last = FALSE;
cc += 1 + IMM2_SIZE;
break;
- case OP_PLUSI:
- case OP_MINPLUSI:
- case OP_POSPLUSI:
- caseless = 1;
+ case OP_QUERYI:
+ case OP_MINQUERYI:
+ case OP_POSQUERYI:
+ caseless = TRUE;
+ case OP_QUERY:
+ case OP_MINQUERY:
+ case OP_POSQUERY:
+ len = 1;
cc++;
+#ifdef SUPPORT_UTF
+ if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc);
+#endif
+ max_chars = scan_prefix(common, cc + len, chars, bytes, max_chars);
+ if (max_chars == 0)
+ return consumed;
+ last = FALSE;
break;
- case OP_EXACTI:
- caseless = 1;
+ case OP_KET:
+ cc += 1 + LINK_SIZE;
+ continue;
+
+ case OP_ALT:
+ cc += GET(cc, 1);
+ continue;
+
+ case OP_ONCE:
+ case OP_ONCE_NC:
+ case OP_BRA:
+ case OP_BRAPOS:
+ case OP_CBRA:
+ case OP_CBRAPOS:
+ alternative = cc + GET(cc, 1);
+ while (*alternative == OP_ALT)
+ {
+ max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, bytes, max_chars);
+ if (max_chars == 0)
+ return consumed;
+ alternative += GET(alternative, 1);
+ }
+
+ if (*cc == OP_CBRA || *cc == OP_CBRAPOS)
+ cc += IMM2_SIZE;
+ cc += 1 + LINK_SIZE;
+ continue;
+
+ case OP_CLASS:
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+ if (common->utf && !is_char7_bitset((const pcre_uint8 *)(cc + 1), FALSE)) return consumed;
+#endif
+ any = TRUE;
+ cc += 1 + 32 / sizeof(pcre_uchar);
+ break;
+
+ case OP_NCLASS:
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (common->utf) return consumed;
+#endif
+ any = TRUE;
+ cc += 1 + 32 / sizeof(pcre_uchar);
+ break;
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ case OP_XCLASS:
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (common->utf) return consumed;
+#endif
+ any = TRUE;
+ cc += GET(cc, 1);
+ break;
+#endif
+
+ case OP_DIGIT:
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+ if (common->utf && !is_char7_bitset((const pcre_uint8 *)common->ctypes - cbit_length + cbit_digit, FALSE))
+ return consumed;
+#endif
+ any = TRUE;
+ cc++;
+ break;
+
+ case OP_WHITESPACE:
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+ if (common->utf && !is_char7_bitset((const pcre_uint8 *)common->ctypes - cbit_length + cbit_space, FALSE))
+ return consumed;
+#endif
+ any = TRUE;
+ cc++;
+ break;
+
+ case OP_WORDCHAR:
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+ if (common->utf && !is_char7_bitset((const pcre_uint8 *)common->ctypes - cbit_length + cbit_word, FALSE))
+ return consumed;
+#endif
+ any = TRUE;
+ cc++;
+ break;
+
+ case OP_NOT:
+ case OP_NOTI:
+ cc++;
+ /* Fall through. */
+ case OP_NOT_DIGIT:
+ case OP_NOT_WHITESPACE:
+ case OP_NOT_WORDCHAR:
+ case OP_ANY:
+ case OP_ALLANY:
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (common->utf) return consumed;
+#endif
+ any = TRUE;
+ cc++;
+ break;
+
+#ifdef SUPPORT_UCP
+ case OP_NOTPROP:
+ case OP_PROP:
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (common->utf) return consumed;
+#endif
+ any = TRUE;
+ cc += 1 + 2;
+ break;
+#endif
+
+ case OP_TYPEEXACT:
+ repeat = GET2(cc, 1);
cc += 1 + IMM2_SIZE;
+ continue;
+
+ case OP_NOTEXACT:
+ case OP_NOTEXACTI:
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (common->utf) return consumed;
+#endif
+ any = TRUE;
+ repeat = GET2(cc, 1);
+ cc += 1 + IMM2_SIZE + 1;
break;
default:
- must_stop = 2;
- break;
+ return consumed;
}
- if (must_stop == 2)
- break;
+ if (any)
+ {
+#if defined COMPILE_PCRE8
+ mask = 0xff;
+#elif defined COMPILE_PCRE16
+ mask = 0xffff;
+#elif defined COMPILE_PCRE32
+ mask = 0xffffffff;
+#else
+ SLJIT_ASSERT_STOP();
+#endif
+
+ do
+ {
+ chars[0] = mask;
+ chars[1] = mask;
+ bytes[0] = 255;
+
+ consumed++;
+ if (--max_chars == 0)
+ return consumed;
+ chars += 2;
+ bytes += MAX_N_BYTES;
+ }
+ while (--repeat > 0);
+
+ repeat = 1;
+ continue;
+ }
len = 1;
#ifdef SUPPORT_UTF
- if (common->utf && HAS_EXTRALEN(cc[0])) len += GET_EXTRALEN(cc[0]);
+ if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc);
#endif
if (caseless && char_has_othercase(common, cc))
{
- caseless = char_get_othercase_bit(common, cc);
- if (caseless == 0)
- return FALSE;
-#ifdef COMPILE_PCRE8
- caseless = ((caseless & 0xff) << 8) | (len - (caseless >> 8));
-#else
- if ((caseless & 0x100) != 0)
- caseless = ((caseless & 0xff) << 16) | (len - (caseless >> 9));
+#ifdef SUPPORT_UTF
+ if (common->utf)
+ {
+ GETCHAR(chr, cc);
+ if ((int)PRIV(ord2utf)(char_othercase(common, chr), othercase) != len)
+ return consumed;
+ }
else
- caseless = ((caseless & 0xff) << 8) | (len - (caseless >> 9));
#endif
+ {
+ chr = *cc;
+ othercase[0] = TABLE_GET(chr, common->fcc, chr);
+ }
}
else
- caseless = 0;
+ caseless = FALSE;
- while (len > 0 && location < MAX_N_CHARS * 2)
+ len_save = len;
+ cc_save = cc;
+ while (TRUE)
{
- c = *cc;
- bit = 0;
- if (len == (caseless & 0xff))
+ oc = othercase;
+ do
{
- bit = caseless >> 8;
- c |= bit;
+ chr = *cc;
+#ifdef COMPILE_PCRE32
+ if (SLJIT_UNLIKELY(chr == NOTACHAR))
+ return consumed;
+#endif
+ add_prefix_byte((pcre_uint8)chr, bytes);
+
+ mask = 0;
+ if (caseless)
+ {
+ add_prefix_byte((pcre_uint8)*oc, bytes);
+ mask = *cc ^ *oc;
+ chr |= mask;
+ }
+
+#ifdef COMPILE_PCRE32
+ if (chars[0] == NOTACHAR && chars[1] == 0)
+#else
+ if (chars[0] == NOTACHAR)
+#endif
+ {
+ chars[0] = chr;
+ chars[1] = mask;
+ }
+ else
+ {
+ mask |= chars[0] ^ chr;
+ chr |= mask;
+ chars[0] = chr;
+ chars[1] |= mask;
+ }
+
+ len--;
+ consumed++;
+ if (--max_chars == 0)
+ return consumed;
+ chars += 2;
+ bytes += MAX_N_BYTES;
+ cc++;
+ oc++;
}
+ while (len > 0);
- chars[location] = c;
- chars[location + 1] = bit;
+ if (--repeat == 0)
+ break;
- len--;
- location += 2;
- cc++;
+ len = len_save;
+ cc = cc_save;
+ }
+
+ repeat = 1;
+ if (last)
+ return consumed;
+ }
+}
+
+static SLJIT_INLINE BOOL fast_forward_first_n_chars(compiler_common *common, BOOL firstline)
+{
+DEFINE_COMPILER;
+struct sljit_label *start;
+struct sljit_jump *quit;
+pcre_uint32 chars[MAX_N_CHARS * 2];
+pcre_uint8 bytes[MAX_N_CHARS * MAX_N_BYTES];
+pcre_uint8 ones[MAX_N_CHARS];
+int offsets[3];
+pcre_uint32 mask;
+pcre_uint8 *byte_set, *byte_set_end;
+int i, max, from;
+int range_right = -1, range_len = 3 - 1;
+sljit_ub *update_table = NULL;
+BOOL in_range;
+
+/* This is even TRUE, if both are NULL. */
+SLJIT_ASSERT(common->read_only_data_ptr == common->read_only_data);
+
+for (i = 0; i < MAX_N_CHARS; i++)
+ {
+ chars[i << 1] = NOTACHAR;
+ chars[(i << 1) + 1] = 0;
+ bytes[i * MAX_N_BYTES] = 0;
+ }
+
+max = scan_prefix(common, common->start, chars, bytes, MAX_N_CHARS);
+
+if (max <= 1)
+ return FALSE;
+
+for (i = 0; i < max; i++)
+ {
+ mask = chars[(i << 1) + 1];
+ ones[i] = ones_in_half_byte[mask & 0xf];
+ mask >>= 4;
+ while (mask != 0)
+ {
+ ones[i] += ones_in_half_byte[mask & 0xf];
+ mask >>= 4;
+ }
+ }
+
+in_range = FALSE;
+from = 0; /* Prevent compiler "uninitialized" warning */
+for (i = 0; i <= max; i++)
+ {
+ if (in_range && (i - from) > range_len && (bytes[(i - 1) * MAX_N_BYTES] <= 4))
+ {
+ range_len = i - from;
+ range_right = i - 1;
+ }
+
+ if (i < max && bytes[i * MAX_N_BYTES] < 255)
+ {
+ if (!in_range)
+ {
+ in_range = TRUE;
+ from = i;
+ }
+ }
+ else if (in_range)
+ in_range = FALSE;
+ }
+
+if (range_right >= 0)
+ {
+ /* Since no data is consumed (see the assert in the beginning
+ of this function), this space can be reallocated. */
+ if (common->read_only_data)
+ SLJIT_FREE(common->read_only_data);
+
+ common->read_only_data_size += 256;
+ common->read_only_data = (sljit_uw *)SLJIT_MALLOC(common->read_only_data_size);
+ if (common->read_only_data == NULL)
+ return TRUE;
+
+ update_table = (sljit_ub *)common->read_only_data;
+ common->read_only_data_ptr = (sljit_uw *)(update_table + 256);
+ memset(update_table, IN_UCHARS(range_len), 256);
+
+ for (i = 0; i < range_len; i++)
+ {
+ byte_set = bytes + ((range_right - i) * MAX_N_BYTES);
+ SLJIT_ASSERT(byte_set[0] > 0 && byte_set[0] < 255);
+ byte_set_end = byte_set + byte_set[0];
+ byte_set++;
+ while (byte_set <= byte_set_end)
+ {
+ if (update_table[*byte_set] > IN_UCHARS(i))
+ update_table[*byte_set] = IN_UCHARS(i);
+ byte_set++;
+ }
}
+ }
- if (location >= MAX_N_CHARS * 2 || must_stop != 0)
+offsets[0] = -1;
+/* Scan forward. */
+for (i = 0; i < max; i++)
+ if (ones[i] <= 2) {
+ offsets[0] = i;
break;
}
-/* At least two characters are required. */
-if (location < 2 * 2)
+if (offsets[0] < 0 && range_right < 0)
+ return FALSE;
+
+if (offsets[0] >= 0)
+ {
+ /* Scan backward. */
+ offsets[1] = -1;
+ for (i = max - 1; i > offsets[0]; i--)
+ if (ones[i] <= 2 && i != range_right)
+ {
+ offsets[1] = i;
+ break;
+ }
+
+ /* This case is handled better by fast_forward_first_char. */
+ if (offsets[1] == -1 && offsets[0] == 0 && range_right < 0)
return FALSE;
+ offsets[2] = -1;
+ /* We only search for a middle character if there is no range check. */
+ if (offsets[1] >= 0 && range_right == -1)
+ {
+ /* Scan from middle. */
+ for (i = (offsets[0] + offsets[1]) / 2 + 1; i < offsets[1]; i++)
+ if (ones[i] <= 2)
+ {
+ offsets[2] = i;
+ break;
+ }
+
+ if (offsets[2] == -1)
+ {
+ for (i = (offsets[0] + offsets[1]) / 2; i > offsets[0]; i--)
+ if (ones[i] <= 2)
+ {
+ offsets[2] = i;
+ break;
+ }
+ }
+ }
+
+ SLJIT_ASSERT(offsets[1] == -1 || (offsets[0] < offsets[1]));
+ SLJIT_ASSERT(offsets[2] == -1 || (offsets[0] < offsets[2] && offsets[1] > offsets[2]));
+
+ chars[0] = chars[offsets[0] << 1];
+ chars[1] = chars[(offsets[0] << 1) + 1];
+ if (offsets[2] >= 0)
+ {
+ chars[2] = chars[offsets[2] << 1];
+ chars[3] = chars[(offsets[2] << 1) + 1];
+ }
+ if (offsets[1] >= 0)
+ {
+ chars[4] = chars[offsets[1] << 1];
+ chars[5] = chars[(offsets[1] << 1) + 1];
+ }
+ }
+
+max -= 1;
if (firstline)
{
SLJIT_ASSERT(common->first_line_end != 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end);
OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
- OP2(SLJIT_SUB, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, SLJIT_IMM, IN_UCHARS((location >> 1) - 1));
+ OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));
+ quit = CMP(SLJIT_C_LESS_EQUAL, STR_END, 0, TMP1, 0);
+ OP1(SLJIT_MOV, STR_END, 0, TMP1, 0);
+ JUMPHERE(quit);
}
else
- OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS((location >> 1) - 1));
+ OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));
+
+#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+if (range_right >= 0)
+ OP1(SLJIT_MOV, RETURN_ADDR, 0, SLJIT_IMM, (sljit_sw)update_table);
+#endif
start = LABEL();
quit = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
-OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
-if (chars[1] != 0)
- OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, chars[1]);
-CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[0], start);
-if (location > 2 * 2)
- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
-if (chars[3] != 0)
- OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, chars[3]);
-CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, chars[2], start);
-if (location > 2 * 2)
- {
- if (chars[5] != 0)
- OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, chars[5]);
- CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[4], start);
+SLJIT_ASSERT(range_right >= 0 || offsets[0] >= 0);
+
+if (range_right >= 0)
+ {
+#if defined COMPILE_PCRE8 || (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right));
+#else
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right + 1) - 1);
+#endif
+
+#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM2(RETURN_ADDR, TMP1), 0);
+#else
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)update_table);
+#endif
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+ CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, start);
+ }
+
+if (offsets[0] >= 0)
+ {
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(offsets[0]));
+ if (offsets[1] >= 0)
+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(offsets[1]));
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
+ if (chars[1] != 0)
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, chars[1]);
+ CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[0], start);
+ if (offsets[2] >= 0)
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(offsets[2] - 1));
+
+ if (offsets[1] >= 0)
+ {
+ if (chars[5] != 0)
+ OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, chars[5]);
+ CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, chars[4], start);
+ }
+
+ if (offsets[2] >= 0)
+ {
+ if (chars[3] != 0)
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, chars[3]);
+ CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[2], start);
+ }
+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
}
-OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
JUMPHERE(quit);
if (firstline)
+ {
+ if (range_right >= 0)
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end);
OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
+ if (range_right >= 0)
+ {
+ quit = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0);
+ OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0);
+ JUMPHERE(quit);
+ }
+ }
else
- OP2(SLJIT_ADD, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS((location >> 1) - 1));
+ OP2(SLJIT_ADD, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));
return TRUE;
}
#undef MAX_N_CHARS
+#undef MAX_N_BYTES
static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless, BOOL firstline)
{
@@ -3167,7 +3873,7 @@ if (common->nltype == NLTYPE_FIXED && common->newline > 255)
JUMPHERE(lastchar);
if (firstline)
- OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
return;
}
@@ -3177,7 +3883,9 @@ firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
skip_char_back(common);
loop = LABEL();
-read_char(common);
+common->ff_newline_shortcut = loop;
+
+read_char_range(common, common->nlmin, common->nlmax, TRUE);
lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
foundcr = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
@@ -3206,24 +3914,19 @@ if (firstline)
OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
}
-static BOOL check_class_ranges(compiler_common *common, const pcre_uint8 *bits, BOOL nclass, jump_list **backtracks);
+static BOOL check_class_ranges(compiler_common *common, const pcre_uint8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks);
-static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, sljit_uw start_bits, BOOL firstline)
+static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, pcre_uint8 *start_bits, BOOL firstline)
{
DEFINE_COMPILER;
struct sljit_label *start;
struct sljit_jump *quit;
struct sljit_jump *found = NULL;
jump_list *matches = NULL;
-pcre_uint8 inverted_start_bits[32];
-int i;
#ifndef COMPILE_PCRE8
struct sljit_jump *jump;
#endif
-for (i = 0; i < 32; ++i)
- inverted_start_bits[i] = ~(((pcre_uint8*)start_bits)[i]);
-
if (firstline)
{
SLJIT_ASSERT(common->first_line_end != 0);
@@ -3239,7 +3942,7 @@ if (common->utf)
OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
#endif
-if (!check_class_ranges(common, inverted_start_bits, (inverted_start_bits[31] & 0x80) != 0, &matches))
+if (!check_class_ranges(common, start_bits, (start_bits[31] & 0x80) != 0, TRUE, &matches))
{
#ifndef COMPILE_PCRE8
jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 255);
@@ -3248,7 +3951,7 @@ if (!check_class_ranges(common, inverted_start_bits, (inverted_start_bits[31] &
#endif
OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
- OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), start_bits);
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)start_bits);
OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
found = JUMP(SLJIT_C_NOT_ZERO);
@@ -3451,7 +4154,7 @@ JUMPHERE(skipread);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
check_str_end(common, &skipread_list);
-peek_char(common);
+peek_char(common, READ_CHAR_MAX);
/* Testing char type. This is a code duplication. */
#ifdef SUPPORT_UCP
@@ -3497,112 +4200,15 @@ OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_R
sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
}
-/*
- range format:
-
- ranges[0] = length of the range (max MAX_RANGE_SIZE, -1 means invalid range).
- ranges[1] = first bit (0 or 1)
- ranges[2-length] = position of the bit change (when the current bit is not equal to the previous)
-*/
-
-static BOOL check_ranges(compiler_common *common, int *ranges, jump_list **backtracks, BOOL readch)
+static BOOL check_class_ranges(compiler_common *common, const pcre_uint8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks)
{
DEFINE_COMPILER;
-struct sljit_jump *jump;
-
-if (ranges[0] < 0)
- return FALSE;
-
-switch(ranges[0])
- {
- case 1:
- if (readch)
- read_char(common);
- add_jump(compiler, backtracks, CMP(ranges[1] == 0 ? SLJIT_C_LESS : SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2]));
- return TRUE;
-
- case 2:
- if (readch)
- read_char(common);
- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2]);
- add_jump(compiler, backtracks, CMP(ranges[1] != 0 ? SLJIT_C_LESS : SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2]));
- return TRUE;
-
- case 4:
- if (ranges[2] + 1 == ranges[3] && ranges[4] + 1 == ranges[5])
- {
- if (readch)
- read_char(common);
- if (ranges[1] != 0)
- {
- add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2]));
- add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[4]));
- }
- else
- {
- jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2]);
- add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[4]));
- JUMPHERE(jump);
- }
- return TRUE;
- }
- if ((ranges[3] - ranges[2]) == (ranges[5] - ranges[4])
- && (ranges[2] | (ranges[4] - ranges[2])) == ranges[4]
- && is_powerof2(ranges[4] - ranges[2]))
- {
- if (readch)
- read_char(common);
- OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[4] - ranges[2]);
- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[4]);
- add_jump(compiler, backtracks, CMP(ranges[1] != 0 ? SLJIT_C_LESS : SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[5] - ranges[4]));
- return TRUE;
- }
- return FALSE;
-
- default:
- return FALSE;
- }
-}
-
-static void get_ctype_ranges(compiler_common *common, int flag, int *ranges)
-{
-int i, bit, length;
-const pcre_uint8 *ctypes = (const pcre_uint8*)common->ctypes;
-
-bit = ctypes[0] & flag;
-ranges[0] = -1;
-ranges[1] = bit != 0 ? 1 : 0;
-length = 0;
-
-for (i = 1; i < 256; i++)
- if ((ctypes[i] & flag) != bit)
- {
- if (length >= MAX_RANGE_SIZE)
- return;
- ranges[2 + length] = i;
- length++;
- bit ^= flag;
- }
-
-if (bit != 0)
- {
- if (length >= MAX_RANGE_SIZE)
- return;
- ranges[2 + length] = 256;
- length++;
- }
-ranges[0] = length;
-}
-
-static BOOL check_class_ranges(compiler_common *common, const pcre_uint8 *bits, BOOL nclass, jump_list **backtracks)
-{
-int ranges[2 + MAX_RANGE_SIZE];
+int ranges[MAX_RANGE_SIZE];
pcre_uint8 bit, cbit, all;
int i, byte, length = 0;
bit = bits[0] & 0x1;
-ranges[1] = bit;
-/* Can be 0 or 255. */
+/* All bits will be zero or one (since bit is zero or one). */
all = -bit;
for (i = 0; i < 256; )
@@ -3617,7 +4223,7 @@ for (i = 0; i < 256; )
{
if (length >= MAX_RANGE_SIZE)
return FALSE;
- ranges[2 + length] = i;
+ ranges[length] = i;
length++;
bit = cbit;
all = -cbit;
@@ -3630,12 +4236,117 @@ if (((bit == 0) && nclass) || ((bit == 1) && !nclass))
{
if (length >= MAX_RANGE_SIZE)
return FALSE;
- ranges[2 + length] = 256;
+ ranges[length] = 256;
length++;
}
-ranges[0] = length;
-return check_ranges(common, ranges, backtracks, FALSE);
+if (length < 0 || length > 4)
+ return FALSE;
+
+bit = bits[0] & 0x1;
+if (invert) bit ^= 0x1;
+
+/* No character is accepted. */
+if (length == 0 && bit == 0)
+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
+
+switch(length)
+ {
+ case 0:
+ /* When bit != 0, all characters are accepted. */
+ return TRUE;
+
+ case 1:
+ add_jump(compiler, backtracks, CMP(bit == 0 ? SLJIT_C_LESS : SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));
+ return TRUE;
+
+ case 2:
+ if (ranges[0] + 1 != ranges[1])
+ {
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);
+ add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_C_LESS : SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));
+ }
+ else
+ add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));
+ return TRUE;
+
+ case 3:
+ if (bit != 0)
+ {
+ add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2]));
+ if (ranges[0] + 1 != ranges[1])
+ {
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));
+ }
+ else
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));
+ return TRUE;
+ }
+
+ add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, ranges[0]));
+ if (ranges[1] + 1 != ranges[2])
+ {
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[1]);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[1]));
+ }
+ else
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1]));
+ return TRUE;
+
+ case 4:
+ if ((ranges[1] - ranges[0]) == (ranges[3] - ranges[2])
+ && (ranges[0] | (ranges[2] - ranges[0])) == ranges[2]
+ && is_powerof2(ranges[2] - ranges[0]))
+ {
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[0]);
+ if (ranges[2] + 1 != ranges[3])
+ {
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2]);
+ add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_C_LESS : SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2]));
+ }
+ else
+ add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2]));
+ return TRUE;
+ }
+
+ if (bit != 0)
+ {
+ i = 0;
+ if (ranges[0] + 1 != ranges[1])
+ {
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));
+ i = ranges[0];
+ }
+ else
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));
+
+ if (ranges[2] + 1 != ranges[3])
+ {
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2] - i);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2]));
+ }
+ else
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2] - i));
+ return TRUE;
+ }
+
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[0]));
+ if (ranges[1] + 1 != ranges[2])
+ {
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[1]));
+ }
+ else
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));
+ return TRUE;
+
+ default:
+ SLJIT_ASSERT_STOP();
+ return FALSE;
+ }
}
static void check_anynewline(compiler_common *common)
@@ -4002,20 +4713,20 @@ return cc;
#define SET_TYPE_OFFSET(value) \
if ((value) != typeoffset) \
{ \
- if ((value) > typeoffset) \
- OP2(SLJIT_SUB, typereg, 0, typereg, 0, SLJIT_IMM, (value) - typeoffset); \
- else \
+ if ((value) < typeoffset) \
OP2(SLJIT_ADD, typereg, 0, typereg, 0, SLJIT_IMM, typeoffset - (value)); \
+ else \
+ OP2(SLJIT_SUB, typereg, 0, typereg, 0, SLJIT_IMM, (value) - typeoffset); \
} \
typeoffset = (value);
#define SET_CHAR_OFFSET(value) \
if ((value) != charoffset) \
{ \
- if ((value) > charoffset) \
- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (value) - charoffset); \
+ if ((value) < charoffset) \
+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(charoffset - (value))); \
else \
- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, charoffset - (value)); \
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)((value) - charoffset)); \
} \
charoffset = (value);
@@ -4023,84 +4734,53 @@ static void compile_xclass_matchingpath(compiler_common *common, pcre_uchar *cc,
{
DEFINE_COMPILER;
jump_list *found = NULL;
-jump_list **list = (*cc & XCL_NOT) == 0 ? &found : backtracks;
-pcre_int32 c, charoffset;
+jump_list **list = (cc[0] & XCL_NOT) == 0 ? &found : backtracks;
+sljit_uw c, charoffset, max = 256, min = READ_CHAR_MAX;
struct sljit_jump *jump = NULL;
pcre_uchar *ccbegin;
int compares, invertcmp, numberofcmps;
+#if defined SUPPORT_UTF && (defined COMPILE_PCRE8 || defined COMPILE_PCRE16)
+BOOL utf = common->utf;
+#endif
#ifdef SUPPORT_UCP
BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE;
BOOL charsaved = FALSE;
int typereg = TMP1, scriptreg = TMP1;
const pcre_uint32 *other_cases;
-pcre_int32 typeoffset;
+sljit_uw typeoffset;
#endif
-/* Although SUPPORT_UTF must be defined, we are
- not necessary in utf mode even in 8 bit mode. */
-detect_partial_match(common, backtracks);
-read_char(common);
-
-if ((*cc++ & XCL_MAP) != 0)
+/* Scanning the necessary info. */
+cc++;
+ccbegin = cc;
+compares = 0;
+if (cc[-1] & XCL_MAP)
{
- OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
-#ifndef COMPILE_PCRE8
- jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
-#elif defined SUPPORT_UTF
- if (common->utf)
- jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
-#endif
-
- if (!check_class_ranges(common, (const pcre_uint8 *)cc, TRUE, list))
- {
- OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
- OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
- OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
- OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
- OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
- add_jump(compiler, list, JUMP(SLJIT_C_NOT_ZERO));
- }
-
-#ifndef COMPILE_PCRE8
- JUMPHERE(jump);
-#elif defined SUPPORT_UTF
- if (common->utf)
- JUMPHERE(jump);
-#endif
- OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
-#ifdef SUPPORT_UCP
- charsaved = TRUE;
-#endif
+ min = 0;
cc += 32 / sizeof(pcre_uchar);
}
-/* Scanning the necessary info. */
-ccbegin = cc;
-compares = 0;
while (*cc != XCL_END)
{
compares++;
if (*cc == XCL_SINGLE)
{
- cc += 2;
-#ifdef SUPPORT_UTF
- if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
-#endif
+ cc ++;
+ GETCHARINCTEST(c, cc);
+ if (c > max) max = c;
+ if (c < min) min = c;
#ifdef SUPPORT_UCP
needschar = TRUE;
#endif
}
else if (*cc == XCL_RANGE)
{
- cc += 2;
-#ifdef SUPPORT_UTF
- if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
-#endif
- cc++;
-#ifdef SUPPORT_UTF
- if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
-#endif
+ cc ++;
+ GETCHARINCTEST(c, cc);
+ if (c < min) min = c;
+ GETCHARINCTEST(c, cc);
+ if (c > max) max = c;
#ifdef SUPPORT_UCP
needschar = TRUE;
#endif
@@ -4110,6 +4790,22 @@ while (*cc != XCL_END)
{
SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
cc++;
+ if (*cc == PT_CLIST)
+ {
+ other_cases = PRIV(ucd_caseless_sets) + cc[1];
+ while (*other_cases != NOTACHAR)
+ {
+ if (*other_cases > max) max = *other_cases;
+ if (*other_cases < min) min = *other_cases;
+ other_cases++;
+ }
+ }
+ else
+ {
+ max = READ_CHAR_MAX;
+ min = 0;
+ }
+
switch(*cc)
{
case PT_ANY:
@@ -4150,6 +4846,64 @@ while (*cc != XCL_END)
#endif
}
+/* We are not necessary in utf mode even in 8 bit mode. */
+cc = ccbegin;
+detect_partial_match(common, backtracks);
+read_char_range(common, min, max, (cc[-1] & XCL_NOT) != 0);
+
+if ((cc[-1] & XCL_HASPROP) == 0)
+ {
+ if ((cc[-1] & XCL_MAP) != 0)
+ {
+ jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
+ if (!check_class_ranges(common, (const pcre_uint8 *)cc, (((const pcre_uint8 *)cc)[31] & 0x80) != 0, TRUE, &found))
+ {
+ OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
+ OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
+ OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
+ OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+ add_jump(compiler, &found, JUMP(SLJIT_C_NOT_ZERO));
+ }
+
+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
+ JUMPHERE(jump);
+
+ cc += 32 / sizeof(pcre_uchar);
+ }
+ else
+ {
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, min);
+ add_jump(compiler, (cc[-1] & XCL_NOT) == 0 ? backtracks : &found, CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, max - min));
+ }
+ }
+else if ((cc[-1] & XCL_MAP) != 0)
+ {
+ OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
+#ifdef SUPPORT_UCP
+ charsaved = TRUE;
+#endif
+ if (!check_class_ranges(common, (const pcre_uint8 *)cc, FALSE, TRUE, list))
+ {
+#ifdef COMPILE_PCRE8
+ SLJIT_ASSERT(common->utf);
+#endif
+ jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
+
+ OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
+ OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
+ OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
+ OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+ add_jump(compiler, list, JUMP(SLJIT_C_NOT_ZERO));
+
+ JUMPHERE(jump);
+ }
+
+ OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
+ cc += 32 / sizeof(pcre_uchar);
+ }
+
#ifdef SUPPORT_UCP
/* Simple register allocation. TMP1 is preferred if possible. */
if (needstype || needsscript)
@@ -4191,7 +4945,6 @@ if (needstype || needsscript)
#endif
/* Generating code. */
-cc = ccbegin;
charoffset = 0;
numberofcmps = 0;
#ifdef SUPPORT_UCP
@@ -4207,70 +4960,50 @@ while (*cc != XCL_END)
if (*cc == XCL_SINGLE)
{
cc ++;
-#ifdef SUPPORT_UTF
- if (common->utf)
- {
- GETCHARINC(c, cc);
- }
- else
-#endif
- c = *cc++;
+ GETCHARINCTEST(c, cc);
if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
{
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, numberofcmps == 0 ? SLJIT_UNUSED : TMP2, 0, SLJIT_C_EQUAL);
numberofcmps++;
}
else if (numberofcmps > 0)
{
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
numberofcmps = 0;
}
else
{
- jump = CMP(SLJIT_C_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, c - charoffset);
+ jump = CMP(SLJIT_C_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
numberofcmps = 0;
}
}
else if (*cc == XCL_RANGE)
{
cc ++;
-#ifdef SUPPORT_UTF
- if (common->utf)
- {
- GETCHARINC(c, cc);
- }
- else
-#endif
- c = *cc++;
+ GETCHARINCTEST(c, cc);
SET_CHAR_OFFSET(c);
-#ifdef SUPPORT_UTF
- if (common->utf)
- {
- GETCHARINC(c, cc);
- }
- else
-#endif
- c = *cc++;
+ GETCHARINCTEST(c, cc);
+
if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
{
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, numberofcmps == 0 ? SLJIT_UNUSED : TMP2, 0, SLJIT_C_LESS_EQUAL);
numberofcmps++;
}
else if (numberofcmps > 0)
{
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL);
jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
numberofcmps = 0;
}
else
{
- jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, c - charoffset);
+ jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
numberofcmps = 0;
}
}
@@ -4336,7 +5069,7 @@ while (*cc != XCL_END)
break;
case PT_WORD:
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE - charoffset);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_UNDERSCORE - charoffset));
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
/* Fall through. */
@@ -4384,35 +5117,35 @@ while (*cc != XCL_END)
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[2]);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, other_cases[0] - charoffset);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(other_cases[0] - charoffset));
OP_FLAGS(SLJIT_OR | ((other_cases[3] == NOTACHAR) ? SLJIT_SET_E : 0), TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
other_cases += 3;
}
else
{
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, *other_cases++ - charoffset);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
}
while (*other_cases != NOTACHAR)
{
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, *other_cases++ - charoffset);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));
OP_FLAGS(SLJIT_OR | ((*other_cases == NOTACHAR) ? SLJIT_SET_E : 0), TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
}
jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
break;
case PT_UCNC:
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_DOLLAR_SIGN - charoffset);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_DOLLAR_SIGN - charoffset));
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_COMMERCIAL_AT - charoffset);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_COMMERCIAL_AT - charoffset));
OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_GRAVE_ACCENT - charoffset);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_GRAVE_ACCENT - charoffset));
OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
SET_CHAR_OFFSET(0xa0);
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd7ff - charoffset);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(0xd7ff - charoffset));
OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL);
SET_CHAR_OFFSET(0);
OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xe000 - 0);
@@ -4511,7 +5244,7 @@ struct sljit_label *label;
#ifdef SUPPORT_UCP
pcre_uchar propdata[5];
#endif
-#endif
+#endif /* SUPPORT_UTF */
switch(type)
{
@@ -4536,26 +5269,27 @@ switch(type)
case OP_NOT_DIGIT:
case OP_DIGIT:
/* Digits are usually 0-9, so it is worth to optimize them. */
- if (common->digits[0] == -2)
- get_ctype_ranges(common, ctype_digit, common->digits);
detect_partial_match(common, backtracks);
- /* Flip the starting bit in the negative case. */
- if (type == OP_NOT_DIGIT)
- common->digits[1] ^= 1;
- if (!check_ranges(common, common->digits, backtracks, TRUE))
- {
- read_char8_type(common);
- OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit);
- add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
- }
- if (type == OP_NOT_DIGIT)
- common->digits[1] ^= 1;
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+ if (common->utf && is_char7_bitset((const pcre_uint8*)common->ctypes - cbit_length + cbit_digit, FALSE))
+ read_char7_type(common, type == OP_NOT_DIGIT);
+ else
+#endif
+ read_char8_type(common, type == OP_NOT_DIGIT);
+ /* Flip the starting bit in the negative case. */
+ OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit);
+ add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
return cc;
case OP_NOT_WHITESPACE:
case OP_WHITESPACE:
detect_partial_match(common, backtracks);
- read_char8_type(common);
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+ if (common->utf && is_char7_bitset((const pcre_uint8*)common->ctypes - cbit_length + cbit_space, FALSE))
+ read_char7_type(common, type == OP_NOT_WHITESPACE);
+ else
+#endif
+ read_char8_type(common, type == OP_NOT_WHITESPACE);
OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space);
add_jump(compiler, backtracks, JUMP(type == OP_WHITESPACE ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
return cc;
@@ -4563,14 +5297,19 @@ switch(type)
case OP_NOT_WORDCHAR:
case OP_WORDCHAR:
detect_partial_match(common, backtracks);
- read_char8_type(common);
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+ if (common->utf && is_char7_bitset((const pcre_uint8*)common->ctypes - cbit_length + cbit_word, FALSE))
+ read_char7_type(common, type == OP_NOT_WORDCHAR);
+ else
+#endif
+ read_char8_type(common, type == OP_NOT_WORDCHAR);
OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word);
add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
return cc;
case OP_ANY:
detect_partial_match(common, backtracks);
- read_char(common);
+ read_char_range(common, common->nlmin, common->nlmax, TRUE);
if (common->nltype == NLTYPE_FIXED && common->newline > 255)
{
jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
@@ -4626,7 +5365,7 @@ switch(type)
#ifdef SUPPORT_UCP
case OP_NOTPROP:
case OP_PROP:
- propdata[0] = 0;
+ propdata[0] = XCL_HASPROP;
propdata[1] = type == OP_NOTPROP ? XCL_NOTPROP : XCL_PROP;
propdata[2] = cc[0];
propdata[3] = cc[1];
@@ -4638,7 +5377,7 @@ switch(type)
case OP_ANYNL:
detect_partial_match(common, backtracks);
- read_char(common);
+ read_char_range(common, common->bsr_nlmin, common->bsr_nlmax, FALSE);
jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
/* We don't need to handle soft partial matching case. */
end_list = NULL;
@@ -4660,7 +5399,7 @@ switch(type)
case OP_NOT_HSPACE:
case OP_HSPACE:
detect_partial_match(common, backtracks);
- read_char(common);
+ read_char_range(common, 0x9, 0x3000, type == OP_NOT_HSPACE);
add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL));
add_jump(compiler, backtracks, JUMP(type == OP_NOT_HSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
return cc;
@@ -4668,7 +5407,7 @@ switch(type)
case OP_NOT_VSPACE:
case OP_VSPACE:
detect_partial_match(common, backtracks);
- read_char(common);
+ read_char_range(common, 0xa, 0x2029, type == OP_NOT_VSPACE);
add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL));
add_jump(compiler, backtracks, JUMP(type == OP_NOT_VSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
return cc;
@@ -4767,7 +5506,7 @@ switch(type)
else
{
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, STR_PTR, 0);
- read_char(common);
+ read_char_range(common, common->nlmin, common->nlmax, TRUE);
add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0));
add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO));
@@ -4815,7 +5554,7 @@ switch(type)
else
{
skip_char_back(common);
- read_char(common);
+ read_char_range(common, common->nlmin, common->nlmax, TRUE);
check_newlinechar(common, common->nltype, backtracks, FALSE);
}
JUMPHERE(jump[0]);
@@ -4866,7 +5605,7 @@ switch(type)
}
else
{
- peek_char(common);
+ peek_char(common, common->nlmax);
check_newlinechar(common, common->nltype, backtracks, FALSE);
}
JUMPHERE(jump[0]);
@@ -4890,8 +5629,8 @@ switch(type)
#endif
return byte_sequence_compare(common, type == OP_CHARI, cc, &context, backtracks);
}
+
detect_partial_match(common, backtracks);
- read_char(common);
#ifdef SUPPORT_UTF
if (common->utf)
{
@@ -4900,12 +5639,15 @@ switch(type)
else
#endif
c = *cc;
+
if (type == OP_CHAR || !char_has_othercase(common, cc))
{
+ read_char_range(common, c, c, FALSE);
add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c));
return cc + length;
}
oc = char_othercase(common, c);
+ read_char_range(common, c < oc ? c : oc, c > oc ? c : oc, FALSE);
bit = c ^ oc;
if (is_powerof2(bit))
{
@@ -4913,11 +5655,9 @@ switch(type)
add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));
return cc + length;
}
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c);
- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc);
- OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
- add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO));
+ jump[0] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, oc));
+ JUMPHERE(jump[0]);
return cc + length;
case OP_NOT:
@@ -4952,21 +5692,21 @@ switch(type)
#endif /* COMPILE_PCRE8 */
{
GETCHARLEN(c, cc, length);
- read_char(common);
}
}
else
#endif /* SUPPORT_UTF */
- {
- read_char(common);
c = *cc;
- }
if (type == OP_NOT || !char_has_othercase(common, cc))
+ {
+ read_char_range(common, c, c, TRUE);
add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
+ }
else
{
oc = char_othercase(common, c);
+ read_char_range(common, c < oc ? c : oc, c > oc ? c : oc, TRUE);
bit = c ^ oc;
if (is_powerof2(bit))
{
@@ -4984,36 +5724,49 @@ switch(type)
case OP_CLASS:
case OP_NCLASS:
detect_partial_match(common, backtracks);
- read_char(common);
- if (check_class_ranges(common, (const pcre_uint8 *)cc, type == OP_NCLASS, backtracks))
+
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+ bit = (common->utf && is_char7_bitset((const pcre_uint8 *)cc, type == OP_NCLASS)) ? 127 : 255;
+ read_char_range(common, 0, bit, type == OP_NCLASS);
+#else
+ read_char_range(common, 0, 255, type == OP_NCLASS);
+#endif
+
+ if (check_class_ranges(common, (const pcre_uint8 *)cc, type == OP_NCLASS, FALSE, backtracks))
return cc + 32 / sizeof(pcre_uchar);
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
jump[0] = NULL;
-#ifdef COMPILE_PCRE8
- /* This check only affects 8 bit mode. In other modes, we
- always need to compare the value with 255. */
if (common->utf)
-#endif /* COMPILE_PCRE8 */
{
- jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
+ jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, bit);
if (type == OP_CLASS)
{
add_jump(compiler, backtracks, jump[0]);
jump[0] = NULL;
}
}
-#endif /* SUPPORT_UTF || !COMPILE_PCRE8 */
+#elif !defined COMPILE_PCRE8
+ jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
+ if (type == OP_CLASS)
+ {
+ add_jump(compiler, backtracks, jump[0]);
+ jump[0] = NULL;
+ }
+#endif /* SUPPORT_UTF && COMPILE_PCRE8 */
+
OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO));
+
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
if (jump[0] != NULL)
JUMPHERE(jump[0]);
-#endif /* SUPPORT_UTF || !COMPILE_PCRE8 */
+#endif
+
return cc + 32 / sizeof(pcre_uchar);
#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
@@ -7347,7 +8100,7 @@ if (*cc == OP_FAIL)
return cc + 1;
}
-if (*cc == OP_ASSERT_ACCEPT || common->currententry != NULL)
+if (*cc == OP_ASSERT_ACCEPT || common->currententry != NULL || !common->might_be_empty)
{
/* No need to check notempty conditions. */
if (common->accept_label == NULL)
@@ -8049,21 +8802,21 @@ if (bra == OP_BRAZERO)
static void compile_bracket_backtrackingpath(compiler_common *common, struct backtrack_common *current)
{
DEFINE_COMPILER;
-int opcode, stacksize, count;
+int opcode, stacksize, alt_count, alt_max;
int offset = 0;
int private_data_ptr = CURRENT_AS(bracket_backtrack)->private_data_ptr;
int repeat_ptr = 0, repeat_type = 0, repeat_count = 0;
pcre_uchar *cc = current->cc;
pcre_uchar *ccbegin;
pcre_uchar *ccprev;
-jump_list *jumplist = NULL;
-jump_list *jumplistitem = NULL;
pcre_uchar bra = OP_BRA;
pcre_uchar ket;
assert_backtrack *assert;
BOOL has_alternatives;
BOOL needs_control_head = FALSE;
struct sljit_jump *brazero = NULL;
+struct sljit_jump *alt1 = NULL;
+struct sljit_jump *alt2 = NULL;
struct sljit_jump *once = NULL;
struct sljit_jump *cond = NULL;
struct sljit_label *rmin_label = NULL;
@@ -8101,6 +8854,8 @@ if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN
if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC))
opcode = OP_ONCE;
+alt_max = has_alternatives ? no_alternatives(ccbegin) : 0;
+
/* Decoding the needs_control_head in framesize. */
if (opcode == OP_ONCE)
{
@@ -8214,44 +8969,27 @@ else if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
free_stack(common, 1);
- jumplistitem = sljit_alloc_memory(compiler, sizeof(jump_list));
- if (SLJIT_UNLIKELY(!jumplistitem))
- return;
- jumplist = jumplistitem;
- jumplistitem->next = NULL;
- jumplistitem->jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 1);
+ alt_max = 2;
+ alt1 = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, sizeof(sljit_uw));
}
}
-else if (*cc == OP_ALT)
+else if (has_alternatives)
{
- /* Build a jump list. Get the last successfully matched branch index. */
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
free_stack(common, 1);
- count = 1;
- do
- {
- /* Append as the last item. */
- if (jumplist != NULL)
- {
- jumplistitem->next = sljit_alloc_memory(compiler, sizeof(jump_list));
- jumplistitem = jumplistitem->next;
- }
- else
- {
- jumplistitem = sljit_alloc_memory(compiler, sizeof(jump_list));
- jumplist = jumplistitem;
- }
- if (SLJIT_UNLIKELY(!jumplistitem))
- return;
-
- jumplistitem->next = NULL;
- jumplistitem->jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, count++);
- cc += GET(cc, 1);
+ if (alt_max > 4)
+ {
+ /* Table jump if alt_max is greater than 4. */
+ sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM1(TMP1), (sljit_sw)common->read_only_data_ptr);
+ add_label_addr(common);
+ }
+ else
+ {
+ if (alt_max == 4)
+ alt2 = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw));
+ alt1 = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, sizeof(sljit_uw));
}
- while (*cc == OP_ALT);
-
- cc = ccbegin + GET(ccbegin, 1);
}
COMPILE_BACKTRACKINGPATH(current->top);
@@ -8286,7 +9024,7 @@ if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
if (has_alternatives)
{
- count = 1;
+ alt_count = sizeof(sljit_uw);
do
{
current->top = NULL;
@@ -8362,7 +9100,7 @@ if (has_alternatives)
stacksize = match_capture_common(common, stacksize, offset, private_data_ptr);
if (opcode != OP_ONCE)
- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, count++);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, alt_count);
if (offset != 0 && ket == OP_KETRMAX && common->optimized_cbracket[offset >> 1] != 0)
{
@@ -8375,9 +9113,24 @@ if (has_alternatives)
if (opcode != OP_ONCE)
{
- SLJIT_ASSERT(jumplist);
- JUMPHERE(jumplist->jump);
- jumplist = jumplist->next;
+ if (alt_max > 4)
+ add_label_addr(common);
+ else
+ {
+ if (alt_count != 2 * sizeof(sljit_uw))
+ {
+ JUMPHERE(alt1);
+ if (alt_max == 3 && alt_count == sizeof(sljit_uw))
+ alt2 = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw));
+ }
+ else
+ {
+ JUMPHERE(alt2);
+ if (alt_max == 4)
+ alt1 = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_uw));
+ }
+ }
+ alt_count += sizeof(sljit_uw);
}
COMPILE_BACKTRACKINGPATH(current->top);
@@ -8386,7 +9139,6 @@ if (has_alternatives)
SLJIT_ASSERT(!current->nextbacktracks);
}
while (*cc == OP_ALT);
- SLJIT_ASSERT(!jumplist);
if (cond != NULL)
{
@@ -8987,16 +9739,18 @@ pcre_uchar *ccend;
executable_functions *functions;
void *executable_func;
sljit_uw executable_size;
+sljit_uw total_length;
+label_addr_list *label_addr;
struct sljit_label *mainloop_label = NULL;
struct sljit_label *continue_match_label;
-struct sljit_label *empty_match_found_label;
-struct sljit_label *empty_match_backtrack_label;
+struct sljit_label *empty_match_found_label = NULL;
+struct sljit_label *empty_match_backtrack_label = NULL;
struct sljit_label *reset_match_label;
+struct sljit_label *quit_label;
struct sljit_jump *jump;
struct sljit_jump *minlength_check_failed = NULL;
struct sljit_jump *reqbyte_notfound = NULL;
-struct sljit_jump *empty_match;
-struct sljit_label *quit_label;
+struct sljit_jump *empty_match = NULL;
SLJIT_ASSERT((extra->flags & PCRE_EXTRA_STUDY_DATA) != 0);
study = extra->study_data;
@@ -9009,9 +9763,13 @@ memset(common, 0, sizeof(compiler_common));
rootbacktrack.cc = (pcre_uchar *)re + re->name_table_offset + re->name_count * re->name_entry_size;
common->start = rootbacktrack.cc;
+common->read_only_data = NULL;
+common->read_only_data_size = 0;
+common->read_only_data_ptr = NULL;
common->fcc = tables + fcc_offset;
common->lcc = (sljit_sw)(tables + lcc_offset);
common->mode = mode;
+common->might_be_empty = study->minlength == 0;
common->nltype = NLTYPE_FIXED;
switch(re->options & PCRE_NEWLINE_BITS)
{
@@ -9032,6 +9790,8 @@ switch(re->options & PCRE_NEWLINE_BITS)
case PCRE_NEWLINE_ANYCRLF: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break;
default: return;
}
+common->nlmax = READ_CHAR_MAX;
+common->nlmin = 0;
if ((re->options & PCRE_BSR_ANYCRLF) != 0)
common->bsr_nltype = NLTYPE_ANYCRLF;
else if ((re->options & PCRE_BSR_UNICODE) != 0)
@@ -9044,9 +9804,10 @@ else
common->bsr_nltype = NLTYPE_ANY;
#endif
}
+common->bsr_nlmax = READ_CHAR_MAX;
+common->bsr_nlmin = 0;
common->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
common->ctypes = (sljit_sw)(tables + ctypes_offset);
-common->digits[0] = -2;
common->name_table = ((pcre_uchar *)re) + re->name_table_offset;
common->name_count = re->name_count;
common->name_entry_size = re->name_entry_size;
@@ -9057,8 +9818,31 @@ common->utf = (re->options & PCRE_UTF8) != 0;
#ifdef SUPPORT_UCP
common->use_ucp = (re->options & PCRE_UCP) != 0;
#endif
+if (common->utf)
+ {
+ if (common->nltype == NLTYPE_ANY)
+ common->nlmax = 0x2029;
+ else if (common->nltype == NLTYPE_ANYCRLF)
+ common->nlmax = (CHAR_CR > CHAR_NL) ? CHAR_CR : CHAR_NL;
+ else
+ {
+ /* We only care about the first newline character. */
+ common->nlmax = common->newline & 0xff;
+ }
+
+ if (common->nltype == NLTYPE_FIXED)
+ common->nlmin = common->newline & 0xff;
+ else
+ common->nlmin = (CHAR_CR < CHAR_NL) ? CHAR_CR : CHAR_NL;
+
+ if (common->bsr_nltype == NLTYPE_ANY)
+ common->bsr_nlmax = 0x2029;
+ else
+ common->bsr_nlmax = (CHAR_CR > CHAR_NL) ? CHAR_CR : CHAR_NL;
+ common->bsr_nlmin = (CHAR_CR < CHAR_NL) ? CHAR_CR : CHAR_NL;
+ }
#endif /* SUPPORT_UTF */
-ccend = bracketend(rootbacktrack.cc);
+ccend = bracketend(common->start);
/* Calculate the local space size on the stack. */
common->ovector_start = LIMIT_MATCH + sizeof(sljit_sw);
@@ -9071,12 +9855,12 @@ memset(common->optimized_cbracket, 0, re->top_bracket + 1);
memset(common->optimized_cbracket, 1, re->top_bracket + 1);
#endif
-SLJIT_ASSERT(*rootbacktrack.cc == OP_BRA && ccend[-(1 + LINK_SIZE)] == OP_KET);
+SLJIT_ASSERT(*common->start == OP_BRA && ccend[-(1 + LINK_SIZE)] == OP_KET);
#if defined DEBUG_FORCE_UNOPTIMIZED_CBRAS && DEBUG_FORCE_UNOPTIMIZED_CBRAS == 2
common->capture_last_ptr = common->ovector_start;
common->ovector_start += sizeof(sljit_sw);
#endif
-if (!check_opcode_types(common, rootbacktrack.cc, ccend))
+if (!check_opcode_types(common, common->start, ccend))
{
SLJIT_FREE(common->optimized_cbracket);
return;
@@ -9139,13 +9923,14 @@ if (common->capture_last_ptr != 0)
SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0));
common->cbra_ptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_sw);
-common->private_data_ptrs = (int *)SLJIT_MALLOC((ccend - rootbacktrack.cc) * sizeof(sljit_si));
+total_length = ccend - common->start;
+common->private_data_ptrs = (sljit_si *)SLJIT_MALLOC(total_length * (sizeof(sljit_si) + (common->has_then ? 1 : 0)));
if (!common->private_data_ptrs)
{
SLJIT_FREE(common->optimized_cbracket);
return;
}
-memset(common->private_data_ptrs, 0, (ccend - rootbacktrack.cc) * sizeof(int));
+memset(common->private_data_ptrs, 0, total_length * sizeof(sljit_si));
private_data_size = common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw);
set_private_data_ptrs(common, &private_data_size, ccend);
@@ -9158,15 +9943,21 @@ if (private_data_size > SLJIT_MAX_LOCAL_SIZE)
if (common->has_then)
{
- common->then_offsets = (pcre_uint8 *)SLJIT_MALLOC(ccend - rootbacktrack.cc);
- if (!common->then_offsets)
+ common->then_offsets = (pcre_uint8 *)(common->private_data_ptrs + total_length);
+ memset(common->then_offsets, 0, total_length);
+ set_then_offsets(common, common->start, NULL);
+ }
+
+if (common->read_only_data_size > 0)
+ {
+ common->read_only_data = (sljit_uw *)SLJIT_MALLOC(common->read_only_data_size);
+ if (common->read_only_data == NULL)
{
SLJIT_FREE(common->optimized_cbracket);
SLJIT_FREE(common->private_data_ptrs);
return;
}
- memset(common->then_offsets, 0, ccend - rootbacktrack.cc);
- set_then_offsets(common, rootbacktrack.cc, NULL);
+ common->read_only_data_ptr = common->read_only_data;
}
compiler = sljit_create_compiler();
@@ -9174,8 +9965,8 @@ if (!compiler)
{
SLJIT_FREE(common->optimized_cbracket);
SLJIT_FREE(common->private_data_ptrs);
- if (common->has_then)
- SLJIT_FREE(common->then_offsets);
+ if (common->read_only_data)
+ SLJIT_FREE(common->read_only_data);
return;
}
common->compiler = compiler;
@@ -9214,13 +10005,22 @@ if ((re->options & PCRE_ANCHORED) == 0)
if ((re->options & PCRE_NO_START_OPTIMIZE) == 0)
{
if (mode == JIT_COMPILE && fast_forward_first_n_chars(common, (re->options & PCRE_FIRSTLINE) != 0))
- { /* Do nothing */ }
+ {
+ /* If read_only_data is reallocated, we might have an allocation failure. */
+ if (common->read_only_data_size > 0 && common->read_only_data == NULL)
+ {
+ sljit_free_compiler(compiler);
+ SLJIT_FREE(common->optimized_cbracket);
+ SLJIT_FREE(common->private_data_ptrs);
+ return;
+ }
+ }
else if ((re->flags & PCRE_FIRSTSET) != 0)
fast_forward_first_char(common, (pcre_uchar)re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0, (re->options & PCRE_FIRSTLINE) != 0);
else if ((re->flags & PCRE_STARTLINE) != 0)
fast_forward_newline(common, (re->options & PCRE_FIRSTLINE) != 0);
else if ((re->flags & PCRE_STARTLINE) == 0 && study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0)
- fast_forward_start_bits(common, (sljit_uw)study->start_bits, (re->options & PCRE_FIRSTLINE) != 0);
+ fast_forward_start_bits(common, study->start_bits, (re->options & PCRE_FIRSTLINE) != 0);
}
}
else
@@ -9261,19 +10061,22 @@ if (mode == JIT_PARTIAL_SOFT_COMPILE)
else if (mode == JIT_PARTIAL_HARD_COMPILE)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
-compile_matchingpath(common, rootbacktrack.cc, ccend, &rootbacktrack);
+compile_matchingpath(common, common->start, ccend, &rootbacktrack);
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
{
sljit_free_compiler(compiler);
SLJIT_FREE(common->optimized_cbracket);
SLJIT_FREE(common->private_data_ptrs);
- if (common->has_then)
- SLJIT_FREE(common->then_offsets);
+ if (common->read_only_data)
+ SLJIT_FREE(common->read_only_data);
return;
}
-empty_match = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
-empty_match_found_label = LABEL();
+if (common->might_be_empty)
+ {
+ empty_match = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
+ empty_match_found_label = LABEL();
+ }
common->accept_label = LABEL();
if (common->accept != NULL)
@@ -9297,15 +10100,16 @@ if (mode != JIT_COMPILE)
return_with_partial_match(common, common->quit_label);
}
-empty_match_backtrack_label = LABEL();
+if (common->might_be_empty)
+ empty_match_backtrack_label = LABEL();
compile_backtrackingpath(common, rootbacktrack.top);
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
{
sljit_free_compiler(compiler);
SLJIT_FREE(common->optimized_cbracket);
SLJIT_FREE(common->private_data_ptrs);
- if (common->has_then)
- SLJIT_FREE(common->then_offsets);
+ if (common->read_only_data)
+ SLJIT_FREE(common->read_only_data);
return;
}
@@ -9333,10 +10137,19 @@ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_ptr);
if ((re->options & PCRE_ANCHORED) == 0)
{
- if ((re->options & PCRE_FIRSTLINE) == 0)
- CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop_label);
+ if (common->ff_newline_shortcut != NULL)
+ {
+ if ((re->options & PCRE_FIRSTLINE) == 0)
+ CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, common->ff_newline_shortcut);
+ /* There cannot be more newlines here. */
+ }
else
- CMPTO(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0, mainloop_label);
+ {
+ if ((re->options & PCRE_FIRSTLINE) == 0)
+ CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop_label);
+ else
+ CMPTO(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0, mainloop_label);
+ }
}
/* No more remaining characters. */
@@ -9351,15 +10164,18 @@ JUMPTO(SLJIT_JUMP, common->quit_label);
flush_stubs(common);
-JUMPHERE(empty_match);
-OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
-OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
-CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_backtrack_label);
-OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
-CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_found_label);
-OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
-CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found_label);
-JUMPTO(SLJIT_JUMP, empty_match_backtrack_label);
+if (common->might_be_empty)
+ {
+ JUMPHERE(empty_match);
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
+ CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_backtrack_label);
+ OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
+ CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_found_label);
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
+ CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found_label);
+ JUMPTO(SLJIT_JUMP, empty_match_backtrack_label);
+ }
common->currententry = common->entries;
common->local_exit = TRUE;
@@ -9373,8 +10189,8 @@ while (common->currententry != NULL)
sljit_free_compiler(compiler);
SLJIT_FREE(common->optimized_cbracket);
SLJIT_FREE(common->private_data_ptrs);
- if (common->has_then)
- SLJIT_FREE(common->then_offsets);
+ if (common->read_only_data)
+ SLJIT_FREE(common->read_only_data);
return;
}
flush_stubs(common);
@@ -9458,14 +10274,17 @@ if (common->reset_match != NULL)
JUMPTO(SLJIT_JUMP, reset_match_label);
}
#ifdef SUPPORT_UTF
-#ifndef COMPILE_PCRE32
+#ifdef COMPILE_PCRE8
if (common->utfreadchar != NULL)
{
set_jumps(common->utfreadchar, LABEL());
do_utfreadchar(common);
}
-#endif /* !COMPILE_PCRE32 */
-#ifdef COMPILE_PCRE8
+if (common->utfreadchar16 != NULL)
+ {
+ set_jumps(common->utfreadchar16, LABEL());
+ do_utfreadchar16(common);
+ }
if (common->utfreadtype8 != NULL)
{
set_jumps(common->utfreadtype8, LABEL());
@@ -9481,16 +10300,25 @@ if (common->getucd != NULL)
}
#endif
+SLJIT_ASSERT(common->read_only_data + (common->read_only_data_size >> SLJIT_WORD_SHIFT) == common->read_only_data_ptr);
SLJIT_FREE(common->optimized_cbracket);
SLJIT_FREE(common->private_data_ptrs);
-if (common->has_then)
- SLJIT_FREE(common->then_offsets);
executable_func = sljit_generate_code(compiler);
executable_size = sljit_get_generated_code_size(compiler);
+label_addr = common->label_addrs;
+while (label_addr != NULL)
+ {
+ *label_addr->addr = sljit_get_label_addr(label_addr->label);
+ label_addr = label_addr->next;
+ }
sljit_free_compiler(compiler);
if (executable_func == NULL)
+ {
+ if (common->read_only_data)
+ SLJIT_FREE(common->read_only_data);
return;
+ }
/* Reuse the function descriptor if possible. */
if ((extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && extra->executable_jit != NULL)
@@ -9510,8 +10338,10 @@ else
if (functions == NULL)
{
/* This case is highly unlikely since we just recently
- freed a lot of memory. Although not impossible. */
+ freed a lot of memory. Not impossible though. */
sljit_free_code(executable_func);
+ if (common->read_only_data)
+ SLJIT_FREE(common->read_only_data);
return;
}
memset(functions, 0, sizeof(executable_functions));
@@ -9522,6 +10352,7 @@ else
}
functions->executable_funcs[mode] = executable_func;
+functions->read_only_data[mode] = common->read_only_data;
functions->executable_sizes[mode] = executable_size;
}
@@ -9708,6 +10539,8 @@ for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++)
{
if (functions->executable_funcs[i] != NULL)
sljit_free_code(functions->executable_funcs[i]);
+ if (functions->read_only_data[i] != NULL)
+ SLJIT_FREE(functions->read_only_data[i]);
}
SLJIT_FREE(functions);
}
diff --git a/src/3rdparty/pcre/pcre_string_utils.c b/src/3rdparty/pcre/pcre_string_utils.c
index 2601ce385a..36f9b7b864 100644
--- a/src/3rdparty/pcre/pcre_string_utils.c
+++ b/src/3rdparty/pcre/pcre_string_utils.c
@@ -6,7 +6,7 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
- Copyright (c) 1997-2013 University of Cambridge
+ Copyright (c) 1997-2014 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -91,8 +91,8 @@ pcre_uchar c2;
while (*str1 != '\0' || *str2 != '\0')
{
- c1 = RAWUCHARINC(str1);
- c2 = RAWUCHARINC(str2);
+ c1 = UCHAR21INC(str1);
+ c2 = UCHAR21INC(str2);
if (c1 != c2)
return ((c1 > c2) << 1) - 1;
}
@@ -131,7 +131,7 @@ pcre_uchar c2;
while (*str1 != '\0' || *ustr2 != '\0')
{
- c1 = RAWUCHARINC(str1);
+ c1 = UCHAR21INC(str1);
c2 = (pcre_uchar)*ustr2++;
if (c1 != c2)
return ((c1 > c2) << 1) - 1;
diff --git a/src/3rdparty/pcre/pcre_study.c b/src/3rdparty/pcre/pcre_study.c
index 0478a00c1a..feb74115c6 100644
--- a/src/3rdparty/pcre/pcre_study.c
+++ b/src/3rdparty/pcre/pcre_study.c
@@ -879,9 +879,6 @@ do
case OP_SOM:
case OP_THEN:
case OP_THEN_ARG:
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
- case OP_XCLASS:
-#endif
return SSB_FAIL;
/* We can ignore word boundary tests. */
@@ -1257,6 +1254,16 @@ do
with a value >= 0xc4 is a potentially valid starter because it starts a
character with a value > 255. */
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ case OP_XCLASS:
+ if ((tcode[1 + LINK_SIZE] & XCL_HASPROP) != 0)
+ return SSB_FAIL;
+ /* All bits are set. */
+ if ((tcode[1 + LINK_SIZE] & XCL_MAP) == 0 && (tcode[1 + LINK_SIZE] & XCL_NOT) != 0)
+ return SSB_FAIL;
+#endif
+ /* Fall through */
+
case OP_NCLASS:
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
if (utf)
@@ -1273,8 +1280,21 @@ do
case OP_CLASS:
{
pcre_uint8 *map;
- tcode++;
- map = (pcre_uint8 *)tcode;
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ map = NULL;
+ if (*tcode == OP_XCLASS)
+ {
+ if ((tcode[1 + LINK_SIZE] & XCL_MAP) != 0)
+ map = (pcre_uint8 *)(tcode + 1 + LINK_SIZE + 1);
+ tcode += GET(tcode, 1);
+ }
+ else
+#endif
+ {
+ tcode++;
+ map = (pcre_uint8 *)tcode;
+ tcode += 32 / sizeof(pcre_uchar);
+ }
/* In UTF-8 mode, the bits in a bit map correspond to character
values, not to byte values. However, the bit map we are constructing is
@@ -1282,31 +1302,35 @@ do
value is > 127. In fact, there are only two possible starting bytes for
characters in the range 128 - 255. */
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
- if (utf)
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ if (map != NULL)
+#endif
{
- for (c = 0; c < 16; c++) start_bits[c] |= map[c];
- for (c = 128; c < 256; c++)
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+ if (utf)
{
- if ((map[c/8] && (1 << (c&7))) != 0)
+ for (c = 0; c < 16; c++) start_bits[c] |= map[c];
+ for (c = 128; c < 256; c++)
{
- int d = (c >> 6) | 0xc0; /* Set bit for this starter */
- start_bits[d/8] |= (1 << (d&7)); /* and then skip on to the */
- c = (c & 0xc0) + 0x40 - 1; /* next relevant character. */
+ if ((map[c/8] && (1 << (c&7))) != 0)
+ {
+ int d = (c >> 6) | 0xc0; /* Set bit for this starter */
+ start_bits[d/8] |= (1 << (d&7)); /* and then skip on to the */
+ c = (c & 0xc0) + 0x40 - 1; /* next relevant character. */
+ }
}
}
- }
- else
+ else
#endif
- {
- /* In non-UTF-8 mode, the two bit maps are completely compatible. */
- for (c = 0; c < 32; c++) start_bits[c] |= map[c];
+ {
+ /* In non-UTF-8 mode, the two bit maps are completely compatible. */
+ for (c = 0; c < 32; c++) start_bits[c] |= map[c];
+ }
}
/* Advance past the bit map, and act on what follows. For a zero
minimum repeat, continue; otherwise stop processing. */
- tcode += 32 / sizeof(pcre_uchar);
switch (*tcode)
{
case OP_CRSTAR:
diff --git a/src/3rdparty/pcre/pcre_xclass.c b/src/3rdparty/pcre/pcre_xclass.c
index dce8580a3d..036b6e734a 100644
--- a/src/3rdparty/pcre/pcre_xclass.c
+++ b/src/3rdparty/pcre/pcre_xclass.c
@@ -81,6 +81,11 @@ additional data. */
if (c < 256)
{
+ if ((*data & XCL_HASPROP) == 0)
+ {
+ if ((*data & XCL_MAP) == 0) return negated;
+ return (((pcre_uint8 *)(data + 1))[c/8] & (1 << (c&7))) != 0;
+ }
if ((*data & XCL_MAP) != 0 &&
(((pcre_uint8 *)(data + 1))[c/8] & (1 << (c&7))) != 0)
return !negated; /* char found */
diff --git a/src/3rdparty/pcre/sljit/sljitConfig.h b/src/3rdparty/pcre/sljit/sljitConfig.h
index 4f0fe4463a..4d93f4f78c 100644
--- a/src/3rdparty/pcre/sljit/sljitConfig.h
+++ b/src/3rdparty/pcre/sljit/sljitConfig.h
@@ -44,9 +44,11 @@
/* #define SLJIT_CONFIG_ARM_V5 1 */
/* #define SLJIT_CONFIG_ARM_V7 1 */
/* #define SLJIT_CONFIG_ARM_THUMB2 1 */
+/* #define SLJIT_CONFIG_ARM_64 1 */
/* #define SLJIT_CONFIG_PPC_32 1 */
/* #define SLJIT_CONFIG_PPC_64 1 */
/* #define SLJIT_CONFIG_MIPS_32 1 */
+/* #define SLJIT_CONFIG_MIPS_64 1 */
/* #define SLJIT_CONFIG_SPARC_32 1 */
/* #define SLJIT_CONFIG_TILEGX 1 */
@@ -106,6 +108,13 @@
#define SLJIT_VERBOSE 1
#endif
-/* See the beginning of sljitConfigInternal.h */
+/*
+ SLJIT_IS_FPU_AVAILABLE
+ The availability of the FPU can be controlled by SLJIT_IS_FPU_AVAILABLE.
+ zero value - FPU is NOT present.
+ nonzero value - FPU is present.
+*/
+
+/* For further configurations, see the beginning of sljitConfigInternal.h */
#endif
diff --git a/src/3rdparty/pcre/sljit/sljitConfigInternal.h b/src/3rdparty/pcre/sljit/sljitConfigInternal.h
index af455df063..89be38bd46 100644
--- a/src/3rdparty/pcre/sljit/sljitConfigInternal.h
+++ b/src/3rdparty/pcre/sljit/sljitConfigInternal.h
@@ -59,9 +59,11 @@
|| (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \
|| (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
|| (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
+ || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|| (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
|| (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
|| (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
+ || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
|| (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
|| (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) \
|| (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
@@ -75,10 +77,12 @@
+ (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \
+ (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
+ (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
+ + (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
+ (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
+ (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
+ (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) \
+ (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
+ + (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
+ (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
+ (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
+ (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2
@@ -102,12 +106,16 @@
#else
#define SLJIT_CONFIG_ARM_V5 1
#endif
+#elif defined (__aarch64__)
+#define SLJIT_CONFIG_ARM_64 1
#elif defined(__ppc64__) || defined(__powerpc64__) || defined(_ARCH_PPC64) || (defined(_POWER) && defined(__64BIT__))
#define SLJIT_CONFIG_PPC_64 1
#elif defined(__ppc__) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(_ARCH_PWR) || defined(_ARCH_PWR2) || defined(_POWER)
#define SLJIT_CONFIG_PPC_32 1
#elif defined(__mips__) && !defined(_LP64)
#define SLJIT_CONFIG_MIPS_32 1
+#elif defined(__mips64)
+#define SLJIT_CONFIG_MIPS_64 1
#elif defined(__sparc__) || defined(__sparc)
#define SLJIT_CONFIG_SPARC_32 1
#elif defined(__tilegx__)
@@ -275,7 +283,9 @@ typedef signed int sljit_si;
typedef unsigned long int sljit_uw;
typedef long int sljit_sw;
#elif !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
+ && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
&& !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
+ && !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
&& !(defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX)
#define SLJIT_32BIT_ARCHITECTURE 1
#define SLJIT_WORD_SHIFT 2
@@ -353,13 +363,18 @@ typedef double sljit_d;
#if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN)
-/* These macros are useful for the application. */
+/* These macros are useful for the applications. */
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
- || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
- || (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+ || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+
+#ifdef __LITTLE_ENDIAN__
+#define SLJIT_LITTLE_ENDIAN 1
+#else
#define SLJIT_BIG_ENDIAN 1
+#endif
-#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
+ || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
#ifdef __MIPSEL__
#define SLJIT_LITTLE_ENDIAN 1
@@ -367,6 +382,10 @@ typedef double sljit_d;
#define SLJIT_BIG_ENDIAN 1
#endif
+#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+
+#define SLJIT_BIG_ENDIAN 1
+
#else
#define SLJIT_LITTLE_ENDIAN 1
#endif
@@ -383,7 +402,8 @@ typedef double sljit_d;
#endif
#ifndef SLJIT_INDIRECT_CALL
-#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) || (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32 && defined _AIX)
+#if ((defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) && (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN)) \
+ || ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && defined _AIX)
/* It seems certain ppc compilers use an indirect addressing for functions
which makes things complicated. */
#define SLJIT_INDIRECT_CALL 1
@@ -420,6 +440,7 @@ typedef double sljit_d;
|| (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
|| (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
|| (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
+ || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|| (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
|| (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
#define SLJIT_UNALIGNED 1
diff --git a/src/3rdparty/pcre/sljit/sljitLir.c b/src/3rdparty/pcre/sljit/sljitLir.c
index 53d208a69d..1acecba8b4 100644
--- a/src/3rdparty/pcre/sljit/sljitLir.c
+++ b/src/3rdparty/pcre/sljit/sljitLir.c
@@ -83,13 +83,13 @@
#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
#define GET_OPCODE(op) \
- ((op) & ~(SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))
+ ((op) & ~(SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))
#define GET_FLAGS(op) \
- ((op) & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C))
+ ((op) & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C))
#define GET_ALL_FLAGS(op) \
- ((op) & (SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))
+ ((op) & (SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))
#define TYPE_CAST_NEEDED(op) \
(((op) >= SLJIT_MOV_UB && (op) <= SLJIT_MOV_SH) || ((op) >= SLJIT_MOVU_UB && (op) <= SLJIT_MOVU_SH))
@@ -102,6 +102,16 @@
#define ABUF_SIZE 4096
#endif
+/* Parameter parsing. */
+#define REG_MASK 0x3f
+#define OFFS_REG(reg) (((reg) >> 8) & REG_MASK)
+#define OFFS_REG_MASK (REG_MASK << 8)
+#define TO_OFFS_REG(reg) ((reg) << 8)
+/* When reg cannot be unused. */
+#define FAST_IS_REG(reg) ((reg) <= REG_MASK)
+/* When reg can be unused. */
+#define SLOW_IS_REG(reg) ((reg) > 0 && (reg) <= REG_MASK)
+
/* Jump flags. */
#define JUMP_LABEL 0x1
#define JUMP_ADDR 0x2
@@ -127,39 +137,59 @@
#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
# define IS_COND 0x04
# define IS_BL 0x08
- /* cannot be encoded as branch */
-# define B_TYPE0 0x00
/* conditional + imm8 */
-# define B_TYPE1 0x10
+# define PATCH_TYPE1 0x10
/* conditional + imm20 */
-# define B_TYPE2 0x20
+# define PATCH_TYPE2 0x20
/* IT + imm24 */
-# define B_TYPE3 0x30
+# define PATCH_TYPE3 0x30
/* imm11 */
-# define B_TYPE4 0x40
+# define PATCH_TYPE4 0x40
/* imm24 */
-# define B_TYPE5 0x50
+# define PATCH_TYPE5 0x50
/* BL + imm24 */
-# define BL_TYPE6 0x60
+# define PATCH_BL 0x60
/* 0xf00 cc code for branches */
#endif
+#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
+# define IS_COND 0x004
+# define IS_CBZ 0x008
+# define IS_BL 0x010
+# define PATCH_B 0x020
+# define PATCH_COND 0x040
+# define PATCH_ABS48 0x080
+# define PATCH_ABS64 0x100
+#endif
+
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
-# define UNCOND_B 0x04
-# define PATCH_B 0x08
-# define ABSOLUTE_B 0x10
+# define IS_COND 0x004
+# define IS_CALL 0x008
+# define PATCH_B 0x010
+# define PATCH_ABS_B 0x020
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+# define PATCH_ABS32 0x040
+# define PATCH_ABS48 0x080
+#endif
+# define REMOVE_COND 0x100
#endif
-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-# define IS_MOVABLE 0x04
-# define IS_JAL 0x08
-# define IS_BIT26_COND 0x10
-# define IS_BIT16_COND 0x20
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+# define IS_MOVABLE 0x004
+# define IS_JAL 0x008
+# define IS_CALL 0x010
+# define IS_BIT26_COND 0x020
+# define IS_BIT16_COND 0x040
# define IS_COND (IS_BIT26_COND | IS_BIT16_COND)
-# define PATCH_B 0x40
-# define PATCH_J 0x80
+# define PATCH_B 0x080
+# define PATCH_J 0x100
+
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+# define PATCH_ABS32 0x200
+# define PATCH_ABS48 0x400
+#endif
/* instruction types */
# define MOVABLE_INS 0
@@ -167,15 +197,15 @@
/* no destination (i.e: store) */
# define UNMOVABLE_INS 32
/* FPU status register */
-# define FCSR_FCC 33
+# define FCSR_FCC 33
#endif
#if (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX)
-# define IS_JAL 0x04
-# define IS_COND 0x08
+# define IS_JAL 0x04
+# define IS_COND 0x08
-# define PATCH_B 0x10
-# define PATCH_J 0x20
+# define PATCH_B 0x10
+# define PATCH_J 0x20
#endif
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
@@ -215,9 +245,13 @@
#endif
#endif
+#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
+#define SLJIT_HAS_VARIABLE_LOCALS_OFFSET 1
+#endif
+
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
#define SLJIT_HAS_FIXED_LOCALS_OFFSET 1
-#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
+#ifdef _AIX
#define FIXED_LOCALS_OFFSET ((6 + 8) * sizeof(sljit_sw))
#else
#define FIXED_LOCALS_OFFSET (2 * sizeof(sljit_sw))
@@ -234,6 +268,11 @@
#define FIXED_LOCALS_OFFSET (4 * sizeof(sljit_sw))
#endif
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+#define SLJIT_HAS_FIXED_LOCALS_OFFSET 1
+#define FIXED_LOCALS_OFFSET 0
+#endif
+
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
#define SLJIT_HAS_FIXED_LOCALS_OFFSET 1
#define FIXED_LOCALS_OFFSET (23 * sizeof(sljit_sw))
@@ -343,7 +382,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void)
compiler->cpool_diff = 0xffffffff;
#endif
-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
compiler->delay_slot = UNMOVABLE_INS;
#endif
@@ -418,8 +457,6 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sl
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target)
{
if (SLJIT_LIKELY(!!jump)) {
- SLJIT_ASSERT(jump->flags & SLJIT_REWRITABLE_JUMP);
-
jump->flags &= ~JUMP_LABEL;
jump->flags |= JUMP_ADDR;
jump->u.target = target;
@@ -534,7 +571,7 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
}
#define ADDRESSING_DEPENDS_ON(exp, reg) \
- (((exp) & SLJIT_MEM) && (((exp) & 0xf) == reg || (((exp) >> 4) & 0xf) == reg))
+ (((exp) & SLJIT_MEM) && (((exp) & REG_MASK) == reg || OFFS_REG(exp) == reg))
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
#define FUNCTION_CHECK_OP() \
@@ -548,41 +585,43 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
case SLJIT_SHL: \
case SLJIT_LSHR: \
case SLJIT_ASHR: \
- SLJIT_ASSERT(!(op & (SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C))); \
+ SLJIT_ASSERT(!(op & (SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C))); \
break; \
case SLJIT_NEG: \
- SLJIT_ASSERT(!(op & (SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_C))); \
+ SLJIT_ASSERT(!(op & (SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))); \
break; \
case SLJIT_MUL: \
- SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_C))); \
+ SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))); \
break; \
case SLJIT_CMPD: \
SLJIT_ASSERT(!(op & (SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
SLJIT_ASSERT((op & (SLJIT_SET_E | SLJIT_SET_S))); \
break; \
case SLJIT_ADD: \
- SLJIT_ASSERT(!(op & (SLJIT_SET_S | SLJIT_SET_U))); \
+ SLJIT_ASSERT(!(op & (SLJIT_SET_U | SLJIT_SET_S))); \
break; \
case SLJIT_SUB: \
break; \
case SLJIT_ADDC: \
case SLJIT_SUBC: \
- SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O))); \
+ SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O))); \
break; \
case SLJIT_BREAKPOINT: \
case SLJIT_NOP: \
case SLJIT_UMUL: \
case SLJIT_SMUL: \
case SLJIT_MOV: \
+ case SLJIT_MOV_UI: \
case SLJIT_MOV_P: \
case SLJIT_MOVU: \
+ case SLJIT_MOVU_UI: \
case SLJIT_MOVU_P: \
/* Nothing allowed */ \
- SLJIT_ASSERT(!(op & (SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
+ SLJIT_ASSERT(!(op & (SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
break; \
default: \
/* Only SLJIT_INT_OP or SLJIT_SINGLE_OP is allowed. */ \
- SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
+ SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
break; \
}
@@ -600,12 +639,12 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
else if ((p) == (SLJIT_MEM1(SLJIT_LOCALS_REG))) \
SLJIT_ASSERT((i) >= 0 && (i) < compiler->logical_local_size); \
else if ((p) & SLJIT_MEM) { \
- SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & 0xf)); \
- if ((p) & 0xf0) { \
- SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(((p) >> 4) & 0xf)); \
+ SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & REG_MASK)); \
+ if ((p) & OFFS_REG_MASK) { \
+ SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(OFFS_REG(p))); \
SLJIT_ASSERT(!((i) & ~0x3)); \
} \
- SLJIT_ASSERT(((p) >> 9) == 0); \
+ SLJIT_ASSERT(!((p) & ~(SLJIT_MEM | SLJIT_IMM | REG_MASK | OFFS_REG_MASK))); \
} \
else \
SLJIT_ASSERT_STOP();
@@ -617,12 +656,12 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
else if ((p) == (SLJIT_MEM1(SLJIT_LOCALS_REG))) \
SLJIT_ASSERT((i) >= 0 && (i) < compiler->logical_local_size); \
else if ((p) & SLJIT_MEM) { \
- SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & 0xf)); \
- if ((p) & 0xf0) { \
- SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(((p) >> 4) & 0xf)); \
+ SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & REG_MASK)); \
+ if ((p) & OFFS_REG_MASK) { \
+ SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(OFFS_REG(p))); \
SLJIT_ASSERT(!((i) & ~0x3)); \
} \
- SLJIT_ASSERT(((p) >> 9) == 0); \
+ SLJIT_ASSERT(!((p) & ~(SLJIT_MEM | SLJIT_IMM | REG_MASK | OFFS_REG_MASK))); \
} \
else \
SLJIT_ASSERT_STOP();
@@ -631,23 +670,23 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
if ((p) >= SLJIT_FLOAT_REG1 && (p) <= SLJIT_FLOAT_REG6) \
SLJIT_ASSERT(i == 0); \
else if ((p) & SLJIT_MEM) { \
- SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & 0xf)); \
- if ((p) & 0xf0) { \
- SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(((p) >> 4) & 0xf)); \
- SLJIT_ASSERT(((p) & 0xf0) != (SLJIT_LOCALS_REG << 4) && !(i & ~0x3)); \
+ SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & REG_MASK)); \
+ if ((p) & OFFS_REG_MASK) { \
+ SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(OFFS_REG(p))); \
+ SLJIT_ASSERT(((p) & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_LOCALS_REG) && !(i & ~0x3)); \
} else \
- SLJIT_ASSERT((((p) >> 4) & 0xf) == 0); \
- SLJIT_ASSERT(((p) >> 9) == 0); \
+ SLJIT_ASSERT(OFFS_REG(p) == 0); \
+ SLJIT_ASSERT(!((p) & ~(SLJIT_MEM | SLJIT_IMM | REG_MASK | OFFS_REG_MASK))); \
} \
else \
SLJIT_ASSERT_STOP();
#define FUNCTION_CHECK_OP1() \
if (GET_OPCODE(op) >= SLJIT_MOVU && GET_OPCODE(op) <= SLJIT_MOVU_P) { \
- SLJIT_ASSERT(!(src & SLJIT_MEM) || (src & 0xf) != SLJIT_LOCALS_REG); \
- SLJIT_ASSERT(!(dst & SLJIT_MEM) || (dst & 0xf) != SLJIT_LOCALS_REG); \
- if ((src & SLJIT_MEM) && (src & 0xf)) \
- SLJIT_ASSERT((dst & 0xf) != (src & 0xf) && ((dst >> 4) & 0xf) != (src & 0xf)); \
+ SLJIT_ASSERT(!(src & SLJIT_MEM) || (src & REG_MASK) != SLJIT_LOCALS_REG); \
+ SLJIT_ASSERT(!(dst & SLJIT_MEM) || (dst & REG_MASK) != SLJIT_LOCALS_REG); \
+ if ((src & SLJIT_MEM) && (src & REG_MASK)) \
+ SLJIT_ASSERT((dst & REG_MASK) != (src & REG_MASK) && OFFS_REG(dst) != (src & REG_MASK)); \
}
#endif
@@ -670,7 +709,7 @@ static char* freg_names[] = {
(char*)"f4", (char*)"f5", (char*)"f6"
};
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
#ifdef _WIN64
# define SLJIT_PRINT_D "I64"
#else
@@ -684,18 +723,18 @@ static char* freg_names[] = {
if ((p) & SLJIT_IMM) \
fprintf(compiler->verbose, "#%" SLJIT_PRINT_D "d", (i)); \
else if ((p) & SLJIT_MEM) { \
- if ((p) & 0xf) { \
+ if ((p) & REG_MASK) { \
if (i) { \
- if (((p) >> 4) & 0xf) \
- fprintf(compiler->verbose, "[%s + %s * %d]", reg_names[(p) & 0xF], reg_names[((p) >> 4)& 0xF], 1 << (i)); \
+ if ((p) & OFFS_REG_MASK) \
+ fprintf(compiler->verbose, "[%s + %s * %d]", reg_names[(p) & REG_MASK], reg_names[OFFS_REG(p)], 1 << (i)); \
else \
- fprintf(compiler->verbose, "[%s + #%" SLJIT_PRINT_D "d]", reg_names[(p) & 0xF], (i)); \
+ fprintf(compiler->verbose, "[%s + #%" SLJIT_PRINT_D "d]", reg_names[(p) & REG_MASK], (i)); \
} \
else { \
- if (((p) >> 4) & 0xf) \
- fprintf(compiler->verbose, "[%s + %s]", reg_names[(p) & 0xF], reg_names[((p) >> 4)& 0xF]); \
+ if ((p) & OFFS_REG_MASK) \
+ fprintf(compiler->verbose, "[%s + %s]", reg_names[(p) & REG_MASK], reg_names[OFFS_REG(p)]); \
else \
- fprintf(compiler->verbose, "[%s]", reg_names[(p) & 0xF]); \
+ fprintf(compiler->verbose, "[%s]", reg_names[(p) & REG_MASK]); \
} \
} \
else \
@@ -704,18 +743,18 @@ static char* freg_names[] = {
fprintf(compiler->verbose, "%s", reg_names[p]);
#define sljit_verbose_fparam(p, i) \
if ((p) & SLJIT_MEM) { \
- if ((p) & 0xf) { \
+ if ((p) & REG_MASK) { \
if (i) { \
- if (((p) >> 4) & 0xf) \
- fprintf(compiler->verbose, "[%s + %s * %d]", reg_names[(p) & 0xF], reg_names[((p) >> 4)& 0xF], 1 << (i)); \
+ if ((p) & OFFS_REG_MASK) \
+ fprintf(compiler->verbose, "[%s + %s * %d]", reg_names[(p) & REG_MASK], reg_names[OFFS_REG(p)], 1 << (i)); \
else \
- fprintf(compiler->verbose, "[%s + #%" SLJIT_PRINT_D "d]", reg_names[(p) & 0xF], (i)); \
+ fprintf(compiler->verbose, "[%s + #%" SLJIT_PRINT_D "d]", reg_names[(p) & REG_MASK], (i)); \
} \
else { \
- if (((p) >> 4) & 0xF) \
- fprintf(compiler->verbose, "[%s + %s]", reg_names[(p) & 0xF], reg_names[((p) >> 4)& 0xF]); \
+ if ((p) & OFFS_REG_MASK) \
+ fprintf(compiler->verbose, "[%s + %s]", reg_names[(p) & REG_MASK], reg_names[OFFS_REG(p)]); \
else \
- fprintf(compiler->verbose, "[%s]", reg_names[(p) & 0xF]); \
+ fprintf(compiler->verbose, "[%s]", reg_names[(p) & REG_MASK]); \
} \
} \
else \
@@ -941,7 +980,7 @@ static SLJIT_INLINE void check_sljit_emit_op1(struct sljit_compiler *compiler, s
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " %s%s%s%s%s%s%s%s ", !(op & SLJIT_INT_OP) ? "" : "i", op_names[GET_OPCODE(op)],
- !(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_S) ? "" : ".s", !(op & SLJIT_SET_U) ? "" : ".u",
+ !(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_U) ? "" : ".u", !(op & SLJIT_SET_S) ? "" : ".s",
!(op & SLJIT_SET_O) ? "" : ".o", !(op & SLJIT_SET_C) ? "" : ".c", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k");
sljit_verbose_param(dst, dstw);
fprintf(compiler->verbose, ", ");
@@ -983,7 +1022,7 @@ static SLJIT_INLINE void check_sljit_emit_op2(struct sljit_compiler *compiler, s
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " %s%s%s%s%s%s%s%s ", !(op & SLJIT_INT_OP) ? "" : "i", op_names[GET_OPCODE(op)],
- !(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_S) ? "" : ".s", !(op & SLJIT_SET_U) ? "" : ".u",
+ !(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_U) ? "" : ".u", !(op & SLJIT_SET_S) ? "" : ".s",
!(op & SLJIT_SET_O) ? "" : ".o", !(op & SLJIT_SET_C) ? "" : ".c", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k");
sljit_verbose_param(dst, dstw);
fprintf(compiler->verbose, ", ");
@@ -1225,7 +1264,7 @@ static SLJIT_INLINE void check_sljit_emit_op_flags(struct sljit_compiler *compil
SLJIT_ASSERT(type >= SLJIT_C_EQUAL && type < SLJIT_JUMP);
SLJIT_ASSERT(op == SLJIT_MOV || GET_OPCODE(op) == SLJIT_MOV_UI || GET_OPCODE(op) == SLJIT_MOV_SI
|| (GET_OPCODE(op) >= SLJIT_AND && GET_OPCODE(op) <= SLJIT_XOR));
- SLJIT_ASSERT((op & (SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C)) == 0);
+ SLJIT_ASSERT((op & (SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C)) == 0);
SLJIT_ASSERT((op & (SLJIT_SET_E | SLJIT_KEEP_FLAGS)) != (SLJIT_SET_E | SLJIT_KEEP_FLAGS));
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
if (GET_OPCODE(op) < SLJIT_ADD) {
@@ -1340,24 +1379,28 @@ static SLJIT_INLINE sljit_si emit_mov_before_return(struct sljit_compiler *compi
#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
# include "sljitNativeX86_common.c"
#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
-# include "sljitNativeARM_v5.c"
+# include "sljitNativeARM_32.c"
#elif (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
-# include "sljitNativeARM_v5.c"
+# include "sljitNativeARM_32.c"
#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
-# include "sljitNativeARM_Thumb2.c"
+# include "sljitNativeARM_T2_32.c"
+#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
+# include "sljitNativeARM_64.c"
#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
# include "sljitNativePPC_common.c"
#elif (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
# include "sljitNativePPC_common.c"
#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
# include "sljitNativeMIPS_common.c"
+#elif (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+# include "sljitNativeMIPS_common.c"
#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
# include "sljitNativeSPARC_common.c"
#elif (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX)
-# include "sljitNativeTILEGX.c"
+# include "sljitNativeTILEGX_64.c"
#endif
-#if !(defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#if !(defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) && !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_si type,
sljit_si src1, sljit_sw src1w,
@@ -1371,6 +1414,19 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w);
condition = type & 0xff;
+#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
+ if ((condition == SLJIT_C_EQUAL || condition == SLJIT_C_NOT_EQUAL)) {
+ if ((src1 & SLJIT_IMM) && !src1w) {
+ src1 = src2;
+ src1w = src2w;
+ src2 = SLJIT_IMM;
+ src2w = 0;
+ }
+ if ((src2 & SLJIT_IMM) && !src2w)
+ return emit_cmp_to0(compiler, type, src1, src1w);
+ }
+#endif
+
if (SLJIT_UNLIKELY((src1 & SLJIT_IMM) && !(src2 & SLJIT_IMM))) {
/* Immediate is prefered as second argument by most architectures. */
switch (condition) {
diff --git a/src/3rdparty/pcre/sljit/sljitLir.h b/src/3rdparty/pcre/sljit/sljitLir.h
index 920689d2ec..e2cd21846d 100644
--- a/src/3rdparty/pcre/sljit/sljitLir.h
+++ b/src/3rdparty/pcre/sljit/sljitLir.h
@@ -265,13 +265,19 @@ struct sljit_compiler {
sljit_sw cache_argw;
#endif
+#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
+ sljit_si locals_offset;
+ sljit_si cache_arg;
+ sljit_sw cache_argw;
+#endif
+
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
sljit_sw imm;
sljit_si cache_arg;
sljit_sw cache_argw;
#endif
-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
sljit_si delay_slot;
sljit_si cache_arg;
sljit_sw cache_argw;
@@ -478,11 +484,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
/* Register output: simply the name of the register.
For destination, you can use SLJIT_UNUSED as well. */
-#define SLJIT_MEM 0x100
+#define SLJIT_MEM 0x80
#define SLJIT_MEM0() (SLJIT_MEM)
#define SLJIT_MEM1(r1) (SLJIT_MEM | (r1))
-#define SLJIT_MEM2(r1, r2) (SLJIT_MEM | (r1) | ((r2) << 4))
-#define SLJIT_IMM 0x200
+#define SLJIT_MEM2(r1, r2) (SLJIT_MEM | (r1) | ((r2) << 8))
+#define SLJIT_IMM 0x40
/* Set 32 bit operation mode (I) on 64 bit CPUs. The flag is totally ignored on
32 bit CPUs. If this flag is set for an arithmetic operation, it uses only the
@@ -494,12 +500,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
is specified, all register arguments must be the result of other operations with
the same SLJIT_INT_OP flag. In other words, although a register can hold either
a 64 or 32 bit value, these values cannot be mixed. The only exceptions are
- SLJIT_IMOV and SLJIT_IMOVU (SLJIT_MOV_SI/SLJIT_MOV_UI/SLJIT_MOVU_SI/SLJIT_MOV_UI
- with SLJIT_INT_OP flag) which can convert any source argument to SLJIT_INT_OP
- compatible result. This conversion might be unnecessary on some CPUs like x86-64,
- since the upper 32 bit is always ignored. In this case SLJIT is clever enough
- to not generate any instructions if the source and destination operands are the
- same registers. Affects sljit_emit_op0, sljit_emit_op1 and sljit_emit_op2. */
+ SLJIT_IMOV and SLJIT_IMOVU (SLJIT_MOV_SI/SLJIT_MOVU_SI with SLJIT_INT_OP flag)
+ which can convert any source argument to SLJIT_INT_OP compatible result. This
+ conversion might be unnecessary on some CPUs like x86-64, since the upper 32
+ bit is always ignored. In this case SLJIT is clever enough to not generate any
+ instructions if the source and destination operands are the same registers.
+ Affects sljit_emit_op0, sljit_emit_op1 and sljit_emit_op2. */
#define SLJIT_INT_OP 0x100
/* Single precision mode (SP). This flag is similar to SLJIT_INT_OP, just
@@ -525,10 +531,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
/* Set Equal (Zero) status flag (E). */
#define SLJIT_SET_E 0x0200
+/* Set unsigned status flag (U). */
+#define SLJIT_SET_U 0x0400
/* Set signed status flag (S). */
-#define SLJIT_SET_S 0x0400
-/* Set unsgined status flag (U). */
-#define SLJIT_SET_U 0x0800
+#define SLJIT_SET_S 0x0800
/* Set signed overflow flag (O). */
#define SLJIT_SET_O 0x1000
/* Set carry flag (C).
@@ -575,7 +581,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op);
/* Notes for MOV instructions:
- U = Mov with update (post form). If source or destination defined as SLJIT_MEM1(r1)
+ U = Mov with update (pre form). If source or destination defined as SLJIT_MEM1(r1)
or SLJIT_MEM2(r1, r2), r1 is increased by the sum of r2 and the constant argument
UB = unsigned byte (8 bit)
SB = signed byte (8 bit)
@@ -602,7 +608,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
/* Flags: I - (never set any flags)
Note: see SLJIT_INT_OP for further details. */
#define SLJIT_MOV_UI 11
-/* No SLJIT_INT_OP form, since it the same as SLJIT_IMOVU. */
+/* No SLJIT_INT_OP form, since it is the same as SLJIT_IMOV. */
/* Flags: I - (never set any flags)
Note: see SLJIT_INT_OP for further details. */
#define SLJIT_MOV_SI 12
@@ -626,7 +632,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
/* Flags: I - (never set any flags)
Note: see SLJIT_INT_OP for further details. */
#define SLJIT_MOVU_UI 19
-/* No SLJIT_INT_OP form, since it the same as SLJIT_IMOVU. */
+/* No SLJIT_INT_OP form, since it is the same as SLJIT_IMOVU. */
/* Flags: I - (never set any flags)
Note: see SLJIT_INT_OP for further details. */
#define SLJIT_MOVU_SI 20
@@ -656,7 +662,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
/* Flags: I | C | K */
#define SLJIT_ADDC 26
#define SLJIT_IADDC (SLJIT_ADDC | SLJIT_INT_OP)
-/* Flags: I | E | S | U | O | C | K */
+/* Flags: I | E | U | S | O | C | K */
#define SLJIT_SUB 27
#define SLJIT_ISUB (SLJIT_SUB | SLJIT_INT_OP)
/* Flags: I | C | K */
@@ -851,8 +857,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile
/* Set the destination of the jump to this label. */
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label);
-/* Only for jumps defined with SLJIT_REWRITABLE_JUMP flag.
- Note: use sljit_emit_ijump for fixed jumps. */
+/* Set the destination address of the jump to this label. */
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target);
/* Call function or jump anywhere. Both direct and indirect form
diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_v5.c b/src/3rdparty/pcre/sljit/sljitNativeARM_32.c
index e3ca3d9bb1..6747c4f617 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeARM_v5.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeARM_32.c
@@ -1379,54 +1379,57 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si inp_fl
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MVN_DP, 0, reg, SLJIT_UNUSED, imm));
return -1;
}
- return (inp_flags & ARG_TEST) ? SLJIT_SUCCESS : 0;
+ return 0;
}
SLJIT_ASSERT(arg & SLJIT_MEM);
/* Fast loads/stores. */
- if (arg & 0xf) {
- if (!(arg & 0xf0)) {
- if (IS_TYPE1_TRANSFER(inp_flags)) {
- if (argw >= 0 && argw <= 0xfff) {
- if (inp_flags & ARG_TEST)
- return 1;
- EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, argw));
- return -1;
- }
- if (argw < 0 && argw >= -0xfff) {
- if (inp_flags & ARG_TEST)
- return 1;
- EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & 0xf, -argw));
- return -1;
- }
- }
- else {
- if (argw >= 0 && argw <= 0xff) {
- if (inp_flags & ARG_TEST)
- return 1;
- EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, TYPE2_TRANSFER_IMM(argw)));
- return -1;
- }
- if (argw < 0 && argw >= -0xff) {
- if (inp_flags & ARG_TEST)
- return 1;
- argw = -argw;
- EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & 0xf, TYPE2_TRANSFER_IMM(argw)));
- return -1;
- }
- }
+ if (!(arg & REG_MASK))
+ return 0;
+
+ if (arg & OFFS_REG_MASK) {
+ if ((argw & 0x3) != 0 && !IS_TYPE1_TRANSFER(inp_flags))
+ return 0;
+
+ if (inp_flags & ARG_TEST)
+ return 1;
+ EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK,
+ RM(OFFS_REG(arg)) | (IS_TYPE1_TRANSFER(inp_flags) ? SRC2_IMM : 0) | ((argw & 0x3) << 7)));
+ return -1;
+ }
+
+ if (IS_TYPE1_TRANSFER(inp_flags)) {
+ if (argw >= 0 && argw <= 0xfff) {
+ if (inp_flags & ARG_TEST)
+ return 1;
+ EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, argw));
+ return -1;
+ }
+ if (argw < 0 && argw >= -0xfff) {
+ if (inp_flags & ARG_TEST)
+ return 1;
+ EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & REG_MASK, -argw));
+ return -1;
+ }
+ }
+ else {
+ if (argw >= 0 && argw <= 0xff) {
+ if (inp_flags & ARG_TEST)
+ return 1;
+ EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, TYPE2_TRANSFER_IMM(argw)));
+ return -1;
}
- else if ((argw & 0x3) == 0 || IS_TYPE1_TRANSFER(inp_flags)) {
+ if (argw < 0 && argw >= -0xff) {
if (inp_flags & ARG_TEST)
return 1;
- EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf,
- RM((arg >> 4) & 0xf) | (IS_TYPE1_TRANSFER(inp_flags) ? SRC2_IMM : 0) | ((argw & 0x3) << 7)));
+ argw = -argw;
+ EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & REG_MASK, TYPE2_TRANSFER_IMM(argw)));
return -1;
}
}
- return (inp_flags & ARG_TEST) ? SLJIT_SUCCESS : 0;
+ return 0;
}
/* See getput_arg below.
@@ -1439,10 +1442,10 @@ static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_
return 0;
/* Always a simple operation. */
- if (arg & 0xf0)
+ if (arg & OFFS_REG_MASK)
return 0;
- if (!(arg & 0xf)) {
+ if (!(arg & REG_MASK)) {
/* Immediate access. */
if ((next_arg & SLJIT_MEM) && ((sljit_uw)argw - (sljit_uw)next_argw <= 0xfff || (sljit_uw)next_argw - (sljit_uw)argw <= 0xfff))
return 1;
@@ -1469,7 +1472,7 @@ static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_
#define TEST_WRITE_BACK() \
if (inp_flags & WRITE_BACK) { \
- tmp_r = arg & 0xf; \
+ tmp_r = arg & REG_MASK; \
if (reg == tmp_r) { \
/* This can only happen for stores */ \
/* since ldr reg, [reg, ...]! has no meaning */ \
@@ -1497,7 +1500,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
tmp_r = (inp_flags & LOAD_DATA) ? reg : TMP_REG3;
max_delta = IS_TYPE1_TRANSFER(inp_flags) ? 0xfff : 0xff;
- if ((arg & 0xf) == SLJIT_UNUSED) {
+ if ((arg & REG_MASK) == SLJIT_UNUSED) {
/* Write back is not used. */
imm = (sljit_uw)(argw - compiler->cache_argw);
if ((compiler->cache_arg & SLJIT_IMM) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) {
@@ -1530,11 +1533,11 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
return SLJIT_SUCCESS;
}
- if (arg & 0xf0) {
+ if (arg & OFFS_REG_MASK) {
SLJIT_ASSERT((argw & 0x3) && !(max_delta & 0xf00));
if (inp_flags & WRITE_BACK)
- tmp_r = arg & 0xf;
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & 0xf, RM((arg >> 4) & 0xf) | ((argw & 0x3) << 7)));
+ tmp_r = arg & REG_MASK;
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & REG_MASK, RM(OFFS_REG(arg)) | ((argw & 0x3) << 7)));
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, 0, reg, tmp_r, TYPE2_TRANSFER_IMM(0)));
return SLJIT_SUCCESS;
}
@@ -1555,7 +1558,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
imm = get_imm(argw & ~max_delta);
if (imm) {
TEST_WRITE_BACK();
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & 0xf, imm));
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & REG_MASK, imm));
GETPUT_ARG_DATA_TRANSFER(1, inp_flags & WRITE_BACK, reg, tmp_r, argw & max_delta);
return SLJIT_SUCCESS;
}
@@ -1564,14 +1567,14 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
if (imm) {
argw = -argw;
TEST_WRITE_BACK();
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP, 0, tmp_r, arg & 0xf, imm));
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP, 0, tmp_r, arg & REG_MASK, imm));
GETPUT_ARG_DATA_TRANSFER(0, inp_flags & WRITE_BACK, reg, tmp_r, argw & max_delta);
return SLJIT_SUCCESS;
}
if ((compiler->cache_arg & SLJIT_IMM) && compiler->cache_argw == argw) {
TEST_WRITE_BACK();
- EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
+ EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
return SLJIT_SUCCESS;
}
@@ -1583,7 +1586,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
compiler->cache_argw = argw;
TEST_WRITE_BACK();
- EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
+ EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
return SLJIT_SUCCESS;
}
@@ -1591,7 +1594,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
if (arg == next_arg && !(inp_flags & WRITE_BACK) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) {
SLJIT_ASSERT(inp_flags & LOAD_DATA);
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, TMP_REG3, reg_map[arg & 0xf]));
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, TMP_REG3, reg_map[arg & REG_MASK]));
compiler->cache_arg = arg;
compiler->cache_argw = argw;
@@ -1600,14 +1603,14 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
return SLJIT_SUCCESS;
}
- if ((arg & 0xf) == tmp_r) {
+ if ((arg & REG_MASK) == tmp_r) {
compiler->cache_arg = SLJIT_IMM;
compiler->cache_argw = argw;
tmp_r = TMP_REG3;
}
FAIL_IF(load_immediate(compiler, tmp_r, argw));
- EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, reg_map[tmp_r] | (max_delta & 0xf00 ? SRC2_IMM : 0)));
+ EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, reg_map[tmp_r] | (max_delta & 0xf00 ? SRC2_IMM : 0)));
return SLJIT_SUCCESS;
}
@@ -1653,7 +1656,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si i
return SLJIT_SUCCESS;
dst_r = TMP_REG2;
}
- else if (dst <= TMP_REG3) {
+ else if (FAST_IS_REG(dst)) {
dst_r = dst;
flags |= REG_DEST;
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
@@ -1672,9 +1675,9 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si i
}
/* Source 1. */
- if (src1 <= TMP_REG3)
+ if (FAST_IS_REG(src1))
src1_r = src1;
- else if (src2 <= TMP_REG3) {
+ else if (FAST_IS_REG(src2)) {
flags |= ARGS_SWAPPED;
src1_r = src2;
src2 = src1;
@@ -1720,7 +1723,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si i
/* Source 2. */
if (src2_r == 0) {
- if (src2 <= TMP_REG3) {
+ if (FAST_IS_REG(src2)) {
src2_r = src2;
flags |= REG_SOURCE;
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
@@ -2026,9 +2029,13 @@ static void init_compiler(void)
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
{
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return SLJIT_IS_FPU_AVAILABLE;
+#else
if (arm_fpu_type == -1)
init_compiler();
return arm_fpu_type;
+#endif
}
#else
@@ -2056,18 +2063,18 @@ static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sl
sljit_sw inst = VSTR_F32 | (flags & (SLJIT_SINGLE_OP | FPU_LOAD));
SLJIT_ASSERT(arg & SLJIT_MEM);
- if (SLJIT_UNLIKELY(arg & 0xf0)) {
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & 0xf, RM((arg >> 4) & 0xf) | ((argw & 0x3) << 7)));
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & REG_MASK, RM(OFFS_REG(arg)) | ((argw & 0x3) << 7)));
arg = SLJIT_MEM | TMP_REG1;
argw = 0;
}
/* Fast loads and stores. */
- if ((arg & 0xf)) {
+ if ((arg & REG_MASK)) {
if (!(argw & ~0x3fc))
- return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, arg & 0xf, reg, argw >> 2));
+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, arg & REG_MASK, reg, argw >> 2));
if (!(-argw & ~0x3fc))
- return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, arg & 0xf, reg, (-argw) >> 2));
+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, arg & REG_MASK, reg, (-argw) >> 2));
}
if (compiler->cache_arg == arg) {
@@ -2083,29 +2090,29 @@ static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sl
}
}
- if (arg & 0xf) {
- if (emit_set_delta(compiler, TMP_REG1, arg & 0xf, argw) != SLJIT_ERR_UNSUPPORTED) {
+ if (arg & REG_MASK) {
+ if (emit_set_delta(compiler, TMP_REG1, arg & REG_MASK, argw) != SLJIT_ERR_UNSUPPORTED) {
FAIL_IF(compiler->error);
return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, 0));
}
imm = get_imm(argw & ~0x3fc);
if (imm) {
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & 0xf, imm));
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & REG_MASK, imm));
return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, (argw & 0x3fc) >> 2));
}
imm = get_imm(-argw & ~0x3fc);
if (imm) {
argw = -argw;
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP, 0, TMP_REG1, arg & 0xf, imm));
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP, 0, TMP_REG1, arg & REG_MASK, imm));
return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG1, reg, (argw & 0x3fc) >> 2));
}
}
compiler->cache_arg = arg;
compiler->cache_argw = argw;
- if (arg & 0xf) {
+ if (arg & REG_MASK) {
FAIL_IF(load_immediate(compiler, TMP_REG1, argw));
- EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, arg & 0xf, reg_map[TMP_REG1]));
+ EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, arg & REG_MASK, reg_map[TMP_REG1]));
}
else
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
@@ -2128,11 +2135,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
op ^= SLJIT_SINGLE_OP;
if (GET_OPCODE(op) == SLJIT_CMPD) {
- if (dst > SLJIT_FLOAT_REG6) {
+ if (dst & SLJIT_MEM) {
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, dst, dstw));
dst = TMP_FREG1;
}
- if (src > SLJIT_FLOAT_REG6) {
+ if (src & SLJIT_MEM) {
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src, srcw));
src = TMP_FREG2;
}
@@ -2141,9 +2148,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
return SLJIT_SUCCESS;
}
- dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : dst;
+ dst_fr = FAST_IS_REG(dst) ? dst : TMP_FREG1;
- if (src > SLJIT_FLOAT_REG6) {
+ if (src & SLJIT_MEM) {
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, dst_fr, src, srcw));
src = dst_fr;
}
@@ -2184,14 +2191,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
compiler->cache_argw = 0;
op ^= SLJIT_SINGLE_OP;
- dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : dst;
+ dst_fr = FAST_IS_REG(dst) ? dst : TMP_FREG1;
- if (src2 > SLJIT_FLOAT_REG6) {
+ if (src2 & SLJIT_MEM) {
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src2, src2w));
src2 = TMP_FREG2;
}
- if (src1 > SLJIT_FLOAT_REG6) {
+ if (src1 & SLJIT_MEM) {
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src1, src1w));
src1 = TMP_FREG1;
}
@@ -2238,7 +2245,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
if (dst == SLJIT_UNUSED)
return SLJIT_SUCCESS;
- if (dst <= TMP_REG3)
+ if (FAST_IS_REG(dst))
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, RM(TMP_REG3)));
/* Memory. */
@@ -2257,7 +2264,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
check_sljit_emit_fast_return(compiler, src, srcw);
ADJUST_LOCAL_OFFSET(src, srcw);
- if (src <= TMP_REG3)
+ if (FAST_IS_REG(src))
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(src)));
else if (src & SLJIT_MEM) {
if (getput_arg_fast(compiler, WORD_DATA | LOAD_DATA, TMP_REG3, src, srcw))
@@ -2398,26 +2405,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
ADJUST_LOCAL_OFFSET(src, srcw);
/* In ARM, we don't need to touch the arguments. */
- if (src & SLJIT_IMM) {
- jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
- FAIL_IF(!jump);
- set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
- jump->u.target = srcw;
-
-#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
- if (type >= SLJIT_FAST_CALL)
- FAIL_IF(prepare_blx(compiler));
- FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0), 0));
- if (type >= SLJIT_FAST_CALL)
- FAIL_IF(emit_blx(compiler));
-#else
- FAIL_IF(emit_imm(compiler, TMP_REG1, 0));
- FAIL_IF(push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)));
-#endif
- jump->addr = compiler->size;
- }
- else {
- if (src <= TMP_REG3)
+ if (!(src & SLJIT_IMM)) {
+ if (FAST_IS_REG(src))
return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(src));
SLJIT_ASSERT(src & SLJIT_MEM);
@@ -2425,6 +2414,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG2));
}
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ FAIL_IF(!jump);
+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
+ jump->u.target = srcw;
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+ if (type >= SLJIT_FAST_CALL)
+ FAIL_IF(prepare_blx(compiler));
+ FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0), 0));
+ if (type >= SLJIT_FAST_CALL)
+ FAIL_IF(emit_blx(compiler));
+#else
+ FAIL_IF(emit_imm(compiler, TMP_REG1, 0));
+ FAIL_IF(push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)));
+#endif
+ jump->addr = compiler->size;
return SLJIT_SUCCESS;
}
@@ -2446,7 +2451,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
op = GET_OPCODE(op);
cc = get_cc(type);
- dst_r = (dst <= TMP_REG3) ? dst : TMP_REG2;
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
if (op < SLJIT_ADD) {
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_r, SLJIT_UNUSED, SRC2_IMM | 0));
@@ -2455,7 +2460,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
}
ins = (op == SLJIT_AND ? AND_DP : (op == SLJIT_OR ? ORR_DP : EOR_DP));
- if ((op == SLJIT_OR || op == SLJIT_XOR) && dst <= TMP_REG3 && dst == src) {
+ if ((op == SLJIT_OR || op == SLJIT_XOR) && FAST_IS_REG(dst) && dst == src) {
EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(ins, 0, dst, dst, SRC2_IMM | 1) & ~COND_MASK) | cc);
/* The condition must always be set, even if the ORR/EOR is not executed above. */
return (flags & SLJIT_SET_E) ? push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG1, SLJIT_UNUSED, RM(dst))) : SLJIT_SUCCESS;
@@ -2493,7 +2498,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
PTR_FAIL_IF(!const_);
- reg = (dst <= TMP_REG3) ? dst : TMP_REG2;
+ reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, reg, TMP_PC, 0), init_value));
@@ -2503,7 +2508,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
#endif
set_const(const_, compiler);
- if (reg == TMP_REG2 && dst != SLJIT_UNUSED)
+ if (dst & SLJIT_MEM)
PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
return const_;
}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_64.c b/src/3rdparty/pcre/sljit/sljitNativeARM_64.c
new file mode 100644
index 0000000000..cfd1a38242
--- /dev/null
+++ b/src/3rdparty/pcre/sljit/sljitNativeARM_64.c
@@ -0,0 +1,1902 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.
+ */
+
+SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
+{
+ return "ARM-64" SLJIT_CPUINFO;
+}
+
+/* Length of an instruction word */
+typedef sljit_ui sljit_ins;
+
+#define TMP_ZERO 0
+
+#define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
+#define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
+#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
+#define TMP_REG4 (SLJIT_NO_REGISTERS + 4)
+#define TMP_LR (SLJIT_NO_REGISTERS + 5)
+#define TMP_SP (SLJIT_NO_REGISTERS + 6)
+
+#define TMP_FREG1 (0)
+#define TMP_FREG2 (SLJIT_FLOAT_REG6 + 1)
+
+static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 7] = {
+ 31, 0, 1, 2, 3, 4, 19, 20, 21, 22, 23, 29, 9, 10, 11, 12, 30, 31
+};
+
+#define W_OP (1 << 31)
+#define RD(rd) (reg_map[rd])
+#define RT(rt) (reg_map[rt])
+#define RN(rn) (reg_map[rn] << 5)
+#define RT2(rt2) (reg_map[rt2] << 10)
+#define RM(rm) (reg_map[rm] << 16)
+#define VD(vd) (vd)
+#define VT(vt) (vt)
+#define VN(vn) ((vn) << 5)
+#define VM(vm) ((vm) << 16)
+
+/* --------------------------------------------------------------------- */
+/* Instrucion forms */
+/* --------------------------------------------------------------------- */
+
+#define ADC 0x9a000000
+#define ADD 0x8b000000
+#define ADDI 0x91000000
+#define AND 0x8a000000
+#define ANDI 0x92000000
+#define ASRV 0x9ac02800
+#define B 0x14000000
+#define B_CC 0x54000000
+#define BL 0x94000000
+#define BLR 0xd63f0000
+#define BR 0xd61f0000
+#define BRK 0xd4200000
+#define CBZ 0xb4000000
+#define CLZ 0xdac01000
+#define CSINC 0x9a800400
+#define EOR 0xca000000
+#define EORI 0xd2000000
+#define FABS 0x1e60c000
+#define FADD 0x1e602800
+#define FCMP 0x1e602000
+#define FDIV 0x1e601800
+#define FMOV 0x1e604000
+#define FMUL 0x1e600800
+#define FNEG 0x1e614000
+#define FSUB 0x1e603800
+#define LDRI 0xf9400000
+#define LDP 0xa9400000
+#define LDP_PST 0xa8c00000
+#define LSLV 0x9ac02000
+#define LSRV 0x9ac02400
+#define MADD 0x9b000000
+#define MOVK 0xf2800000
+#define MOVN 0x92800000
+#define MOVZ 0xd2800000
+#define NOP 0xd503201f
+#define ORN 0xaa200000
+#define ORR 0xaa000000
+#define ORRI 0xb2000000
+#define RET 0xd65f0000
+#define SBC 0xda000000
+#define SBFM 0x93000000
+#define SDIV 0x9ac00c00
+#define SMADDL 0x9b200000
+#define SMULH 0x9b403c00
+#define STP 0xa9000000
+#define STP_PRE 0xa9800000
+#define STRI 0xf9000000
+#define STR_FI 0x3d000000
+#define STR_FR 0x3c206800
+#define STUR_FI 0x3c000000
+#define SUB 0xcb000000
+#define SUBI 0xd1000000
+#define SUBS 0xeb000000
+#define UBFM 0xd3000000
+#define UDIV 0x9ac00800
+#define UMULH 0x9bc03c00
+
+/* dest_reg is the absolute name of the register
+ Useful for reordering instructions in the delay slot. */
+static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins)
+{
+ sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ptr);
+ *ptr = ins;
+ compiler->size++;
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_si emit_imm64_const(struct sljit_compiler *compiler, sljit_si dst, sljit_uw imm)
+{
+ FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | ((imm & 0xffff) << 5)));
+ FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((imm >> 16) & 0xffff) << 5) | (1 << 21)));
+ FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((imm >> 32) & 0xffff) << 5) | (2 << 21)));
+ return push_inst(compiler, MOVK | RD(dst) | ((imm >> 48) << 5) | (3 << 21));
+}
+
+static SLJIT_INLINE void modify_imm64_const(sljit_ins* inst, sljit_uw new_imm)
+{
+ sljit_si dst = inst[0] & 0x1f;
+ SLJIT_ASSERT((inst[0] & 0xffe00000) == MOVZ && (inst[1] & 0xffe00000) == (MOVK | (1 << 21)));
+ inst[0] = MOVZ | dst | ((new_imm & 0xffff) << 5);
+ inst[1] = MOVK | dst | (((new_imm >> 16) & 0xffff) << 5) | (1 << 21);
+ inst[2] = MOVK | dst | (((new_imm >> 32) & 0xffff) << 5) | (2 << 21);
+ inst[3] = MOVK | dst | ((new_imm >> 48) << 5) | (3 << 21);
+}
+
+static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
+{
+ sljit_sw diff;
+ sljit_uw target_addr;
+
+ if (jump->flags & SLJIT_REWRITABLE_JUMP) {
+ jump->flags |= PATCH_ABS64;
+ return 0;
+ }
+
+ if (jump->flags & JUMP_ADDR)
+ target_addr = jump->u.target;
+ else {
+ SLJIT_ASSERT(jump->flags & JUMP_LABEL);
+ target_addr = (sljit_uw)(code + jump->u.label->size);
+ }
+ diff = (sljit_sw)target_addr - (sljit_sw)(code_ptr + 4);
+
+ if (jump->flags & IS_COND) {
+ diff += sizeof(sljit_ins);
+ if (diff <= 0xfffff && diff >= -0x100000) {
+ code_ptr[-5] ^= (jump->flags & IS_CBZ) ? (0x1 << 24) : 0x1;
+ jump->addr -= sizeof(sljit_ins);
+ jump->flags |= PATCH_COND;
+ return 5;
+ }
+ diff -= sizeof(sljit_ins);
+ }
+
+ if (diff <= 0x7ffffff && diff >= -0x8000000) {
+ jump->flags |= PATCH_B;
+ return 4;
+ }
+
+ if (target_addr <= 0xffffffffl) {
+ if (jump->flags & IS_COND)
+ code_ptr[-5] -= (2 << 5);
+ code_ptr[-2] = code_ptr[0];
+ return 2;
+ }
+ if (target_addr <= 0xffffffffffffl) {
+ if (jump->flags & IS_COND)
+ code_ptr[-5] -= (1 << 5);
+ jump->flags |= PATCH_ABS48;
+ code_ptr[-1] = code_ptr[0];
+ return 1;
+ }
+
+ jump->flags |= PATCH_ABS64;
+ return 0;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
+{
+ struct sljit_memory_fragment *buf;
+ sljit_ins *code;
+ sljit_ins *code_ptr;
+ sljit_ins *buf_ptr;
+ sljit_ins *buf_end;
+ sljit_uw word_count;
+ sljit_uw addr;
+ sljit_si dst;
+
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ struct sljit_const *const_;
+
+ CHECK_ERROR_PTR();
+ check_sljit_generate_code(compiler);
+ reverse_buf(compiler);
+
+ code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins));
+ PTR_FAIL_WITH_EXEC_IF(code);
+ buf = compiler->buf;
+
+ code_ptr = code;
+ word_count = 0;
+ label = compiler->labels;
+ jump = compiler->jumps;
+ const_ = compiler->consts;
+
+ do {
+ buf_ptr = (sljit_ins*)buf->memory;
+ buf_end = buf_ptr + (buf->used_size >> 2);
+ do {
+ *code_ptr = *buf_ptr++;
+ /* These structures are ordered by their address. */
+ SLJIT_ASSERT(!label || label->size >= word_count);
+ SLJIT_ASSERT(!jump || jump->addr >= word_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+ if (label && label->size == word_count) {
+ label->addr = (sljit_uw)code_ptr;
+ label->size = code_ptr - code;
+ label = label->next;
+ }
+ if (jump && jump->addr == word_count) {
+ jump->addr = (sljit_uw)(code_ptr - 4);
+ code_ptr -= detect_jump_type(jump, code_ptr, code);
+ jump = jump->next;
+ }
+ if (const_ && const_->addr == word_count) {
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ }
+ code_ptr ++;
+ word_count ++;
+ } while (buf_ptr < buf_end);
+
+ buf = buf->next;
+ } while (buf);
+
+ if (label && label->size == word_count) {
+ label->addr = (sljit_uw)code_ptr;
+ label->size = code_ptr - code;
+ label = label->next;
+ }
+
+ SLJIT_ASSERT(!label);
+ SLJIT_ASSERT(!jump);
+ SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
+
+ jump = compiler->jumps;
+ while (jump) {
+ do {
+ addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
+ buf_ptr = (sljit_ins*)jump->addr;
+ if (jump->flags & PATCH_B) {
+ addr = (sljit_sw)(addr - jump->addr) >> 2;
+ SLJIT_ASSERT((sljit_sw)addr <= 0x1ffffff && (sljit_sw)addr >= -0x2000000);
+ buf_ptr[0] = ((jump->flags & IS_BL) ? BL : B) | (addr & 0x3ffffff);
+ if (jump->flags & IS_COND)
+ buf_ptr[-1] -= (4 << 5);
+ break;
+ }
+ if (jump->flags & PATCH_COND) {
+ addr = (sljit_sw)(addr - jump->addr) >> 2;
+ SLJIT_ASSERT((sljit_sw)addr <= 0x3ffff && (sljit_sw)addr >= -0x40000);
+ buf_ptr[0] = (buf_ptr[0] & ~0xffffe0) | ((addr & 0x7ffff) << 5);
+ break;
+ }
+
+ SLJIT_ASSERT((jump->flags & (PATCH_ABS48 | PATCH_ABS64)) || addr <= 0xffffffffl);
+ SLJIT_ASSERT((jump->flags & PATCH_ABS64) || addr <= 0xffffffffffffl);
+
+ dst = buf_ptr[0] & 0x1f;
+ buf_ptr[0] = MOVZ | dst | ((addr & 0xffff) << 5);
+ buf_ptr[1] = MOVK | dst | (((addr >> 16) & 0xffff) << 5) | (1 << 21);
+ if (jump->flags & (PATCH_ABS48 | PATCH_ABS64))
+ buf_ptr[2] = MOVK | dst | (((addr >> 32) & 0xffff) << 5) | (2 << 21);
+ if (jump->flags & PATCH_ABS64)
+ buf_ptr[3] = MOVK | dst | (((addr >> 48) & 0xffff) << 5) | (3 << 21);
+ } while (0);
+ jump = jump->next;
+ }
+
+ compiler->error = SLJIT_ERR_COMPILED;
+ compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
+ SLJIT_CACHE_FLUSH(code, code_ptr);
+ return code;
+}
+
+/* --------------------------------------------------------------------- */
+/* Core code generator functions. */
+/* --------------------------------------------------------------------- */
+
+#define COUNT_TRAILING_ZERO(value, result) \
+ result = 0; \
+ if (!(value & 0xffffffff)) { \
+ result += 32; \
+ value >>= 32; \
+ } \
+ if (!(value & 0xffff)) { \
+ result += 16; \
+ value >>= 16; \
+ } \
+ if (!(value & 0xff)) { \
+ result += 8; \
+ value >>= 8; \
+ } \
+ if (!(value & 0xf)) { \
+ result += 4; \
+ value >>= 4; \
+ } \
+ if (!(value & 0x3)) { \
+ result += 2; \
+ value >>= 2; \
+ } \
+ if (!(value & 0x1)) { \
+ result += 1; \
+ value >>= 1; \
+ }
+
+#define LOGICAL_IMM_CHECK 0x100
+
+static sljit_ins logical_imm(sljit_sw imm, sljit_si len)
+{
+ sljit_si negated, ones, right;
+ sljit_uw mask, uimm;
+ sljit_ins ins;
+
+ if (len & LOGICAL_IMM_CHECK) {
+ len &= ~LOGICAL_IMM_CHECK;
+ if (len == 32 && (imm == 0 || imm == -1))
+ return 0;
+ if (len == 16 && ((sljit_si)imm == 0 || (sljit_si)imm == -1))
+ return 0;
+ }
+
+ SLJIT_ASSERT((len == 32 && imm != 0 && imm != -1)
+ || (len == 16 && (sljit_si)imm != 0 && (sljit_si)imm != -1));
+ uimm = (sljit_uw)imm;
+ while (1) {
+ if (len <= 0) {
+ SLJIT_ASSERT_STOP();
+ return 0;
+ }
+ mask = ((sljit_uw)1 << len) - 1;
+ if ((uimm & mask) != ((uimm >> len) & mask))
+ break;
+ len >>= 1;
+ }
+
+ len <<= 1;
+
+ negated = 0;
+ if (uimm & 0x1) {
+ negated = 1;
+ uimm = ~uimm;
+ }
+
+ if (len < 64)
+ uimm &= ((sljit_uw)1 << len) - 1;
+
+ /* Unsigned right shift. */
+ COUNT_TRAILING_ZERO(uimm, right);
+
+ /* Signed shift. We also know that the highest bit is set. */
+ imm = (sljit_sw)~uimm;
+ SLJIT_ASSERT(imm < 0);
+
+ COUNT_TRAILING_ZERO(imm, ones);
+
+ if (~imm)
+ return 0;
+
+ if (len == 64)
+ ins = 1 << 22;
+ else
+ ins = (0x3f - ((len << 1) - 1)) << 10;
+
+ if (negated)
+ return ins | ((len - ones - 1) << 10) | ((len - ones - right) << 16);
+
+ return ins | ((ones - 1) << 10) | ((len - right) << 16);
+}
+
+#undef COUNT_TRAILING_ZERO
+
+static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst, sljit_sw simm)
+{
+ sljit_uw imm = (sljit_uw)simm;
+ sljit_si i, zeros, ones, first;
+ sljit_ins bitmask;
+
+ if (imm <= 0xffff)
+ return push_inst(compiler, MOVZ | RD(dst) | (imm << 5));
+
+ if (simm >= -0x10000 && simm < 0)
+ return push_inst(compiler, MOVN | RD(dst) | ((~imm & 0xffff) << 5));
+
+ if (imm <= 0xffffffffl) {
+ if ((imm & 0xffff0000l) == 0xffff0000)
+ return push_inst(compiler, (MOVN ^ W_OP) | RD(dst) | ((~imm & 0xffff) << 5));
+ if ((imm & 0xffff) == 0xffff)
+ return push_inst(compiler, (MOVN ^ W_OP) | RD(dst) | ((~imm & 0xffff0000l) >> (16 - 5)) | (1 << 21));
+ bitmask = logical_imm(simm, 16);
+ if (bitmask != 0)
+ return push_inst(compiler, (ORRI ^ W_OP) | RD(dst) | RN(TMP_ZERO) | bitmask);
+ }
+ else {
+ bitmask = logical_imm(simm, 32);
+ if (bitmask != 0)
+ return push_inst(compiler, ORRI | RD(dst) | RN(TMP_ZERO) | bitmask);
+ }
+
+ if (imm <= 0xffffffffl) {
+ FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | ((imm & 0xffff) << 5)));
+ return push_inst(compiler, MOVK | RD(dst) | ((imm & 0xffff0000l) >> (16 - 5)) | (1 << 21));
+ }
+
+ if (simm >= -0x100000000l && simm < 0) {
+ FAIL_IF(push_inst(compiler, MOVN | RD(dst) | ((~imm & 0xffff) << 5)));
+ return push_inst(compiler, MOVK | RD(dst) | ((imm & 0xffff0000l) >> (16 - 5)) | (1 << 21));
+ }
+
+ /* A large amount of number can be constructed from ORR and MOVx,
+ but computing them is costly. We don't */
+
+ zeros = 0;
+ ones = 0;
+ for (i = 4; i > 0; i--) {
+ if ((simm & 0xffff) == 0)
+ zeros++;
+ if ((simm & 0xffff) == 0xffff)
+ ones++;
+ simm >>= 16;
+ }
+
+ simm = (sljit_sw)imm;
+ first = 1;
+ if (ones > zeros) {
+ simm = ~simm;
+ for (i = 0; i < 4; i++) {
+ if (!(simm & 0xffff)) {
+ simm >>= 16;
+ continue;
+ }
+ if (first) {
+ first = 0;
+ FAIL_IF(push_inst(compiler, MOVN | RD(dst) | ((simm & 0xffff) << 5) | (i << 21)));
+ }
+ else
+ FAIL_IF(push_inst(compiler, MOVK | RD(dst) | ((~simm & 0xffff) << 5) | (i << 21)));
+ simm >>= 16;
+ }
+ return SLJIT_SUCCESS;
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (!(simm & 0xffff)) {
+ simm >>= 16;
+ continue;
+ }
+ if (first) {
+ first = 0;
+ FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | ((simm & 0xffff) << 5) | (i << 21)));
+ }
+ else
+ FAIL_IF(push_inst(compiler, MOVK | RD(dst) | ((simm & 0xffff) << 5) | (i << 21)));
+ simm >>= 16;
+ }
+ return SLJIT_SUCCESS;
+}
+
+#define ARG1_IMM 0x0010000
+#define ARG2_IMM 0x0020000
+#define INT_OP 0x0040000
+#define SET_FLAGS 0x0080000
+#define UNUSED_RETURN 0x0100000
+#define SLOW_DEST 0x0200000
+#define SLOW_SRC1 0x0400000
+#define SLOW_SRC2 0x0800000
+
+#define CHECK_FLAGS(flag_bits) \
+ if (flags & SET_FLAGS) { \
+ inv_bits |= flag_bits; \
+ if (flags & UNUSED_RETURN) \
+ dst = TMP_ZERO; \
+ }
+
+static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, sljit_si dst, sljit_sw arg1, sljit_sw arg2)
+{
+ /* dst must be register, TMP_REG1
+ arg1 must be register, TMP_REG1, imm
+ arg2 must be register, TMP_REG2, imm */
+ sljit_ins inv_bits = (flags & INT_OP) ? (1 << 31) : 0;
+ sljit_ins inst_bits;
+ sljit_si op = (flags & 0xffff);
+ sljit_si reg;
+ sljit_sw imm, nimm;
+
+ if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) {
+ /* Both are immediates. */
+ flags &= ~ARG1_IMM;
+ if (arg1 == 0 && op != SLJIT_ADD && op != SLJIT_SUB)
+ arg1 = TMP_ZERO;
+ else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, arg1));
+ arg1 = TMP_REG1;
+ }
+ }
+
+ if (flags & (ARG1_IMM | ARG2_IMM)) {
+ reg = (flags & ARG2_IMM) ? arg1 : arg2;
+ imm = (flags & ARG2_IMM) ? arg2 : arg1;
+
+ switch (op) {
+ case SLJIT_MUL:
+ case SLJIT_NEG:
+ case SLJIT_CLZ:
+ case SLJIT_ADDC:
+ case SLJIT_SUBC:
+ /* No form with immediate operand (except imm 0, which
+ is represented by a ZERO register). */
+ break;
+ case SLJIT_MOV:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG1);
+ return load_immediate(compiler, dst, imm);
+ case SLJIT_NOT:
+ SLJIT_ASSERT(flags & ARG2_IMM);
+ FAIL_IF(load_immediate(compiler, dst, (flags & INT_OP) ? (~imm & 0xffffffff) : ~imm));
+ goto set_flags;
+ case SLJIT_SUB:
+ if (flags & ARG1_IMM)
+ break;
+ imm = -imm;
+ /* Fall through. */
+ case SLJIT_ADD:
+ if (imm == 0) {
+ CHECK_FLAGS(1 << 29);
+ return push_inst(compiler, ((op == SLJIT_ADD ? ADDI : SUBI) ^ inv_bits) | RD(dst) | RN(reg));
+ }
+ if (imm > 0 && imm <= 0xfff) {
+ CHECK_FLAGS(1 << 29);
+ return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | (imm << 10));
+ }
+ nimm = -imm;
+ if (nimm > 0 && nimm <= 0xfff) {
+ CHECK_FLAGS(1 << 29);
+ return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | (nimm << 10));
+ }
+ if (imm > 0 && imm <= 0xffffff && !(imm & 0xfff)) {
+ CHECK_FLAGS(1 << 29);
+ return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | ((imm >> 12) << 10) | (1 << 22));
+ }
+ if (nimm > 0 && nimm <= 0xffffff && !(nimm & 0xfff)) {
+ CHECK_FLAGS(1 << 29);
+ return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | ((nimm >> 12) << 10) | (1 << 22));
+ }
+ if (imm > 0 && imm <= 0xffffff && !(flags & SET_FLAGS)) {
+ FAIL_IF(push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | ((imm >> 12) << 10) | (1 << 22)));
+ return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(dst) | ((imm & 0xfff) << 10));
+ }
+ if (nimm > 0 && nimm <= 0xffffff && !(flags & SET_FLAGS)) {
+ FAIL_IF(push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | ((nimm >> 12) << 10) | (1 << 22)));
+ return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(dst) | ((nimm & 0xfff) << 10));
+ }
+ break;
+ case SLJIT_AND:
+ inst_bits = logical_imm(imm, LOGICAL_IMM_CHECK | ((flags & INT_OP) ? 16 : 32));
+ if (!inst_bits)
+ break;
+ CHECK_FLAGS(3 << 29);
+ return push_inst(compiler, (ANDI ^ inv_bits) | RD(dst) | RN(reg) | inst_bits);
+ case SLJIT_OR:
+ case SLJIT_XOR:
+ inst_bits = logical_imm(imm, LOGICAL_IMM_CHECK | ((flags & INT_OP) ? 16 : 32));
+ if (!inst_bits)
+ break;
+ if (op == SLJIT_OR)
+ inst_bits |= ORRI;
+ else
+ inst_bits |= EORI;
+ FAIL_IF(push_inst(compiler, (inst_bits ^ inv_bits) | RD(dst) | RN(reg)));
+ goto set_flags;
+ case SLJIT_SHL:
+ if (flags & ARG1_IMM)
+ break;
+ if (flags & INT_OP) {
+ imm &= 0x1f;
+ FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | ((-imm & 0x1f) << 16) | ((31 - imm) << 10)));
+ }
+ else {
+ imm &= 0x3f;
+ FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | (1 << 22) | ((-imm & 0x3f) << 16) | ((63 - imm) << 10)));
+ }
+ goto set_flags;
+ case SLJIT_LSHR:
+ case SLJIT_ASHR:
+ if (flags & ARG1_IMM)
+ break;
+ if (op == SLJIT_ASHR)
+ inv_bits |= 1 << 30;
+ if (flags & INT_OP) {
+ imm &= 0x1f;
+ FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | (imm << 16) | (31 << 10)));
+ }
+ else {
+ imm &= 0x3f;
+ FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | (1 << 22) | (imm << 16) | (63 << 10)));
+ }
+ goto set_flags;
+ default:
+ SLJIT_ASSERT_STOP();
+ break;
+ }
+
+ if (flags & ARG2_IMM) {
+ if (arg2 == 0)
+ arg2 = TMP_ZERO;
+ else {
+ FAIL_IF(load_immediate(compiler, TMP_REG2, arg2));
+ arg2 = TMP_REG2;
+ }
+ }
+ else {
+ if (arg1 == 0)
+ arg1 = TMP_ZERO;
+ else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, arg1));
+ arg1 = TMP_REG1;
+ }
+ }
+ }
+
+ /* Both arguments are registers. */
+ switch (op) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+ case SLJIT_MOVU:
+ case SLJIT_MOVU_P:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ if (dst == arg2)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(arg2));
+ case SLJIT_MOV_UB:
+ case SLJIT_MOVU_UB:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ return push_inst(compiler, (UBFM ^ (1 << 31)) | RD(dst) | RN(arg2) | (7 << 10));
+ case SLJIT_MOV_SB:
+ case SLJIT_MOVU_SB:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ if (!(flags & INT_OP))
+ inv_bits |= 1 << 22;
+ return push_inst(compiler, (SBFM ^ inv_bits) | RD(dst) | RN(arg2) | (7 << 10));
+ case SLJIT_MOV_UH:
+ case SLJIT_MOVU_UH:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ return push_inst(compiler, (UBFM ^ (1 << 31)) | RD(dst) | RN(arg2) | (15 << 10));
+ case SLJIT_MOV_SH:
+ case SLJIT_MOVU_SH:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ if (!(flags & INT_OP))
+ inv_bits |= 1 << 22;
+ return push_inst(compiler, (SBFM ^ inv_bits) | RD(dst) | RN(arg2) | (15 << 10));
+ case SLJIT_MOV_UI:
+ case SLJIT_MOVU_UI:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ if ((flags & INT_OP) && dst == arg2)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, (ORR ^ (1 << 31)) | RD(dst) | RN(TMP_ZERO) | RM(arg2));
+ case SLJIT_MOV_SI:
+ case SLJIT_MOVU_SI:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ if ((flags & INT_OP) && dst == arg2)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, SBFM | (1 << 22) | RD(dst) | RN(arg2) | (31 << 10));
+ case SLJIT_NOT:
+ SLJIT_ASSERT(arg1 == TMP_REG1);
+ FAIL_IF(push_inst(compiler, (ORN ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2)));
+ goto set_flags;
+ case SLJIT_NEG:
+ SLJIT_ASSERT(arg1 == TMP_REG1);
+ if (flags & SET_FLAGS)
+ inv_bits |= 1 << 29;
+ return push_inst(compiler, (SUB ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2));
+ case SLJIT_CLZ:
+ SLJIT_ASSERT(arg1 == TMP_REG1);
+ FAIL_IF(push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(arg2)));
+ goto set_flags;
+ case SLJIT_ADD:
+ CHECK_FLAGS(1 << 29);
+ return push_inst(compiler, (ADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
+ case SLJIT_ADDC:
+ CHECK_FLAGS(1 << 29);
+ return push_inst(compiler, (ADC ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
+ case SLJIT_SUB:
+ CHECK_FLAGS(1 << 29);
+ return push_inst(compiler, (SUB ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
+ case SLJIT_SUBC:
+ CHECK_FLAGS(1 << 29);
+ return push_inst(compiler, (SBC ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
+ case SLJIT_MUL:
+ if (!(flags & SET_FLAGS))
+ return push_inst(compiler, (MADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2) | RT2(TMP_ZERO));
+ if (flags & INT_OP) {
+ FAIL_IF(push_inst(compiler, SMADDL | RD(dst) | RN(arg1) | RM(arg2) | (31 << 10)));
+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG4) | RN(TMP_ZERO) | RM(dst) | (2 << 22) | (31 << 10)));
+ return push_inst(compiler, SUBS | RD(TMP_ZERO) | RN(TMP_REG4) | RM(dst) | (2 << 22) | (63 << 10));
+ }
+ FAIL_IF(push_inst(compiler, SMULH | RD(TMP_REG4) | RN(arg1) | RM(arg2)));
+ FAIL_IF(push_inst(compiler, MADD | RD(dst) | RN(arg1) | RM(arg2) | RT2(TMP_ZERO)));
+ return push_inst(compiler, SUBS | RD(TMP_ZERO) | RN(TMP_REG4) | RM(dst) | (2 << 22) | (63 << 10));
+ case SLJIT_AND:
+ CHECK_FLAGS(3 << 29);
+ return push_inst(compiler, (AND ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
+ case SLJIT_OR:
+ FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
+ goto set_flags;
+ case SLJIT_XOR:
+ FAIL_IF(push_inst(compiler, (EOR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
+ goto set_flags;
+ case SLJIT_SHL:
+ FAIL_IF(push_inst(compiler, (LSLV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
+ goto set_flags;
+ case SLJIT_LSHR:
+ FAIL_IF(push_inst(compiler, (LSRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
+ goto set_flags;
+ case SLJIT_ASHR:
+ FAIL_IF(push_inst(compiler, (ASRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
+ goto set_flags;
+ }
+
+ SLJIT_ASSERT_STOP();
+ return SLJIT_SUCCESS;
+
+set_flags:
+ if (flags & SET_FLAGS)
+ return push_inst(compiler, (SUBS ^ inv_bits) | RD(TMP_ZERO) | RN(dst) | RM(TMP_ZERO));
+ return SLJIT_SUCCESS;
+}
+
+#define STORE 0x01
+#define SIGNED 0x02
+
+#define UPDATE 0x04
+#define ARG_TEST 0x08
+
+#define BYTE_SIZE 0x000
+#define HALF_SIZE 0x100
+#define INT_SIZE 0x200
+#define WORD_SIZE 0x300
+
+#define MEM_SIZE_SHIFT(flags) ((flags) >> 8)
+
+static SLJIT_CONST sljit_ins sljit_mem_imm[4] = {
+/* u l */ 0x39400000 /* ldrb [reg,imm] */,
+/* u s */ 0x39000000 /* strb [reg,imm] */,
+/* s l */ 0x39800000 /* ldrsb [reg,imm] */,
+/* s s */ 0x39000000 /* strb [reg,imm] */,
+};
+
+static SLJIT_CONST sljit_ins sljit_mem_simm[4] = {
+/* u l */ 0x38400000 /* ldurb [reg,imm] */,
+/* u s */ 0x38000000 /* sturb [reg,imm] */,
+/* s l */ 0x38800000 /* ldursb [reg,imm] */,
+/* s s */ 0x38000000 /* sturb [reg,imm] */,
+};
+
+static SLJIT_CONST sljit_ins sljit_mem_pre_simm[4] = {
+/* u l */ 0x38400c00 /* ldrb [reg,imm]! */,
+/* u s */ 0x38000c00 /* strb [reg,imm]! */,
+/* s l */ 0x38800c00 /* ldrsb [reg,imm]! */,
+/* s s */ 0x38000c00 /* strb [reg,imm]! */,
+};
+
+static SLJIT_CONST sljit_ins sljit_mem_reg[4] = {
+/* u l */ 0x38606800 /* ldrb [reg,reg] */,
+/* u s */ 0x38206800 /* strb [reg,reg] */,
+/* s l */ 0x38a06800 /* ldrsb [reg,reg] */,
+/* s s */ 0x38206800 /* strb [reg,reg] */,
+};
+
+/* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */
+static sljit_si emit_set_delta(struct sljit_compiler *compiler, sljit_si dst, sljit_si reg, sljit_sw value)
+{
+ if (value >= 0) {
+ if (value <= 0xfff)
+ return push_inst(compiler, ADDI | RD(dst) | RN(reg) | (value << 10));
+ if (value <= 0xffffff && !(value & 0xfff))
+ return push_inst(compiler, ADDI | (1 << 22) | RD(dst) | RN(reg) | (value >> 2));
+ }
+ else {
+ value = -value;
+ if (value <= 0xfff)
+ return push_inst(compiler, SUBI | RD(dst) | RN(reg) | (value << 10));
+ if (value <= 0xffffff && !(value & 0xfff))
+ return push_inst(compiler, SUBI | (1 << 22) | RD(dst) | RN(reg) | (value >> 2));
+ }
+ return SLJIT_ERR_UNSUPPORTED;
+}
+
+/* Can perform an operation using at most 1 instruction. */
+static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
+{
+ sljit_ui shift = MEM_SIZE_SHIFT(flags);
+
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+
+ if (SLJIT_UNLIKELY(flags & UPDATE)) {
+ if ((arg & REG_MASK) && !(arg & OFFS_REG_MASK) && argw <= 255 && argw >= -256) {
+ if (SLJIT_UNLIKELY(flags & ARG_TEST))
+ return 1;
+
+ arg &= REG_MASK;
+ argw &= 0x1ff;
+ FAIL_IF(push_inst(compiler, sljit_mem_pre_simm[flags & 0x3]
+ | (shift << 30) | RT(reg) | RN(arg) | (argw << 12)));
+ return -1;
+ }
+ return 0;
+ }
+
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+ argw &= 0x3;
+ if (argw && argw != shift)
+ return 0;
+
+ if (SLJIT_UNLIKELY(flags & ARG_TEST))
+ return 1;
+
+ FAIL_IF(push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg)
+ | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw ? (1 << 12) : 0)));
+ return -1;
+ }
+
+ arg &= REG_MASK;
+ if (argw >= 0 && (argw >> shift) <= 0xfff && (argw & ((1 << shift) - 1)) == 0) {
+ if (SLJIT_UNLIKELY(flags & ARG_TEST))
+ return 1;
+
+ FAIL_IF(push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30)
+ | RT(reg) | RN(arg) | (argw << (10 - shift))));
+ return -1;
+ }
+
+ if (argw > 255 || argw < -256)
+ return 0;
+
+ if (SLJIT_UNLIKELY(flags & ARG_TEST))
+ return 1;
+
+ FAIL_IF(push_inst(compiler, sljit_mem_simm[flags & 0x3] | (shift << 30)
+ | RT(reg) | RN(arg) | ((argw & 0x1ff) << 12)));
+ return -1;
+}
+
+/* see getput_arg below.
+ Note: can_cache is called only for binary operators. Those
+ operators always uses word arguments without write back. */
+static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
+{
+ sljit_sw diff;
+ if ((arg & OFFS_REG_MASK) || !(next_arg & SLJIT_MEM))
+ return 0;
+
+ if (!(arg & REG_MASK)) {
+ diff = argw - next_argw;
+ if (diff <= 0xfff && diff >= -0xfff)
+ return 1;
+ return 0;
+ }
+
+ if (argw == next_argw)
+ return 1;
+
+ diff = argw - next_argw;
+ if (arg == next_arg && diff <= 0xfff && diff >= -0xfff)
+ return 1;
+
+ return 0;
+}
+
+/* Emit the necessary instructions. See can_cache above. */
+static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg,
+ sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
+{
+ sljit_ui shift = MEM_SIZE_SHIFT(flags);
+ sljit_si tmp_r, other_r;
+ sljit_sw diff;
+
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+ if (!(next_arg & SLJIT_MEM)) {
+ next_arg = 0;
+ next_argw = 0;
+ }
+
+ tmp_r = (flags & STORE) ? TMP_REG3 : reg;
+
+ if (SLJIT_UNLIKELY((flags & UPDATE) && (arg & REG_MASK))) {
+ /* Update only applies if a base register exists. */
+ other_r = OFFS_REG(arg);
+ if (!other_r) {
+ other_r = arg & REG_MASK;
+ if (other_r != reg && argw >= 0 && argw <= 0xffffff) {
+ if ((argw & 0xfff) != 0)
+ FAIL_IF(push_inst(compiler, ADDI | RD(other_r) | RN(other_r) | ((argw & 0xfff) << 10)));
+ if (argw >> 12)
+ FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(other_r) | RN(other_r) | ((argw >> 12) << 10)));
+ return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(other_r));
+ }
+ else if (other_r != reg && argw < 0 && argw >= -0xffffff) {
+ argw = -argw;
+ if ((argw & 0xfff) != 0)
+ FAIL_IF(push_inst(compiler, SUBI | RD(other_r) | RN(other_r) | ((argw & 0xfff) << 10)));
+ if (argw >> 12)
+ FAIL_IF(push_inst(compiler, SUBI | (1 << 22) | RD(other_r) | RN(other_r) | ((argw >> 12) << 10)));
+ return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(other_r));
+ }
+
+ if (compiler->cache_arg == SLJIT_MEM) {
+ if (argw == compiler->cache_argw) {
+ other_r = TMP_REG3;
+ argw = 0;
+ }
+ else if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) {
+ FAIL_IF(compiler->error);
+ compiler->cache_argw = argw;
+ other_r = TMP_REG3;
+ argw = 0;
+ }
+ }
+
+ if (argw) {
+ FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+ compiler->cache_arg = SLJIT_MEM;
+ compiler->cache_argw = argw;
+ other_r = TMP_REG3;
+ argw = 0;
+ }
+ }
+
+ /* No caching here. */
+ arg &= REG_MASK;
+ argw &= 0x3;
+ if (!argw || argw == shift) {
+ FAIL_IF(push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(other_r) | (argw ? (1 << 12) : 0)));
+ return push_inst(compiler, ADD | RD(arg) | RN(arg) | RM(other_r) | (argw << 10));
+ }
+ if (arg != reg) {
+ FAIL_IF(push_inst(compiler, ADD | RD(arg) | RN(arg) | RM(other_r) | (argw << 10)));
+ return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg));
+ }
+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG4) | RN(arg) | RM(other_r) | (argw << 10)));
+ FAIL_IF(push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(TMP_REG4)));
+ return push_inst(compiler, ORR | RD(arg) | RN(TMP_ZERO) | RM(TMP_REG4));
+ }
+
+ if (arg & OFFS_REG_MASK) {
+ other_r = OFFS_REG(arg);
+ arg &= REG_MASK;
+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RN(arg) | RM(other_r) | ((argw & 0x3) << 10)));
+ return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(tmp_r));
+ }
+
+ if (compiler->cache_arg == arg) {
+ diff = argw - compiler->cache_argw;
+ if (diff <= 255 && diff >= -256)
+ return push_inst(compiler, sljit_mem_simm[flags & 0x3] | (shift << 30)
+ | RT(reg) | RN(TMP_REG3) | ((diff & 0x1ff) << 12));
+ if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, diff) != SLJIT_ERR_UNSUPPORTED) {
+ FAIL_IF(compiler->error);
+ return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg));
+ }
+ }
+
+ if (argw >= 0 && argw <= 0xffffff && (argw & ((1 << shift) - 1)) == 0) {
+ FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_r) | RN(arg & REG_MASK) | ((argw >> 12) << 10)));
+ return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30)
+ | RT(reg) | RN(tmp_r) | ((argw & 0xfff) << (10 - shift)));
+ }
+
+ diff = argw - next_argw;
+ next_arg = (arg & REG_MASK) && (arg == next_arg) && diff <= 0xfff && diff >= -0xfff && diff != 0;
+ arg &= REG_MASK;
+
+ if (arg && compiler->cache_arg == SLJIT_MEM) {
+ if (compiler->cache_argw == argw)
+ return push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(TMP_REG3));
+ if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) {
+ FAIL_IF(compiler->error);
+ compiler->cache_argw = argw;
+ return push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(TMP_REG3));
+ }
+ }
+
+ compiler->cache_argw = argw;
+ if (next_arg && emit_set_delta(compiler, TMP_REG3, arg, argw) != SLJIT_ERR_UNSUPPORTED) {
+ FAIL_IF(compiler->error);
+ compiler->cache_arg = SLJIT_MEM | arg;
+ arg = 0;
+ }
+ else {
+ FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+ compiler->cache_arg = SLJIT_MEM;
+
+ if (next_arg) {
+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RN(TMP_REG3) | RM(arg)));
+ compiler->cache_arg = SLJIT_MEM | arg;
+ arg = 0;
+ }
+ }
+
+ if (arg)
+ return push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(TMP_REG3));
+ return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(TMP_REG3));
+}
+
+static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
+{
+ if (getput_arg_fast(compiler, flags, reg, arg, argw))
+ return compiler->error;
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+ return getput_arg(compiler, flags, reg, arg, argw, 0, 0);
+}
+
+static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg1, sljit_sw arg1w, sljit_si arg2, sljit_sw arg2w)
+{
+ if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
+ return compiler->error;
+ return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
+}
+
+/* --------------------------------------------------------------------- */
+/* Entry, exit */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
+{
+ CHECK_ERROR();
+ check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
+
+ compiler->scratches = scratches;
+ compiler->saveds = saveds;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->logical_local_size = local_size;
+#endif
+ compiler->locals_offset = (2 + saveds) * sizeof(sljit_sw);
+ local_size = (compiler->locals_offset + local_size + 15) & ~15;
+ compiler->local_size = local_size;
+
+ if (local_size <= (64 << 3))
+ FAIL_IF(push_inst(compiler, STP_PRE | 29 | RT2(TMP_LR)
+ | RN(TMP_SP) | ((-(local_size >> 3) & 0x7f) << 15)));
+ else {
+ local_size -= (64 << 3);
+ if (local_size > 0xfff) {
+ FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | ((local_size >> 12) << 10) | (1 << 22)));
+ local_size &= 0xfff;
+ }
+ if (local_size)
+ FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (local_size << 10)));
+ FAIL_IF(push_inst(compiler, STP_PRE | 29 | RT2(TMP_LR) | RN(TMP_SP) | (0x40 << 15)));
+ }
+
+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_LOCALS_REG) | RN(TMP_SP)));
+
+ if (saveds >= 2)
+ FAIL_IF(push_inst(compiler, STP | RT(SLJIT_SAVED_REG1) | RT2(SLJIT_SAVED_REG2) | RN(TMP_SP) | (2 << 15)));
+ if (saveds >= 4)
+ FAIL_IF(push_inst(compiler, STP | RT(SLJIT_SAVED_REG3) | RT2(SLJIT_SAVED_EREG1) | RN(TMP_SP) | (4 << 15)));
+ if (saveds == 1)
+ FAIL_IF(push_inst(compiler, STRI | RT(SLJIT_SAVED_REG1) | RN(TMP_SP) | (2 << 10)));
+ if (saveds == 3)
+ FAIL_IF(push_inst(compiler, STRI | RT(SLJIT_SAVED_REG3) | RN(TMP_SP) | (4 << 10)));
+ if (saveds == 5)
+ FAIL_IF(push_inst(compiler, STRI | RT(SLJIT_SAVED_EREG2) | RN(TMP_SP) | (6 << 10)));
+
+ if (args >= 1)
+ FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_SAVED_REG1) | RN(TMP_ZERO) | RM(SLJIT_SCRATCH_REG1)));
+ if (args >= 2)
+ FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_SAVED_REG2) | RN(TMP_ZERO) | RM(SLJIT_SCRATCH_REG2)));
+ if (args >= 3)
+ FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_SAVED_REG3) | RN(TMP_ZERO) | RM(SLJIT_SCRATCH_REG3)));
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
+{
+ CHECK_ERROR_VOID();
+ check_sljit_set_context(compiler, args, scratches, saveds, local_size);
+
+ compiler->scratches = scratches;
+ compiler->saveds = saveds;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->logical_local_size = local_size;
+#endif
+ compiler->locals_offset = (2 + saveds) * sizeof(sljit_sw);
+ compiler->local_size = (compiler->locals_offset + local_size + 15) & ~15;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
+{
+ sljit_si saveds, local_size;
+
+ CHECK_ERROR();
+ check_sljit_emit_return(compiler, op, src, srcw);
+
+ FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
+
+ saveds = compiler->saveds;
+
+ if (saveds >= 2)
+ FAIL_IF(push_inst(compiler, LDP | RT(SLJIT_SAVED_REG1) | RT2(SLJIT_SAVED_REG2) | RN(TMP_SP) | (2 << 15)));
+ if (saveds >= 4)
+ FAIL_IF(push_inst(compiler, LDP | RT(SLJIT_SAVED_REG3) | RT2(SLJIT_SAVED_EREG1) | RN(TMP_SP) | (4 << 15)));
+ if (saveds == 1)
+ FAIL_IF(push_inst(compiler, LDRI | RT(SLJIT_SAVED_REG1) | RN(TMP_SP) | (2 << 10)));
+ if (saveds == 3)
+ FAIL_IF(push_inst(compiler, LDRI | RT(SLJIT_SAVED_REG3) | RN(TMP_SP) | (4 << 10)));
+ if (saveds == 5)
+ FAIL_IF(push_inst(compiler, LDRI | RT(SLJIT_SAVED_EREG2) | RN(TMP_SP) | (6 << 10)));
+
+ local_size = compiler->local_size;
+
+ if (local_size <= (62 << 3))
+ FAIL_IF(push_inst(compiler, LDP_PST | 29 | RT2(TMP_LR)
+ | RN(TMP_SP) | (((local_size >> 3) & 0x7f) << 15)));
+ else {
+ FAIL_IF(push_inst(compiler, LDP_PST | 29 | RT2(TMP_LR) | RN(TMP_SP) | (0x3e << 15)));
+ local_size -= (62 << 3);
+ if (local_size > 0xfff) {
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_SP) | RN(TMP_SP) | ((local_size >> 12) << 10) | (1 << 22)));
+ local_size &= 0xfff;
+ }
+ if (local_size)
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_SP) | RN(TMP_SP) | (local_size << 10)));
+ }
+
+ FAIL_IF(push_inst(compiler, RET | RN(TMP_LR)));
+ return SLJIT_SUCCESS;
+}
+
+/* --------------------------------------------------------------------- */
+/* Operators */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
+{
+ sljit_ins inv_bits = (op & SLJIT_INT_OP) ? (1 << 31) : 0;
+
+ CHECK_ERROR();
+ check_sljit_emit_op0(compiler, op);
+
+ op = GET_OPCODE(op);
+ switch (op) {
+ case SLJIT_BREAKPOINT:
+ return push_inst(compiler, BRK);
+ case SLJIT_NOP:
+ return push_inst(compiler, NOP);
+ case SLJIT_UMUL:
+ case SLJIT_SMUL:
+ FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_SCRATCH_REG1)));
+ FAIL_IF(push_inst(compiler, MADD | RD(SLJIT_SCRATCH_REG1) | RN(SLJIT_SCRATCH_REG1) | RM(SLJIT_SCRATCH_REG2) | RT2(TMP_ZERO)));
+ return push_inst(compiler, (op == SLJIT_SMUL ? SMULH : UMULH) | RD(SLJIT_SCRATCH_REG2) | RN(TMP_REG1) | RM(SLJIT_SCRATCH_REG2));
+ case SLJIT_UDIV:
+ case SLJIT_SDIV:
+ FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_SCRATCH_REG1)));
+ FAIL_IF(push_inst(compiler, ((op == SLJIT_SDIV ? SDIV : UDIV) ^ inv_bits) | RD(SLJIT_SCRATCH_REG1) | RN(SLJIT_SCRATCH_REG1) | RM(SLJIT_SCRATCH_REG2)));
+ FAIL_IF(push_inst(compiler, (MADD ^ inv_bits) | RD(SLJIT_SCRATCH_REG2) | RN(SLJIT_SCRATCH_REG1) | RM(SLJIT_SCRATCH_REG2) | RT2(TMP_ZERO)));
+ return push_inst(compiler, (SUB ^ inv_bits) | RD(SLJIT_SCRATCH_REG2) | RN(TMP_REG1) | RM(SLJIT_SCRATCH_REG2));
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
+{
+ sljit_si dst_r, flags, mem_flags;
+ sljit_si op_flags = GET_ALL_FLAGS(op);
+
+ CHECK_ERROR();
+ check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+
+ dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
+
+ op = GET_OPCODE(op);
+ if (op >= SLJIT_MOV && op <= SLJIT_MOVU_P) {
+ switch (op) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+ flags = WORD_SIZE;
+ break;
+ case SLJIT_MOV_UB:
+ flags = BYTE_SIZE;
+ if (src & SLJIT_IMM)
+ srcw = (sljit_ub)srcw;
+ break;
+ case SLJIT_MOV_SB:
+ flags = BYTE_SIZE | SIGNED;
+ if (src & SLJIT_IMM)
+ srcw = (sljit_sb)srcw;
+ break;
+ case SLJIT_MOV_UH:
+ flags = HALF_SIZE;
+ if (src & SLJIT_IMM)
+ srcw = (sljit_uh)srcw;
+ break;
+ case SLJIT_MOV_SH:
+ flags = HALF_SIZE | SIGNED;
+ if (src & SLJIT_IMM)
+ srcw = (sljit_sh)srcw;
+ break;
+ case SLJIT_MOV_UI:
+ flags = INT_SIZE;
+ if (src & SLJIT_IMM)
+ srcw = (sljit_ui)srcw;
+ break;
+ case SLJIT_MOV_SI:
+ flags = INT_SIZE | SIGNED;
+ if (src & SLJIT_IMM)
+ srcw = (sljit_si)srcw;
+ break;
+ case SLJIT_MOVU:
+ case SLJIT_MOVU_P:
+ flags = WORD_SIZE | UPDATE;
+ break;
+ case SLJIT_MOVU_UB:
+ flags = BYTE_SIZE | UPDATE;
+ if (src & SLJIT_IMM)
+ srcw = (sljit_ub)srcw;
+ break;
+ case SLJIT_MOVU_SB:
+ flags = BYTE_SIZE | SIGNED | UPDATE;
+ if (src & SLJIT_IMM)
+ srcw = (sljit_sb)srcw;
+ break;
+ case SLJIT_MOVU_UH:
+ flags = HALF_SIZE | UPDATE;
+ if (src & SLJIT_IMM)
+ srcw = (sljit_uh)srcw;
+ break;
+ case SLJIT_MOVU_SH:
+ flags = HALF_SIZE | SIGNED | UPDATE;
+ if (src & SLJIT_IMM)
+ srcw = (sljit_sh)srcw;
+ break;
+ case SLJIT_MOVU_UI:
+ flags = INT_SIZE | UPDATE;
+ if (src & SLJIT_IMM)
+ srcw = (sljit_ui)srcw;
+ break;
+ case SLJIT_MOVU_SI:
+ flags = INT_SIZE | SIGNED | UPDATE;
+ if (src & SLJIT_IMM)
+ srcw = (sljit_si)srcw;
+ break;
+ default:
+ SLJIT_ASSERT_STOP();
+ flags = 0;
+ break;
+ }
+
+ if (src & SLJIT_IMM)
+ FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG1, srcw));
+ else if (src & SLJIT_MEM) {
+ if (getput_arg_fast(compiler, flags, dst_r, src, srcw))
+ FAIL_IF(compiler->error);
+ else
+ FAIL_IF(getput_arg(compiler, flags, dst_r, src, srcw, dst, dstw));
+ } else {
+ if (dst_r != TMP_REG1)
+ return emit_op_imm(compiler, op | ((op_flags & SLJIT_INT_OP) ? INT_OP : 0), dst_r, TMP_REG1, src);
+ dst_r = src;
+ }
+
+ if (dst & SLJIT_MEM) {
+ if (getput_arg_fast(compiler, flags | STORE, dst_r, dst, dstw))
+ return compiler->error;
+ else
+ return getput_arg(compiler, flags | STORE, dst_r, dst, dstw, 0, 0);
+ }
+ return SLJIT_SUCCESS;
+ }
+
+ flags = GET_FLAGS(op_flags) ? SET_FLAGS : 0;
+ mem_flags = WORD_SIZE;
+ if (op_flags & SLJIT_INT_OP) {
+ flags |= INT_OP;
+ mem_flags = INT_SIZE;
+ }
+
+ if (dst == SLJIT_UNUSED)
+ flags |= UNUSED_RETURN;
+
+ if (src & SLJIT_MEM) {
+ if (getput_arg_fast(compiler, mem_flags, TMP_REG2, src, srcw))
+ FAIL_IF(compiler->error);
+ else
+ FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG2, src, srcw, dst, dstw));
+ src = TMP_REG2;
+ }
+
+ if (src & SLJIT_IMM) {
+ flags |= ARG2_IMM;
+ if (op_flags & SLJIT_INT_OP)
+ srcw = (sljit_si)srcw;
+ } else
+ srcw = src;
+
+ emit_op_imm(compiler, flags | op, dst_r, TMP_REG1, srcw);
+
+ if (dst & SLJIT_MEM) {
+ if (getput_arg_fast(compiler, mem_flags | STORE, dst_r, dst, dstw))
+ return compiler->error;
+ else
+ return getput_arg(compiler, mem_flags | STORE, dst_r, dst, dstw, 0, 0);
+ }
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
+{
+ sljit_si dst_r, flags, mem_flags;
+
+ CHECK_ERROR();
+ check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+
+ dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
+ flags = GET_FLAGS(op) ? SET_FLAGS : 0;
+ mem_flags = WORD_SIZE;
+ if (op & SLJIT_INT_OP) {
+ flags |= INT_OP;
+ mem_flags = INT_SIZE;
+ }
+
+ if (dst == SLJIT_UNUSED)
+ flags |= UNUSED_RETURN;
+
+ if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, mem_flags | STORE | ARG_TEST, TMP_REG1, dst, dstw))
+ flags |= SLOW_DEST;
+
+ if (src1 & SLJIT_MEM) {
+ if (getput_arg_fast(compiler, mem_flags, TMP_REG1, src1, src1w))
+ FAIL_IF(compiler->error);
+ else
+ flags |= SLOW_SRC1;
+ }
+ if (src2 & SLJIT_MEM) {
+ if (getput_arg_fast(compiler, mem_flags, TMP_REG2, src2, src2w))
+ FAIL_IF(compiler->error);
+ else
+ flags |= SLOW_SRC2;
+ }
+
+ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
+ if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
+ FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG2, src2, src2w, src1, src1w));
+ FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG1, src1, src1w, dst, dstw));
+ }
+ else {
+ FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG1, src1, src1w, src2, src2w));
+ FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG2, src2, src2w, dst, dstw));
+ }
+ }
+ else if (flags & SLOW_SRC1)
+ FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG1, src1, src1w, dst, dstw));
+ else if (flags & SLOW_SRC2)
+ FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG2, src2, src2w, dst, dstw));
+
+ if (src1 & SLJIT_MEM)
+ src1 = TMP_REG1;
+ if (src2 & SLJIT_MEM)
+ src2 = TMP_REG2;
+
+ if (src1 & SLJIT_IMM)
+ flags |= ARG1_IMM;
+ else
+ src1w = src1;
+ if (src2 & SLJIT_IMM)
+ flags |= ARG2_IMM;
+ else
+ src2w = src2;
+
+ emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src1w, src2w);
+
+ if (dst & SLJIT_MEM) {
+ if (!(flags & SLOW_DEST)) {
+ getput_arg_fast(compiler, mem_flags | STORE, dst_r, dst, dstw);
+ return compiler->error;
+ }
+ return getput_arg(compiler, mem_flags | STORE, TMP_REG1, dst, dstw, 0, 0);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
+{
+ check_sljit_get_register_index(reg);
+ return reg_map[reg];
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg)
+{
+ check_sljit_get_float_register_index(reg);
+ return reg;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_si size)
+{
+ CHECK_ERROR();
+ check_sljit_emit_op_custom(compiler, instruction, size);
+ SLJIT_ASSERT(size == 4);
+
+ return push_inst(compiler, *(sljit_ins*)instruction);
+}
+
+/* --------------------------------------------------------------------- */
+/* Floating point operators */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
+{
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return SLJIT_IS_FPU_AVAILABLE;
+#else
+ /* Available by default. */
+ return 1;
+#endif
+}
+
+static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
+{
+ sljit_ui shift = MEM_SIZE_SHIFT(flags);
+ sljit_ins ins_bits = (shift << 30);
+ sljit_si other_r;
+ sljit_sw diff;
+
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+
+ if (!(flags & STORE))
+ ins_bits |= 1 << 22;
+
+ if (arg & OFFS_REG_MASK) {
+ argw &= 3;
+ if (!argw || argw == shift)
+ return push_inst(compiler, STR_FR | ins_bits | VT(reg)
+ | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw ? (1 << 12) : 0));
+ other_r = OFFS_REG(arg);
+ arg &= REG_MASK;
+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg) | RM(other_r) | (argw << 10)));
+ arg = TMP_REG1;
+ argw = 0;
+ }
+
+ arg &= REG_MASK;
+ if (arg && argw >= 0 && ((argw >> shift) <= 0xfff) && (argw & ((1 << shift) - 1)) == 0)
+ return push_inst(compiler, STR_FI | ins_bits | VT(reg) | RN(arg) | (argw << (10 - shift)));
+
+ if (arg && argw <= 255 && argw >= -256)
+ return push_inst(compiler, STUR_FI | ins_bits | VT(reg) | RN(arg) | ((argw & 0x1ff) << 12));
+
+ /* Slow cases */
+ if (compiler->cache_arg == SLJIT_MEM && argw != compiler->cache_argw) {
+ diff = argw - compiler->cache_argw;
+ if (!arg && diff <= 255 && diff >= -256)
+ return push_inst(compiler, STUR_FI | ins_bits | VT(reg) | RN(TMP_REG3) | ((diff & 0x1ff) << 12));
+ if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) {
+ FAIL_IF(compiler->error);
+ compiler->cache_argw = argw;
+ }
+ }
+
+ if (compiler->cache_arg != SLJIT_MEM || argw != compiler->cache_argw) {
+ compiler->cache_arg = SLJIT_MEM;
+ compiler->cache_argw = argw;
+ FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+ }
+
+ if (arg & REG_MASK)
+ return push_inst(compiler, STR_FR | ins_bits | VT(reg) | RN(arg) | RM(TMP_REG3));
+ return push_inst(compiler, STR_FI | ins_bits | VT(reg) | RN(TMP_REG3));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw)
+{
+ sljit_si dst_r, mem_flags = (op & SLJIT_SINGLE_OP) ? INT_SIZE : WORD_SIZE;
+ sljit_ins inv_bits = (op & SLJIT_SINGLE_OP) ? (1 << 22) : 0;
+
+ CHECK_ERROR();
+ check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+
+ if (GET_OPCODE(op) == SLJIT_CMPD) {
+ if (dst & SLJIT_MEM) {
+ emit_fop_mem(compiler, mem_flags, TMP_FREG1, dst, dstw);
+ dst = TMP_FREG1;
+ }
+ if (src & SLJIT_MEM) {
+ emit_fop_mem(compiler, mem_flags, TMP_FREG2, src, srcw);
+ src = TMP_FREG2;
+ }
+ return push_inst(compiler, (FCMP ^ inv_bits) | VN(dst) | VM(src));
+ }
+
+ dst_r = (dst <= REG_MASK) ? dst : TMP_FREG1;
+ if (src & SLJIT_MEM) {
+ emit_fop_mem(compiler, mem_flags, dst_r, src, srcw);
+ src = dst_r;
+ }
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOVD:
+ if (src != dst_r)
+ FAIL_IF(push_inst(compiler, (FMOV ^ inv_bits) | VD(dst_r) | VN(src)));
+ break;
+ case SLJIT_NEGD:
+ FAIL_IF(push_inst(compiler, (FNEG ^ inv_bits) | VD(dst_r) | VN(src)));
+ break;
+ case SLJIT_ABSD:
+ FAIL_IF(push_inst(compiler, (FABS ^ inv_bits) | VD(dst_r) | VN(src)));
+ break;
+ }
+
+ if (!(dst & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+ return emit_fop_mem(compiler, mem_flags | STORE, TMP_FREG1, dst, dstw);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src1, sljit_sw src1w,
+ sljit_si src2, sljit_sw src2w)
+{
+ sljit_si dst_r, mem_flags = (op & SLJIT_SINGLE_OP) ? INT_SIZE : WORD_SIZE;
+ sljit_ins inv_bits = (op & SLJIT_SINGLE_OP) ? (1 << 22) : 0;
+
+ CHECK_ERROR();
+ check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+
+ dst_r = (dst <= REG_MASK) ? dst : TMP_FREG1;
+ if (src1 & SLJIT_MEM) {
+ emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w);
+ src1 = TMP_FREG1;
+ }
+ if (src2 & SLJIT_MEM) {
+ emit_fop_mem(compiler, mem_flags, TMP_FREG2, src2, src2w);
+ src2 = TMP_FREG2;
+ }
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADDD:
+ FAIL_IF(push_inst(compiler, (FADD ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));
+ break;
+ case SLJIT_SUBD:
+ FAIL_IF(push_inst(compiler, (FSUB ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));
+ break;
+ case SLJIT_MULD:
+ FAIL_IF(push_inst(compiler, (FMUL ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));
+ break;
+ case SLJIT_DIVD:
+ FAIL_IF(push_inst(compiler, (FDIV ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));
+ break;
+ }
+
+ if (!(dst & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+ return emit_fop_mem(compiler, mem_flags | STORE, TMP_FREG1, dst, dstw);
+}
+
+/* --------------------------------------------------------------------- */
+/* Other instructions */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
+{
+ CHECK_ERROR();
+ check_sljit_emit_fast_enter(compiler, dst, dstw);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ /* For UNUSED dst. Uncommon, but possible. */
+ if (dst == SLJIT_UNUSED)
+ return SLJIT_SUCCESS;
+
+ if (dst <= REG_MASK)
+ return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(TMP_LR));
+
+ /* Memory. */
+ return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_LR, dst, dstw);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ check_sljit_emit_fast_return(compiler, src, srcw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (src <= REG_MASK)
+ FAIL_IF(push_inst(compiler, ORR | RD(TMP_LR) | RN(TMP_ZERO) | RM(src)));
+ else if (src & SLJIT_MEM)
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_LR, src, srcw));
+ else if (src & SLJIT_IMM)
+ FAIL_IF(load_immediate(compiler, TMP_LR, srcw));
+
+ return push_inst(compiler, RET | RN(TMP_LR));
+}
+
+/* --------------------------------------------------------------------- */
+/* Conditional instructions */
+/* --------------------------------------------------------------------- */
+
+static sljit_uw get_cc(sljit_si type)
+{
+ switch (type) {
+ case SLJIT_C_EQUAL:
+ case SLJIT_C_MUL_NOT_OVERFLOW:
+ case SLJIT_C_FLOAT_EQUAL:
+ return 0x1;
+
+ case SLJIT_C_NOT_EQUAL:
+ case SLJIT_C_MUL_OVERFLOW:
+ case SLJIT_C_FLOAT_NOT_EQUAL:
+ return 0x0;
+
+ case SLJIT_C_LESS:
+ case SLJIT_C_FLOAT_LESS:
+ return 0x2;
+
+ case SLJIT_C_GREATER_EQUAL:
+ case SLJIT_C_FLOAT_GREATER_EQUAL:
+ return 0x3;
+
+ case SLJIT_C_GREATER:
+ case SLJIT_C_FLOAT_GREATER:
+ return 0x9;
+
+ case SLJIT_C_LESS_EQUAL:
+ case SLJIT_C_FLOAT_LESS_EQUAL:
+ return 0x8;
+
+ case SLJIT_C_SIG_LESS:
+ return 0xa;
+
+ case SLJIT_C_SIG_GREATER_EQUAL:
+ return 0xb;
+
+ case SLJIT_C_SIG_GREATER:
+ return 0xd;
+
+ case SLJIT_C_SIG_LESS_EQUAL:
+ return 0xc;
+
+ case SLJIT_C_OVERFLOW:
+ case SLJIT_C_FLOAT_UNORDERED:
+ return 0x7;
+
+ case SLJIT_C_NOT_OVERFLOW:
+ case SLJIT_C_FLOAT_ORDERED:
+ return 0x6;
+
+ default:
+ SLJIT_ASSERT_STOP();
+ return 0xe;
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
+{
+ struct sljit_label *label;
+
+ CHECK_ERROR_PTR();
+ check_sljit_emit_label(compiler);
+
+ if (compiler->last_label && compiler->last_label->size == compiler->size)
+ return compiler->last_label;
+
+ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
+ PTR_FAIL_IF(!label);
+ set_label(label, compiler);
+ return label;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
+{
+ struct sljit_jump *jump;
+
+ CHECK_ERROR_PTR();
+ check_sljit_emit_jump(compiler, type);
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+ type &= 0xff;
+
+ if (type < SLJIT_JUMP) {
+ jump->flags |= IS_COND;
+ PTR_FAIL_IF(push_inst(compiler, B_CC | (6 << 5) | get_cc(type)));
+ }
+ else if (type >= SLJIT_FAST_CALL)
+ jump->flags |= IS_BL;
+
+ PTR_FAIL_IF(emit_imm64_const(compiler, TMP_REG1, 0));
+ jump->addr = compiler->size;
+ PTR_FAIL_IF(push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(TMP_REG1)));
+
+ return jump;
+}
+
+static SLJIT_INLINE struct sljit_jump* emit_cmp_to0(struct sljit_compiler *compiler, sljit_si type,
+ sljit_si src, sljit_sw srcw)
+{
+ struct sljit_jump *jump;
+ sljit_ins inv_bits = (type & SLJIT_INT_OP) ? (1 << 31) : 0;
+
+ SLJIT_ASSERT((type & 0xff) == SLJIT_C_EQUAL || (type & 0xff) == SLJIT_C_NOT_EQUAL);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+ jump->flags |= IS_CBZ | IS_COND;
+
+ if (src & SLJIT_MEM) {
+ PTR_FAIL_IF(emit_op_mem(compiler, inv_bits ? INT_SIZE : WORD_SIZE, TMP_REG1, src, srcw));
+ src = TMP_REG1;
+ }
+ else if (src & SLJIT_IMM) {
+ PTR_FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
+ src = TMP_REG1;
+ }
+ SLJIT_ASSERT(FAST_IS_REG(src));
+
+ if ((type & 0xff) == SLJIT_C_EQUAL)
+ inv_bits |= 1 << 24;
+
+ PTR_FAIL_IF(push_inst(compiler, (CBZ ^ inv_bits) | (6 << 5) | RT(src)));
+ PTR_FAIL_IF(emit_imm64_const(compiler, TMP_REG1, 0));
+ jump->addr = compiler->size;
+ PTR_FAIL_IF(push_inst(compiler, BR | RN(TMP_REG1)));
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
+{
+ struct sljit_jump *jump;
+
+ CHECK_ERROR();
+ check_sljit_emit_ijump(compiler, type, src, srcw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ /* In ARM, we don't need to touch the arguments. */
+ if (!(src & SLJIT_IMM)) {
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw));
+ src = TMP_REG1;
+ }
+ return push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(src));
+ }
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ FAIL_IF(!jump);
+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
+ jump->u.target = srcw;
+
+ FAIL_IF(emit_imm64_const(compiler, TMP_REG1, 0));
+ jump->addr = compiler->size;
+ return push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(TMP_REG1));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
+ sljit_si dst, sljit_sw dstw,
+ sljit_si src, sljit_sw srcw,
+ sljit_si type)
+{
+ sljit_si dst_r, flags, mem_flags;
+ sljit_ins cc;
+
+ CHECK_ERROR();
+ check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (dst == SLJIT_UNUSED)
+ return SLJIT_SUCCESS;
+
+ cc = get_cc(type);
+ dst_r = (dst <= REG_MASK) ? dst : TMP_REG1;
+
+ if (GET_OPCODE(op) < SLJIT_ADD) {
+ FAIL_IF(push_inst(compiler, CSINC | (cc << 12) | RD(dst_r) | RN(TMP_ZERO) | RM(TMP_ZERO)));
+ if (dst_r != TMP_REG1)
+ return SLJIT_SUCCESS;
+ return emit_op_mem(compiler, (GET_OPCODE(op) == SLJIT_MOV ? WORD_SIZE : INT_SIZE) | STORE, TMP_REG1, dst, dstw);
+ }
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+ flags = GET_FLAGS(op) ? SET_FLAGS : 0;
+ mem_flags = WORD_SIZE;
+ if (op & SLJIT_INT_OP) {
+ flags |= INT_OP;
+ mem_flags = INT_SIZE;
+ }
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, mem_flags, TMP_REG1, src, srcw, dst, dstw));
+ src = TMP_REG1;
+ srcw = 0;
+ } else if (src & SLJIT_IMM)
+ flags |= ARG1_IMM;
+
+ FAIL_IF(push_inst(compiler, CSINC | (cc << 12) | RD(TMP_REG2) | RN(TMP_ZERO) | RM(TMP_ZERO)));
+ emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src, TMP_REG2);
+
+ if (dst_r != TMP_REG1)
+ return SLJIT_SUCCESS;
+ return emit_op_mem2(compiler, mem_flags | STORE, TMP_REG1, dst, dstw, 0, 0);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
+{
+ struct sljit_const *const_;
+ sljit_si dst_r;
+
+ CHECK_ERROR_PTR();
+ check_sljit_emit_const(compiler, dst, dstw, init_value);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
+ PTR_FAIL_IF(!const_);
+ set_const(const_, compiler);
+
+ dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
+ PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, init_value));
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw));
+ return const_;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+{
+ sljit_ins* inst = (sljit_ins*)addr;
+ modify_imm64_const(inst, new_addr);
+ SLJIT_CACHE_FLUSH(inst, inst + 4);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+{
+ sljit_ins* inst = (sljit_ins*)addr;
+ modify_imm64_const(inst, new_constant);
+ SLJIT_CACHE_FLUSH(inst, inst + 4);
+}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_Thumb2.c b/src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c
index 74ec83177d..682f964e35 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeARM_Thumb2.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c
@@ -207,7 +207,7 @@ static SLJIT_INLINE sljit_si emit_imm32_const(struct sljit_compiler *compiler, s
COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16));
}
-static SLJIT_INLINE void modify_imm32_const(sljit_uh* inst, sljit_uw new_imm)
+static SLJIT_INLINE void modify_imm32_const(sljit_uh *inst, sljit_uw new_imm)
{
sljit_si dst = inst[1] & 0x0f00;
SLJIT_ASSERT(((inst[0] & 0xfbf0) == (MOVW >> 16)) && ((inst[2] & 0xfbf0) == (MOVT >> 16)) && dst == (inst[3] & 0x0f00));
@@ -238,33 +238,33 @@ static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_uh
if (jump->flags & IS_COND) {
SLJIT_ASSERT(!(jump->flags & IS_BL));
if (diff <= 127 && diff >= -128) {
- jump->flags |= B_TYPE1;
+ jump->flags |= PATCH_TYPE1;
return 5;
}
if (diff <= 524287 && diff >= -524288) {
- jump->flags |= B_TYPE2;
+ jump->flags |= PATCH_TYPE2;
return 4;
}
/* +1 comes from the prefix IT instruction. */
diff--;
if (diff <= 8388607 && diff >= -8388608) {
- jump->flags |= B_TYPE3;
+ jump->flags |= PATCH_TYPE3;
return 3;
}
}
else if (jump->flags & IS_BL) {
if (diff <= 8388607 && diff >= -8388608) {
- jump->flags |= BL_TYPE6;
+ jump->flags |= PATCH_BL;
return 3;
}
}
else {
if (diff <= 1023 && diff >= -1024) {
- jump->flags |= B_TYPE4;
+ jump->flags |= PATCH_TYPE4;
return 4;
}
if (diff <= 8388607 && diff >= -8388608) {
- jump->flags |= B_TYPE5;
+ jump->flags |= PATCH_TYPE5;
return 3;
}
}
@@ -272,15 +272,6 @@ static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_uh
return 0;
}
-static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr, sljit_si flush)
-{
- sljit_uh* inst = (sljit_uh*)addr;
- modify_imm32_const(inst, new_addr);
- if (flush) {
- SLJIT_CACHE_FLUSH(inst, inst + 3);
- }
-}
-
static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump)
{
sljit_si type = (jump->flags >> 4) & 0xf;
@@ -289,7 +280,7 @@ static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump)
sljit_si s, j1, j2;
if (SLJIT_UNLIKELY(type == 0)) {
- inline_set_jump_addr(jump->addr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
+ modify_imm32_const((sljit_uh*)jump->addr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target);
return;
}
@@ -425,6 +416,10 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
return (void*)((sljit_uw)code | 0x1);
}
+/* --------------------------------------------------------------------- */
+/* Core code generator functions. */
+/* --------------------------------------------------------------------- */
+
#define INVALID_IMM 0x80000000
static sljit_uw get_imm(sljit_uw imm)
{
@@ -502,7 +497,6 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst, sl
#define ARG1_IMM 0x0010000
#define ARG2_IMM 0x0020000
#define KEEP_FLAGS 0x0040000
-#define SET_MULOV 0x0080000
/* SET_FLAGS must be 0x100000 as it is also the value of S bit (can be used for optimization). */
#define SET_FLAGS 0x0100000
#define UNUSED_RETURN 0x0200000
@@ -516,7 +510,7 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
arg1 must be register, TMP_REG1, imm
arg2 must be register, TMP_REG2, imm */
sljit_si reg;
- sljit_uw imm, negated_imm;
+ sljit_uw imm, nimm;
if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) {
/* Both are immediates. */
@@ -530,6 +524,10 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
imm = (flags & ARG2_IMM) ? arg2 : arg1;
switch (flags & 0xffff) {
+ case SLJIT_CLZ:
+ case SLJIT_MUL:
+ /* No form with immediate operand. */
+ break;
case SLJIT_MOV:
SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG1);
return load_immediate(compiler, dst, imm);
@@ -537,30 +535,27 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
if (!(flags & SET_FLAGS))
return load_immediate(compiler, dst, ~imm);
/* Since the flags should be set, we just fallback to the register mode.
- Although I could do some clever things here, "NOT IMM" does not worth the efforts. */
- break;
- case SLJIT_CLZ:
- /* No form with immediate operand. */
+ Although some clever things could be done here, "NOT IMM" does not worth the efforts. */
break;
case SLJIT_ADD:
- negated_imm = (sljit_uw)-(sljit_sw)imm;
+ nimm = -imm;
if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) {
if (imm <= 0x7)
return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg));
- if (negated_imm <= 0x7)
- return push_inst16(compiler, SUBSI3 | IMM3(negated_imm) | RD3(dst) | RN3(reg));
+ if (nimm <= 0x7)
+ return push_inst16(compiler, SUBSI3 | IMM3(nimm) | RD3(dst) | RN3(reg));
if (reg == dst) {
if (imm <= 0xff)
return push_inst16(compiler, ADDSI8 | IMM8(imm) | RDN3(dst));
- if (negated_imm <= 0xff)
- return push_inst16(compiler, SUBSI8 | IMM8(negated_imm) | RDN3(dst));
+ if (nimm <= 0xff)
+ return push_inst16(compiler, SUBSI8 | IMM8(nimm) | RDN3(dst));
}
}
if (!(flags & SET_FLAGS)) {
if (imm <= 0xfff)
return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(imm));
- if (negated_imm <= 0xfff)
- return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(negated_imm));
+ if (nimm <= 0xfff)
+ return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(nimm));
}
imm = get_imm(imm);
if (imm != INVALID_IMM)
@@ -572,64 +567,60 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
return push_inst32(compiler, ADCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
break;
case SLJIT_SUB:
- if (flags & ARG2_IMM) {
- negated_imm = (sljit_uw)-(sljit_sw)imm;
- if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) {
- if (imm <= 0x7)
- return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg));
- if (negated_imm <= 0x7)
- return push_inst16(compiler, ADDSI3 | IMM3(negated_imm) | RD3(dst) | RN3(reg));
- if (reg == dst) {
- if (imm <= 0xff)
- return push_inst16(compiler, SUBSI8 | IMM8(imm) | RDN3(dst));
- if (negated_imm <= 0xff)
- return push_inst16(compiler, ADDSI8 | IMM8(negated_imm) | RDN3(dst));
- }
- if (imm <= 0xff && (flags & UNUSED_RETURN))
- return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg));
- }
- if (!(flags & SET_FLAGS)) {
- if (imm <= 0xfff)
- return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm));
- if (negated_imm <= 0xfff)
- return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(negated_imm));
- }
- imm = get_imm(imm);
- if (imm != INVALID_IMM)
- return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
- }
- else {
+ if (flags & ARG1_IMM) {
if (!(flags & KEEP_FLAGS) && imm == 0 && IS_2_LO_REGS(reg, dst))
return push_inst16(compiler, RSBSI | RD3(dst) | RN3(reg));
imm = get_imm(imm);
if (imm != INVALID_IMM)
return push_inst32(compiler, RSB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+ break;
}
- break;
- case SLJIT_SUBC:
- if (flags & ARG2_IMM) {
- imm = get_imm(imm);
- if (imm != INVALID_IMM)
- return push_inst32(compiler, SBCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+ nimm = -imm;
+ if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) {
+ if (imm <= 0x7)
+ return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg));
+ if (nimm <= 0x7)
+ return push_inst16(compiler, ADDSI3 | IMM3(nimm) | RD3(dst) | RN3(reg));
+ if (reg == dst) {
+ if (imm <= 0xff)
+ return push_inst16(compiler, SUBSI8 | IMM8(imm) | RDN3(dst));
+ if (nimm <= 0xff)
+ return push_inst16(compiler, ADDSI8 | IMM8(nimm) | RDN3(dst));
+ }
+ if (imm <= 0xff && (flags & UNUSED_RETURN))
+ return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg));
}
+ if (!(flags & SET_FLAGS)) {
+ if (imm <= 0xfff)
+ return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm));
+ if (nimm <= 0xfff)
+ return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(nimm));
+ }
+ imm = get_imm(imm);
+ if (imm != INVALID_IMM)
+ return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
break;
- case SLJIT_MUL:
- /* No form with immediate operand. */
+ case SLJIT_SUBC:
+ if (flags & ARG1_IMM)
+ break;
+ imm = get_imm(imm);
+ if (imm != INVALID_IMM)
+ return push_inst32(compiler, SBCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
break;
case SLJIT_AND:
+ nimm = get_imm(imm);
+ if (nimm != INVALID_IMM)
+ return push_inst32(compiler, ANDI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
imm = get_imm(imm);
if (imm != INVALID_IMM)
- return push_inst32(compiler, ANDI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
- imm = get_imm(~((flags & ARG2_IMM) ? arg2 : arg1));
- if (imm != INVALID_IMM)
return push_inst32(compiler, BICI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
break;
case SLJIT_OR:
+ nimm = get_imm(imm);
+ if (nimm != INVALID_IMM)
+ return push_inst32(compiler, ORRI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
imm = get_imm(imm);
if (imm != INVALID_IMM)
- return push_inst32(compiler, ORRI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
- imm = get_imm(~((flags & ARG2_IMM) ? arg2 : arg1));
- if (imm != INVALID_IMM)
return push_inst32(compiler, ORNI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
break;
case SLJIT_XOR:
@@ -638,50 +629,32 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
return push_inst32(compiler, EORI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
break;
case SLJIT_SHL:
- if (flags & ARG2_IMM) {
- imm &= 0x1f;
- if (imm == 0) {
- if (!(flags & SET_FLAGS))
- return push_inst16(compiler, MOV | SET_REGS44(dst, reg));
- if (IS_2_LO_REGS(dst, reg))
- return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg));
- return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg));
- }
+ case SLJIT_LSHR:
+ case SLJIT_ASHR:
+ if (flags & ARG1_IMM)
+ break;
+ imm &= 0x1f;
+ if (imm == 0) {
+ if (!(flags & SET_FLAGS))
+ return push_inst16(compiler, MOV | SET_REGS44(dst, reg));
+ if (IS_2_LO_REGS(dst, reg))
+ return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg));
+ return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg));
+ }
+ switch (flags & 0xffff) {
+ case SLJIT_SHL:
if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg))
return push_inst16(compiler, LSLSI | RD3(dst) | RN3(reg) | (imm << 6));
return push_inst32(compiler, LSL_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
- }
- break;
- case SLJIT_LSHR:
- if (flags & ARG2_IMM) {
- imm &= 0x1f;
- if (imm == 0) {
- if (!(flags & SET_FLAGS))
- return push_inst16(compiler, MOV | SET_REGS44(dst, reg));
- if (IS_2_LO_REGS(dst, reg))
- return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg));
- return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg));
- }
+ case SLJIT_LSHR:
if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg))
return push_inst16(compiler, LSRSI | RD3(dst) | RN3(reg) | (imm << 6));
return push_inst32(compiler, LSR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
- }
- break;
- case SLJIT_ASHR:
- if (flags & ARG2_IMM) {
- imm &= 0x1f;
- if (imm == 0) {
- if (!(flags & SET_FLAGS))
- return push_inst16(compiler, MOV | SET_REGS44(dst, reg));
- if (IS_2_LO_REGS(dst, reg))
- return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg));
- return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg));
- }
+ default: /* SLJIT_ASHR */
if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg))
return push_inst16(compiler, ASRSI | RD3(dst) | RN3(reg) | (imm << 6));
return push_inst32(compiler, ASR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
}
- break;
default:
SLJIT_ASSERT_STOP();
break;
@@ -708,6 +681,8 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
case SLJIT_MOVU_SI:
case SLJIT_MOVU_P:
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ if (dst == arg2)
+ return SLJIT_SUCCESS;
return push_inst16(compiler, MOV | SET_REGS44(dst, arg2));
case SLJIT_MOV_UB:
case SLJIT_MOVU_UB:
@@ -834,7 +809,7 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
s = store
*/
-static SLJIT_CONST sljit_uw sljit_mem16[12] = {
+static SLJIT_CONST sljit_ins sljit_mem16[12] = {
/* w u l */ 0x5800 /* ldr */,
/* w u s */ 0x5000 /* str */,
/* w s l */ 0x5800 /* ldr */,
@@ -851,7 +826,7 @@ static SLJIT_CONST sljit_uw sljit_mem16[12] = {
/* h s s */ 0x5200 /* strh */,
};
-static SLJIT_CONST sljit_uw sljit_mem16_imm5[12] = {
+static SLJIT_CONST sljit_ins sljit_mem16_imm5[12] = {
/* w u l */ 0x6800 /* ldr imm5 */,
/* w u s */ 0x6000 /* str imm5 */,
/* w s l */ 0x6800 /* ldr imm5 */,
@@ -870,7 +845,7 @@ static SLJIT_CONST sljit_uw sljit_mem16_imm5[12] = {
#define MEM_IMM8 0xc00
#define MEM_IMM12 0x800000
-static SLJIT_CONST sljit_uw sljit_mem32[12] = {
+static SLJIT_CONST sljit_ins sljit_mem32[12] = {
/* w u l */ 0xf8500000 /* ldr.w */,
/* w u s */ 0xf8400000 /* str.w */,
/* w s l */ 0xf8500000 /* ldr.w */,
@@ -911,69 +886,71 @@ static sljit_si emit_set_delta(struct sljit_compiler *compiler, sljit_si dst, sl
/* Can perform an operation using at most 1 instruction. */
static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
{
- sljit_si tmp;
+ sljit_si other_r, shift;
SLJIT_ASSERT(arg & SLJIT_MEM);
if (SLJIT_UNLIKELY(flags & UPDATE)) {
- if ((arg & 0xf) && !(arg & 0xf0) && argw <= 0xff && argw >= -0xff) {
- flags &= ~UPDATE;
- arg &= 0xf;
+ if ((arg & REG_MASK) && !(arg & OFFS_REG_MASK) && argw <= 0xff && argw >= -0xff) {
if (SLJIT_UNLIKELY(flags & ARG_TEST))
return 1;
+ flags &= ~UPDATE;
+ arg &= 0xf;
if (argw >= 0)
argw |= 0x200;
else {
argw = -argw;
}
+
SLJIT_ASSERT(argw >= 0 && (argw & 0xff) <= 0xff);
FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | 0x100 | argw));
return -1;
}
- return (flags & ARG_TEST) ? SLJIT_SUCCESS : 0;
+ return 0;
}
- if (SLJIT_UNLIKELY(arg & 0xf0)) {
- argw &= 0x3;
- tmp = (arg >> 4) & 0xf;
- arg &= 0xf;
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
if (SLJIT_UNLIKELY(flags & ARG_TEST))
return 1;
- if (!argw && IS_3_LO_REGS(reg, arg, tmp))
- FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(tmp)));
+ argw &= 0x3;
+ other_r = OFFS_REG(arg);
+ arg &= 0xf;
+
+ if (!argw && IS_3_LO_REGS(reg, arg, other_r))
+ FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r)));
else
- FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp) | (argw << 4)));
+ FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | (argw << 4)));
return -1;
}
- if (!(arg & 0xf) || argw > 0xfff || argw < -0xff)
- return (flags & ARG_TEST) ? SLJIT_SUCCESS : 0;
+ if (!(arg & REG_MASK) || argw > 0xfff || argw < -0xff)
+ return 0;
if (SLJIT_UNLIKELY(flags & ARG_TEST))
return 1;
arg &= 0xf;
if (IS_2_LO_REGS(reg, arg) && sljit_mem16_imm5[flags]) {
- tmp = 3;
+ shift = 3;
if (IS_WORD_SIZE(flags)) {
if (OFFSET_CHECK(0x1f, 2))
- tmp = 2;
+ shift = 2;
}
else if (flags & BYTE_SIZE)
{
if (OFFSET_CHECK(0x1f, 0))
- tmp = 0;
+ shift = 0;
}
else {
SLJIT_ASSERT(flags & HALF_SIZE);
if (OFFSET_CHECK(0x1f, 1))
- tmp = 1;
+ shift = 1;
}
- if (tmp != 3) {
- FAIL_IF(push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | (argw << (6 - tmp))));
+ if (shift != 3) {
+ FAIL_IF(push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | (argw << (6 - shift))));
return -1;
}
}
@@ -996,12 +973,13 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags,
operators always uses word arguments without write back. */
static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
{
- /* Simple operation except for updates. */
- if ((arg & 0xf0) || !(next_arg & SLJIT_MEM))
+ sljit_sw diff;
+ if ((arg & OFFS_REG_MASK) || !(next_arg & SLJIT_MEM))
return 0;
- if (!(arg & 0xf)) {
- if ((sljit_uw)(argw - next_argw) <= 0xfff || (sljit_uw)(next_argw - argw) <= 0xfff)
+ if (!(arg & REG_MASK)) {
+ diff = argw - next_argw;
+ if (diff <= 0xfff && diff >= -0xfff)
return 1;
return 0;
}
@@ -1009,17 +987,19 @@ static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_
if (argw == next_argw)
return 1;
- if (arg == next_arg && ((sljit_uw)(argw - next_argw) <= 0xfff || (sljit_uw)(next_argw - argw) <= 0xfff))
+ diff = argw - next_argw;
+ if (arg == next_arg && diff <= 0xfff && diff >= -0xfff)
return 1;
return 0;
}
/* Emit the necessary instructions. See can_cache above. */
-static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
+static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg,
+ sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
{
- sljit_si tmp_r;
- sljit_sw tmp;
+ sljit_si tmp_r, other_r;
+ sljit_sw diff;
SLJIT_ASSERT(arg & SLJIT_MEM);
if (!(next_arg & SLJIT_MEM)) {
@@ -1029,69 +1009,76 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
tmp_r = (flags & STORE) ? TMP_REG3 : reg;
- if (SLJIT_UNLIKELY(flags & UPDATE)) {
- flags &= ~UPDATE;
+ if (SLJIT_UNLIKELY((flags & UPDATE) && (arg & REG_MASK))) {
/* Update only applies if a base register exists. */
- if (arg & 0xf) {
- /* There is no caching here. */
- tmp = (arg & 0xf0) >> 4;
- arg &= 0xf;
+ /* There is no caching here. */
+ other_r = OFFS_REG(arg);
+ arg &= 0xf;
+ flags &= ~UPDATE;
- if (!tmp) {
- if (!(argw & ~0xfff)) {
- FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | argw));
- return push_inst32(compiler, ADDWI | RD4(arg) | RN4(arg) | IMM12(argw));
- }
+ if (!other_r) {
+ if (!(argw & ~0xfff)) {
+ FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | argw));
+ return push_inst32(compiler, ADDWI | RD4(arg) | RN4(arg) | IMM12(argw));
+ }
- if (compiler->cache_arg == SLJIT_MEM) {
- if (argw == compiler->cache_argw) {
- tmp = TMP_REG3;
- argw = 0;
- }
- else if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) {
- FAIL_IF(compiler->error);
- compiler->cache_argw = argw;
- tmp = TMP_REG3;
- argw = 0;
- }
+ if (compiler->cache_arg == SLJIT_MEM) {
+ if (argw == compiler->cache_argw) {
+ other_r = TMP_REG3;
+ argw = 0;
}
-
- if (argw) {
- FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
- compiler->cache_arg = SLJIT_MEM;
+ else if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) {
+ FAIL_IF(compiler->error);
compiler->cache_argw = argw;
- tmp = TMP_REG3;
+ other_r = TMP_REG3;
argw = 0;
}
}
- argw &= 0x3;
- if (!argw && IS_3_LO_REGS(reg, arg, tmp)) {
- FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(tmp)));
- return push_inst16(compiler, ADD | SET_REGS44(arg, tmp));
+ if (argw) {
+ FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+ compiler->cache_arg = SLJIT_MEM;
+ compiler->cache_argw = argw;
+ other_r = TMP_REG3;
+ argw = 0;
}
- FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp) | (argw << 4)));
- return push_inst32(compiler, ADD_W | RD4(arg) | RN4(arg) | RM4(tmp) | (argw << 6));
}
+
+ argw &= 0x3;
+ if (!argw && IS_3_LO_REGS(reg, arg, other_r)) {
+ FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r)));
+ return push_inst16(compiler, ADD | SET_REGS44(arg, other_r));
+ }
+ FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | (argw << 4)));
+ return push_inst32(compiler, ADD_W | RD4(arg) | RN4(arg) | RM4(other_r) | (argw << 6));
}
+ flags &= ~UPDATE;
- SLJIT_ASSERT(!(arg & 0xf0));
+ SLJIT_ASSERT(!(arg & OFFS_REG_MASK));
if (compiler->cache_arg == arg) {
- if (!((argw - compiler->cache_argw) & ~0xfff))
- return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | (argw - compiler->cache_argw));
+ diff = argw - compiler->cache_argw;
+ if (!(diff & ~0xfff))
+ return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | diff);
if (!((compiler->cache_argw - argw) & ~0xff))
return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(TMP_REG3) | (compiler->cache_argw - argw));
- if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) {
+ if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, diff) != SLJIT_ERR_UNSUPPORTED) {
FAIL_IF(compiler->error);
return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | 0);
}
}
- next_arg = (arg & 0xf) && (arg == next_arg);
+ next_arg = (arg & REG_MASK) && (arg == next_arg) && (argw != next_argw);
arg &= 0xf;
- if (arg && compiler->cache_arg == SLJIT_MEM && compiler->cache_argw == argw)
- return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(TMP_REG3));
+ if (arg && compiler->cache_arg == SLJIT_MEM) {
+ if (compiler->cache_argw == argw)
+ return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(TMP_REG3));
+ if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) {
+ FAIL_IF(compiler->error);
+ compiler->cache_argw = argw;
+ return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(TMP_REG3));
+ }
+ }
compiler->cache_argw = argw;
if (next_arg && emit_set_delta(compiler, TMP_REG3, arg, argw) != SLJIT_ERR_UNSUPPORTED) {
@@ -1103,7 +1090,8 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
compiler->cache_arg = SLJIT_MEM;
- if (next_arg) {
+ diff = argw - next_argw;
+ if (next_arg && diff <= 0xfff && diff >= -0xfff) {
FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG3, arg)));
compiler->cache_arg = SLJIT_MEM | arg;
arg = 0;
@@ -1270,11 +1258,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
op = GET_OPCODE(op);
switch (op) {
case SLJIT_BREAKPOINT:
- push_inst16(compiler, BKPT);
- break;
+ return push_inst16(compiler, BKPT);
case SLJIT_NOP:
- push_inst16(compiler, NOP);
- break;
+ return push_inst16(compiler, NOP);
case SLJIT_UMUL:
case SLJIT_SMUL:
return push_inst32(compiler, (op == SLJIT_UMUL ? UMULL : SMULL)
@@ -1321,7 +1307,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
compiler->cache_arg = 0;
compiler->cache_argw = 0;
- dst_r = (dst >= SLJIT_SCRATCH_REG1 && dst <= TMP_REG3) ? dst : TMP_REG1;
+ dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
op = GET_OPCODE(op);
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_P) {
@@ -1454,7 +1440,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
compiler->cache_arg = 0;
compiler->cache_argw = 0;
- dst_r = (dst >= SLJIT_SCRATCH_REG1 && dst <= TMP_REG3) ? dst : TMP_REG1;
+ dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
flags = (GET_FLAGS(op) ? SET_FLAGS : 0) | ((op & SLJIT_KEEP_FLAGS) ? KEEP_FLAGS : 0);
if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, WORD_SIZE | STORE | ARG_TEST, TMP_REG1, dst, dstw))
@@ -1505,9 +1491,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
if (dst == SLJIT_UNUSED)
flags |= UNUSED_RETURN;
- if (GET_OPCODE(op) == SLJIT_MUL && (op & SLJIT_SET_O))
- flags |= SET_MULOV;
-
emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src1w, src2w);
if (dst & SLJIT_MEM) {
@@ -1550,7 +1533,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *co
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
{
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return SLJIT_IS_FPU_AVAILABLE;
+#else
+ /* Available by default. */
return 1;
+#endif
}
#define FPU_LOAD (1 << 20)
@@ -1564,20 +1552,21 @@ static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sl
SLJIT_ASSERT(arg & SLJIT_MEM);
/* Fast loads and stores. */
- if (SLJIT_UNLIKELY(arg & 0xf0)) {
- FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG2) | RN4(arg & 0xf) | RM4((arg & 0xf0) >> 4) | ((argw & 0x3) << 6)));
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+ FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG2) | RN4(arg & REG_MASK) | RM4(OFFS_REG(arg)) | ((argw & 0x3) << 6)));
arg = SLJIT_MEM | TMP_REG2;
argw = 0;
}
- if ((arg & 0xf) && (argw & 0x3) == 0) {
+ if ((arg & REG_MASK) && (argw & 0x3) == 0) {
if (!(argw & ~0x3fc))
- return push_inst32(compiler, inst | 0x800000 | RN4(arg & 0xf) | DD4(reg) | (argw >> 2));
+ return push_inst32(compiler, inst | 0x800000 | RN4(arg & REG_MASK) | DD4(reg) | (argw >> 2));
if (!(-argw & ~0x3fc))
- return push_inst32(compiler, inst | RN4(arg & 0xf) | DD4(reg) | (-argw >> 2));
+ return push_inst32(compiler, inst | RN4(arg & REG_MASK) | DD4(reg) | (-argw >> 2));
}
- SLJIT_ASSERT(!(arg & 0xf0));
+ /* Slow cases */
+ SLJIT_ASSERT(!(arg & OFFS_REG_MASK));
if (compiler->cache_arg == arg) {
tmp = argw - compiler->cache_argw;
if (!(tmp & ~0x3fc))
@@ -1591,20 +1580,20 @@ static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sl
}
}
- if (arg & 0xf) {
- if (emit_set_delta(compiler, TMP_REG1, arg & 0xf, argw) != SLJIT_ERR_UNSUPPORTED) {
+ if (arg & REG_MASK) {
+ if (emit_set_delta(compiler, TMP_REG1, arg & REG_MASK, argw) != SLJIT_ERR_UNSUPPORTED) {
FAIL_IF(compiler->error);
return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg));
}
imm = get_imm(argw & ~0x3fc);
if (imm != INVALID_IMM) {
- FAIL_IF(push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg & 0xf) | imm));
+ FAIL_IF(push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg & REG_MASK) | imm));
return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg) | ((argw & 0x3fc) >> 2));
}
imm = get_imm(-argw & ~0x3fc);
if (imm != INVALID_IMM) {
argw = -argw;
- FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(arg & 0xf) | imm));
+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(arg & REG_MASK) | imm));
return push_inst32(compiler, inst | RN4(TMP_REG1) | DD4(reg) | ((argw & 0x3fc) >> 2));
}
}
@@ -1612,13 +1601,9 @@ static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sl
compiler->cache_arg = arg;
compiler->cache_argw = argw;
- if (SLJIT_UNLIKELY(!(arg & 0xf)))
- FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
- else {
- FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
- if (arg & 0xf)
- FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG3, (arg & 0xf))));
- }
+ FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+ if (arg & REG_MASK)
+ FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG3, (arg & REG_MASK))));
return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg));
}
@@ -1649,7 +1634,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
return push_inst32(compiler, VMRS);
}
- dst_r = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : dst;
+ dst_r = (dst <= REG_MASK) ? dst : TMP_FREG1;
if (src & SLJIT_MEM) {
emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, dst_r, src, srcw);
src = dst_r;
@@ -1668,9 +1653,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
break;
}
- if (dst & SLJIT_MEM)
- return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw);
- return SLJIT_SUCCESS;
+ if (!(dst & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+ return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
@@ -1687,7 +1672,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
compiler->cache_argw = 0;
op ^= SLJIT_SINGLE_OP;
- dst_r = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : dst;
+ dst_r = (dst <= REG_MASK) ? dst : TMP_FREG1;
if (src1 & SLJIT_MEM) {
emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src1, src1w);
src1 = TMP_FREG1;
@@ -1712,9 +1697,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
break;
}
- if (dst & SLJIT_MEM)
- return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw);
- return SLJIT_SUCCESS;
+ if (!(dst & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+ return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw);
}
#undef FPU_LOAD
@@ -1733,7 +1718,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
if (dst == SLJIT_UNUSED)
return SLJIT_SUCCESS;
- if (dst <= TMP_REG3)
+ if (dst <= REG_MASK)
return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG3));
/* Memory. */
@@ -1752,7 +1737,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
check_sljit_emit_fast_return(compiler, src, srcw);
ADJUST_LOCAL_OFFSET(src, srcw);
- if (src <= TMP_REG3)
+ if (src <= REG_MASK)
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG3, src)));
else if (src & SLJIT_MEM) {
if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG3, src, srcw))
@@ -1846,7 +1831,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
{
struct sljit_jump *jump;
- sljit_si cc;
+ sljit_ins cc;
CHECK_ERROR_PTR();
check_sljit_emit_jump(compiler, type);
@@ -1885,25 +1870,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
ADJUST_LOCAL_OFFSET(src, srcw);
/* In ARM, we don't need to touch the arguments. */
- if (src & SLJIT_IMM) {
- jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
- FAIL_IF(!jump);
- set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
- jump->u.target = srcw;
-
- FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0));
- jump->addr = compiler->size;
- FAIL_IF(push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(TMP_REG1)));
- }
- else {
- if (src <= TMP_REG3)
+ if (!(src & SLJIT_IMM)) {
+ if (FAST_IS_REG(src))
return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(src));
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, src, srcw));
if (type >= SLJIT_FAST_CALL)
return push_inst16(compiler, BLX | RN3(TMP_REG1));
}
- return SLJIT_SUCCESS;
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ FAIL_IF(!jump);
+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
+ jump->u.target = srcw;
+
+ FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0));
+ jump->addr = compiler->size;
+ return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(TMP_REG1));
}
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
@@ -1912,8 +1895,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
sljit_si type)
{
sljit_si dst_r, flags = GET_ALL_FLAGS(op);
- sljit_ins ins;
- sljit_uw cc;
+ sljit_ins cc, ins;
CHECK_ERROR();
check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type);
@@ -1925,7 +1907,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
op = GET_OPCODE(op);
cc = get_cc(type);
- dst_r = (dst <= TMP_REG3) ? dst : TMP_REG2;
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
if (op < SLJIT_ADD) {
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4));
@@ -1936,11 +1918,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 1));
FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 0));
}
- return dst_r == TMP_REG2 ? emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw) : SLJIT_SUCCESS;
+ if (dst_r != TMP_REG2)
+ return SLJIT_SUCCESS;
+ return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw);
}
ins = (op == SLJIT_AND ? ANDI : (op == SLJIT_OR ? ORRI : EORI));
- if ((op == SLJIT_OR || op == SLJIT_XOR) && dst <= TMP_REG3 && dst == src) {
+ if ((op == SLJIT_OR || op == SLJIT_XOR) && FAST_IS_REG(dst) && dst == src) {
/* Does not change the other bits. */
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst) | 1));
@@ -1956,18 +1940,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
compiler->cache_arg = 0;
compiler->cache_argw = 0;
if (src & SLJIT_MEM) {
- FAIL_IF(emit_op_mem2(compiler, WORD_SIZE, TMP_REG1, src, srcw, dst, dstw));
- src = TMP_REG1;
+ FAIL_IF(emit_op_mem2(compiler, WORD_SIZE, TMP_REG2, src, srcw, dst, dstw));
+ src = TMP_REG2;
srcw = 0;
} else if (src & SLJIT_IMM) {
- FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
- src = TMP_REG1;
+ FAIL_IF(load_immediate(compiler, TMP_REG2, srcw));
+ src = TMP_REG2;
srcw = 0;
}
- FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4));
- FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 1));
- FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 0));
+ if (op == SLJIT_AND || src != dst_r) {
+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4));
+ FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 1));
+ FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 0));
+ }
+ else {
+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
+ FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 1));
+ }
+
if (dst_r == TMP_REG2)
FAIL_IF(emit_op_mem2(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, 0, 0));
@@ -1993,7 +1984,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
PTR_FAIL_IF(!const_);
set_const(const_, compiler);
- dst_r = (dst <= TMP_REG3) ? dst : TMP_REG1;
+ dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, init_value));
if (dst & SLJIT_MEM)
@@ -2003,12 +1994,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
{
- inline_set_jump_addr(addr, new_addr, 1);
+ sljit_uh *inst = (sljit_uh*)addr;
+ modify_imm32_const(inst, new_addr);
+ SLJIT_CACHE_FLUSH(inst, inst + 4);
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
{
- sljit_uh* inst = (sljit_uh*)addr;
+ sljit_uh *inst = (sljit_uh*)addr;
modify_imm32_const(inst, new_constant);
- SLJIT_CACHE_FLUSH(inst, inst + 3);
+ SLJIT_CACHE_FLUSH(inst, inst + 4);
}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c b/src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c
index f8c214863d..cb7c695168 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c
@@ -52,7 +52,7 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar,
FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \
}
-#define EMIT_SHIFT(op_imm, op_norm) \
+#define EMIT_SHIFT(op_imm, op_v) \
if (flags & SRC2_IMM) { \
if (op & SLJIT_SET_E) \
FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
@@ -61,16 +61,14 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar,
} \
else { \
if (op & SLJIT_SET_E) \
- FAIL_IF(push_inst(compiler, op_norm | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
+ FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
if (CHECK_FLAGS(SLJIT_SET_E)) \
- FAIL_IF(push_inst(compiler, op_norm | S(src2) | T(src1) | D(dst), DR(dst))); \
+ FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst))); \
}
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
sljit_si dst, sljit_si src1, sljit_sw src2)
{
- sljit_si overflow_ra = 0;
-
switch (GET_OPCODE(op)) {
case SLJIT_MOV:
case SLJIT_MOV_UI:
@@ -138,30 +136,31 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
}
/* Nearly all instructions are unmovable in the following sequence. */
- FAIL_IF(push_inst(compiler, ADDU_W | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, ADDU | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
/* Check zero. */
FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(32), UNMOVABLE_INS));
- FAIL_IF(push_inst(compiler, ADDIU_W | SA(0) | T(dst) | IMM(-1), DR(dst)));
+ FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(dst) | IMM(-1), DR(dst)));
/* Loop for searching the highest bit. */
- FAIL_IF(push_inst(compiler, ADDIU_W | S(dst) | T(dst) | IMM(1), DR(dst)));
+ FAIL_IF(push_inst(compiler, ADDIU | S(dst) | T(dst) | IMM(1), DR(dst)));
FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
if (op & SLJIT_SET_E)
- return push_inst(compiler, ADDU_W | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
+ return push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
#endif
return SLJIT_SUCCESS;
case SLJIT_ADD:
if (flags & SRC2_IMM) {
if (op & SLJIT_SET_O) {
- FAIL_IF(push_inst(compiler, SRL | T(src1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1));
- if (src2 < 0)
- FAIL_IF(push_inst(compiler, XORI | SA(TMP_EREG1) | TA(TMP_EREG1) | IMM(1), TMP_EREG1));
+ if (src2 >= 0)
+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
+ else
+ FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
}
if (op & SLJIT_SET_E)
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
- if (op & SLJIT_SET_C) {
+ if (op & (SLJIT_SET_C | SLJIT_SET_O)) {
if (src2 >= 0)
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
else {
@@ -172,45 +171,28 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
/* dst may be the same as src1 or src2. */
if (CHECK_FLAGS(SLJIT_SET_E))
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));
- if (op & SLJIT_SET_O) {
- FAIL_IF(push_inst(compiler, SRL | T(dst) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
- if (src2 < 0)
- FAIL_IF(push_inst(compiler, XORI | SA(OVERFLOW_FLAG) | TA(OVERFLOW_FLAG) | IMM(1), OVERFLOW_FLAG));
- }
}
else {
- if (op & SLJIT_SET_O) {
+ if (op & SLJIT_SET_O)
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
- FAIL_IF(push_inst(compiler, SRL | TA(TMP_EREG1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1));
- if (src1 != dst)
- overflow_ra = DR(src1);
- else if (src2 != dst)
- overflow_ra = DR(src2);
- else {
- /* Rare ocasion. */
- FAIL_IF(push_inst(compiler, ADDU | S(src1) | TA(0) | DA(TMP_EREG2), TMP_EREG2));
- overflow_ra = TMP_EREG2;
- }
- }
if (op & SLJIT_SET_E)
FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
- if (op & SLJIT_SET_C)
+ if (op & (SLJIT_SET_C | SLJIT_SET_O))
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
/* dst may be the same as src1 or src2. */
if (CHECK_FLAGS(SLJIT_SET_E))
FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));
- if (op & SLJIT_SET_O) {
- FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(overflow_ra) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
- FAIL_IF(push_inst(compiler, SRL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
- }
}
/* a + b >= a | b (otherwise, the carry should be set to 1). */
- if (op & SLJIT_SET_C)
+ if (op & (SLJIT_SET_C | SLJIT_SET_O))
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
- if (op & SLJIT_SET_O)
- return push_inst(compiler, MOVN | SA(0) | TA(TMP_EREG1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
- return SLJIT_SUCCESS;
+ if (!(op & SLJIT_SET_O))
+ return SLJIT_SUCCESS;
+ FAIL_IF(push_inst(compiler, SLL | TA(ULESS_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
+ FAIL_IF(push_inst(compiler, XOR | SA(TMP_EREG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ return push_inst(compiler, SLL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
case SLJIT_ADDC:
if (flags & SRC2_IMM) {
@@ -236,14 +218,13 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
if (!(op & SLJIT_SET_C))
return SLJIT_SUCCESS;
- /* Set TMP_EREG2 (dst == 0) && (ULESS_FLAG == 1). */
- FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(TMP_EREG2) | IMM(1), TMP_EREG2));
- FAIL_IF(push_inst(compiler, AND | SA(TMP_EREG2) | TA(ULESS_FLAG) | DA(TMP_EREG2), TMP_EREG2));
+ /* Set ULESS_FLAG (dst == 0) && (ULESS_FLAG == 1). */
+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
/* Set carry flag. */
- return push_inst(compiler, OR | SA(TMP_EREG2) | TA(TMP_EREG1) | DA(ULESS_FLAG), ULESS_FLAG);
+ return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(TMP_EREG1) | DA(ULESS_FLAG), ULESS_FLAG);
case SLJIT_SUB:
- if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_S | SLJIT_SET_U)) || src2 == SIMM_MIN)) {
+ if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_MIN)) {
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
src2 = TMP_REG2;
flags &= ~SRC2_IMM;
@@ -251,40 +232,25 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
if (flags & SRC2_IMM) {
if (op & SLJIT_SET_O) {
- FAIL_IF(push_inst(compiler, SRL | T(src1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1));
- if (src2 < 0)
- FAIL_IF(push_inst(compiler, XORI | SA(TMP_EREG1) | TA(TMP_EREG1) | IMM(1), TMP_EREG1));
- if (src1 != dst)
- overflow_ra = DR(src1);
- else {
- /* Rare ocasion. */
- FAIL_IF(push_inst(compiler, ADDU | S(src1) | TA(0) | DA(TMP_EREG2), TMP_EREG2));
- overflow_ra = TMP_EREG2;
- }
+ if (src2 >= 0)
+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
+ else
+ FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
}
if (op & SLJIT_SET_E)
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
- if (op & SLJIT_SET_C)
+ if (op & (SLJIT_SET_C | SLJIT_SET_O))
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
/* dst may be the same as src1 or src2. */
if (CHECK_FLAGS(SLJIT_SET_E))
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
}
else {
- if (op & SLJIT_SET_O) {
+ if (op & SLJIT_SET_O)
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
- FAIL_IF(push_inst(compiler, SRL | TA(TMP_EREG1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1));
- if (src1 != dst)
- overflow_ra = DR(src1);
- else {
- /* Rare ocasion. */
- FAIL_IF(push_inst(compiler, ADDU | S(src1) | TA(0) | DA(TMP_EREG2), TMP_EREG2));
- overflow_ra = TMP_EREG2;
- }
- }
if (op & SLJIT_SET_E)
FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
- if (op & (SLJIT_SET_U | SLJIT_SET_C))
+ if (op & (SLJIT_SET_U | SLJIT_SET_C | SLJIT_SET_O))
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
if (op & SLJIT_SET_U)
FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(UGREATER_FLAG), UGREATER_FLAG));
@@ -293,16 +259,16 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(GREATER_FLAG), GREATER_FLAG));
}
/* dst may be the same as src1 or src2. */
- if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_C))
+ if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))
FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));
}
- if (op & SLJIT_SET_O) {
- FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(overflow_ra) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
- FAIL_IF(push_inst(compiler, SRL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
- return push_inst(compiler, MOVZ | SA(0) | TA(TMP_EREG1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
- }
- return SLJIT_SUCCESS;
+ if (!(op & SLJIT_SET_O))
+ return SLJIT_SUCCESS;
+ FAIL_IF(push_inst(compiler, SLL | TA(ULESS_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
+ FAIL_IF(push_inst(compiler, XOR | SA(TMP_EREG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ return push_inst(compiler, SRL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
case SLJIT_SUBC:
if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
@@ -313,7 +279,7 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
if (flags & SRC2_IMM) {
if (op & SLJIT_SET_C)
- FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(TMP_EREG1) | IMM(-src2), TMP_EREG1));
+ FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1));
/* dst may be the same as src1 or src2. */
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
}
@@ -325,14 +291,10 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
}
if (op & SLJIT_SET_C)
- FAIL_IF(push_inst(compiler, MOVZ | SA(ULESS_FLAG) | T(dst) | DA(TMP_EREG1), TMP_EREG1));
+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(TMP_EREG2), TMP_EREG2));
FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
-
- if (op & SLJIT_SET_C)
- FAIL_IF(push_inst(compiler, ADDU | SA(TMP_EREG1) | TA(0) | DA(ULESS_FLAG), ULESS_FLAG));
-
- return SLJIT_SUCCESS;
+ return (op & SLJIT_SET_C) ? push_inst(compiler, OR | SA(TMP_EREG1) | TA(TMP_EREG2) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS;
case SLJIT_MUL:
SLJIT_ASSERT(!(flags & SRC2_IMM));
diff --git a/src/3rdparty/pcre/sljit/sljitNativeMIPS_64.c b/src/3rdparty/pcre/sljit/sljitNativeMIPS_64.c
new file mode 100644
index 0000000000..df22ebaf55
--- /dev/null
+++ b/src/3rdparty/pcre/sljit/sljitNativeMIPS_64.c
@@ -0,0 +1,469 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.
+ */
+
+/* mips 64-bit arch dependent functions. */
+
+static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm)
+{
+ sljit_si shift = 32;
+ sljit_si shift2;
+ sljit_si inv = 0;
+ sljit_ins ins;
+ sljit_uw uimm;
+
+ if (!(imm & ~0xffff))
+ return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
+
+ if (imm < 0 && imm >= SIMM_MIN)
+ return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
+
+ if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
+ FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));
+ return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;
+ }
+
+ /* Zero extended number. */
+ uimm = imm;
+ if (imm < 0) {
+ uimm = ~imm;
+ inv = 1;
+ }
+
+ while (!(uimm & 0xff00000000000000l)) {
+ shift -= 8;
+ uimm <<= 8;
+ }
+
+ if (!(uimm & 0xf000000000000000l)) {
+ shift -= 4;
+ uimm <<= 4;
+ }
+
+ if (!(uimm & 0xc000000000000000l)) {
+ shift -= 2;
+ uimm <<= 2;
+ }
+
+ if ((sljit_sw)uimm < 0) {
+ uimm >>= 1;
+ shift += 1;
+ }
+ SLJIT_ASSERT(((uimm & 0xc000000000000000l) == 0x4000000000000000l) && (shift > 0) && (shift <= 32));
+
+ if (inv)
+ uimm = ~uimm;
+
+ FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(uimm >> 48), dst_ar));
+ if (uimm & 0x0000ffff00000000l)
+ FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 32), dst_ar));
+
+ imm &= (1l << shift) - 1;
+ if (!(imm & ~0xffff)) {
+ ins = (shift == 32) ? DSLL32 : DSLL;
+ if (shift < 32)
+ ins |= SH_IMM(shift);
+ FAIL_IF(push_inst(compiler, ins | TA(dst_ar) | DA(dst_ar), dst_ar));
+ return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);
+ }
+
+ /* Double shifts needs to be performed. */
+ uimm <<= 32;
+ shift2 = shift - 16;
+
+ while (!(uimm & 0xf000000000000000l)) {
+ shift2 -= 4;
+ uimm <<= 4;
+ }
+
+ if (!(uimm & 0xc000000000000000l)) {
+ shift2 -= 2;
+ uimm <<= 2;
+ }
+
+ if (!(uimm & 0x8000000000000000l)) {
+ shift2--;
+ uimm <<= 1;
+ }
+
+ SLJIT_ASSERT((uimm & 0x8000000000000000l) && (shift2 > 0) && (shift2 <= 16));
+
+ FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift - shift2), dst_ar));
+ FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 48), dst_ar));
+ FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift2), dst_ar));
+
+ imm &= (1l << shift2) - 1;
+ return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);
+}
+
+#define SELECT_OP(a, b) \
+ (!(op & SLJIT_INT_OP) ? a : b)
+
+#define EMIT_LOGICAL(op_imm, op_norm) \
+ if (flags & SRC2_IMM) { \
+ if (op & SLJIT_SET_E) \
+ FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
+ if (CHECK_FLAGS(SLJIT_SET_E)) \
+ FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
+ } \
+ else { \
+ if (op & SLJIT_SET_E) \
+ FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
+ if (CHECK_FLAGS(SLJIT_SET_E)) \
+ FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \
+ }
+
+#define EMIT_SHIFT(op_dimm, op_dimm32, op_imm, op_dv, op_v) \
+ if (flags & SRC2_IMM) { \
+ if (src2 >= 32) { \
+ SLJIT_ASSERT(!(op & SLJIT_INT_OP)); \
+ ins = op_dimm32; \
+ src2 -= 32; \
+ } \
+ else \
+ ins = (op & SLJIT_INT_OP) ? op_imm : op_dimm; \
+ if (op & SLJIT_SET_E) \
+ FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
+ if (CHECK_FLAGS(SLJIT_SET_E)) \
+ FAIL_IF(push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
+ } \
+ else { \
+ ins = (op & SLJIT_INT_OP) ? op_v : op_dv; \
+ if (op & SLJIT_SET_E) \
+ FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
+ if (CHECK_FLAGS(SLJIT_SET_E)) \
+ FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst))); \
+ }
+
+static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
+ sljit_si dst, sljit_si src1, sljit_sw src2)
+{
+ sljit_ins ins;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if (dst != src2)
+ return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst));
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_UB:
+ case SLJIT_MOV_SB:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ if (op == SLJIT_MOV_SB) {
+ FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
+ return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst));
+ }
+ return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
+ }
+ else if (dst != src2)
+ SLJIT_ASSERT_STOP();
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_UH:
+ case SLJIT_MOV_SH:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ if (op == SLJIT_MOV_SH) {
+ FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
+ return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst));
+ }
+ return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
+ }
+ else if (dst != src2)
+ SLJIT_ASSERT_STOP();
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_UI:
+ SLJIT_ASSERT(!(op & SLJIT_INT_OP));
+ FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst)));
+ return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst));
+
+ case SLJIT_MOV_SI:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst));
+
+ case SLJIT_NOT:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if (op & SLJIT_SET_E)
+ FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ if (CHECK_FLAGS(SLJIT_SET_E))
+ FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
+ return SLJIT_SUCCESS;
+
+ case SLJIT_CLZ:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
+ if (op & SLJIT_SET_E)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ if (CHECK_FLAGS(SLJIT_SET_E))
+ FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst)));
+#else
+ if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));
+ return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
+ }
+ /* Nearly all instructions are unmovable in the following sequence. */
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
+ /* Check zero. */
+ FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS));
+ FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM((op & SLJIT_INT_OP) ? 32 : 64), UNMOVABLE_INS));
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(dst) | IMM(-1), DR(dst)));
+ /* Loop for searching the highest bit. */
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst)));
+ FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
+ if (op & SLJIT_SET_E)
+ return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
+#endif
+ return SLJIT_SUCCESS;
+
+ case SLJIT_ADD:
+ if (flags & SRC2_IMM) {
+ if (op & SLJIT_SET_O) {
+ if (src2 >= 0)
+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
+ else
+ FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
+ }
+ if (op & SLJIT_SET_E)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
+ if (op & (SLJIT_SET_C | SLJIT_SET_O)) {
+ if (src2 >= 0)
+ FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
+ else {
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
+ FAIL_IF(push_inst(compiler, OR | S(src1) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
+ }
+ }
+ /* dst may be the same as src1 or src2. */
+ if (CHECK_FLAGS(SLJIT_SET_E))
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
+ }
+ else {
+ if (op & SLJIT_SET_O)
+ FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
+ if (op & SLJIT_SET_E)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ if (op & (SLJIT_SET_C | SLJIT_SET_O))
+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
+ /* dst may be the same as src1 or src2. */
+ if (CHECK_FLAGS(SLJIT_SET_E))
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
+ }
+
+ /* a + b >= a | b (otherwise, the carry should be set to 1). */
+ if (op & (SLJIT_SET_C | SLJIT_SET_O))
+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
+ if (!(op & SLJIT_SET_O))
+ return SLJIT_SUCCESS;
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(ULESS_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
+ FAIL_IF(push_inst(compiler, XOR | SA(TMP_EREG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ return push_inst(compiler, SELECT_OP(DSRL32, SLL) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
+
+ case SLJIT_ADDC:
+ if (flags & SRC2_IMM) {
+ if (op & SLJIT_SET_C) {
+ if (src2 >= 0)
+ FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1));
+ else {
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1));
+ FAIL_IF(push_inst(compiler, OR | S(src1) | TA(TMP_EREG1) | DA(TMP_EREG1), TMP_EREG1));
+ }
+ }
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
+ } else {
+ if (op & SLJIT_SET_C)
+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
+ /* dst may be the same as src1 or src2. */
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
+ }
+ if (op & SLJIT_SET_C)
+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(TMP_EREG1) | DA(TMP_EREG1), TMP_EREG1));
+
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
+ if (!(op & SLJIT_SET_C))
+ return SLJIT_SUCCESS;
+
+ /* Set ULESS_FLAG (dst == 0) && (ULESS_FLAG == 1). */
+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
+ /* Set carry flag. */
+ return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(TMP_EREG1) | DA(ULESS_FLAG), ULESS_FLAG);
+
+ case SLJIT_SUB:
+ if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_MIN)) {
+ FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
+ src2 = TMP_REG2;
+ flags &= ~SRC2_IMM;
+ }
+
+ if (flags & SRC2_IMM) {
+ if (op & SLJIT_SET_O) {
+ if (src2 >= 0)
+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
+ else
+ FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
+ }
+ if (op & SLJIT_SET_E)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
+ if (op & (SLJIT_SET_C | SLJIT_SET_O))
+ FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
+ /* dst may be the same as src1 or src2. */
+ if (CHECK_FLAGS(SLJIT_SET_E))
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
+ }
+ else {
+ if (op & SLJIT_SET_O)
+ FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
+ if (op & SLJIT_SET_E)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ if (op & (SLJIT_SET_U | SLJIT_SET_C | SLJIT_SET_O))
+ FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
+ if (op & SLJIT_SET_U)
+ FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(UGREATER_FLAG), UGREATER_FLAG));
+ if (op & SLJIT_SET_S) {
+ FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(LESS_FLAG), LESS_FLAG));
+ FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(GREATER_FLAG), GREATER_FLAG));
+ }
+ /* dst may be the same as src1 or src2. */
+ if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
+ }
+
+ if (!(op & SLJIT_SET_O))
+ return SLJIT_SUCCESS;
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(ULESS_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
+ FAIL_IF(push_inst(compiler, XOR | SA(TMP_EREG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
+
+ case SLJIT_SUBC:
+ if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
+ FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
+ src2 = TMP_REG2;
+ flags &= ~SRC2_IMM;
+ }
+
+ if (flags & SRC2_IMM) {
+ if (op & SLJIT_SET_C)
+ FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1));
+ /* dst may be the same as src1 or src2. */
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
+ }
+ else {
+ if (op & SLJIT_SET_C)
+ FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
+ /* dst may be the same as src1 or src2. */
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
+ }
+
+ if (op & SLJIT_SET_C)
+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(TMP_EREG2), TMP_EREG2));
+
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
+ return (op & SLJIT_SET_C) ? push_inst(compiler, OR | SA(TMP_EREG1) | TA(TMP_EREG2) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS;
+
+ case SLJIT_MUL:
+ SLJIT_ASSERT(!(flags & SRC2_IMM));
+ if (!(op & SLJIT_SET_O)) {
+#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
+ if (op & SLJIT_INT_OP)
+ return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
+ FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS));
+ return push_inst(compiler, MFLO | D(dst), DR(dst));
+#else
+ FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
+ return push_inst(compiler, MFLO | D(dst), DR(dst));
+#endif
+ }
+ FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, MFHI | DA(TMP_EREG1), TMP_EREG1));
+ FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(TMP_EREG2) | SH_IMM(31), TMP_EREG2));
+ return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(TMP_EREG1) | TA(TMP_EREG2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
+
+ case SLJIT_AND:
+ EMIT_LOGICAL(ANDI, AND);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_OR:
+ EMIT_LOGICAL(ORI, OR);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_XOR:
+ EMIT_LOGICAL(XORI, XOR);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_SHL:
+ EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_LSHR:
+ EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_ASHR:
+ EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV);
+ return SLJIT_SUCCESS;
+ }
+
+ SLJIT_ASSERT_STOP();
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw init_value)
+{
+ FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 48), DR(dst)));
+ FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 32), DR(dst)));
+ FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
+ FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 16), DR(dst)));
+ FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
+ return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+{
+ sljit_ins *inst = (sljit_ins*)addr;
+
+ inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 48) & 0xffff);
+ inst[1] = (inst[1] & 0xffff0000) | ((new_addr >> 32) & 0xffff);
+ inst[3] = (inst[3] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
+ inst[5] = (inst[5] & 0xffff0000) | (new_addr & 0xffff);
+ SLJIT_CACHE_FLUSH(inst, inst + 6);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+{
+ sljit_ins *inst = (sljit_ins*)addr;
+
+ inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff);
+ inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff);
+ inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
+ inst[5] = (inst[5] & 0xffff0000) | (new_constant & 0xffff);
+ SLJIT_CACHE_FLUSH(inst, inst + 6);
+}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c b/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c
index ede1c0bafe..011d8874c2 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c
@@ -30,7 +30,7 @@
SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
{
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
- return "MIPS(32)" SLJIT_CPUINFO;
+ return "MIPS V" SLJIT_CPUINFO;
#else
return "MIPS III" SLJIT_CPUINFO;
#endif
@@ -47,7 +47,7 @@ typedef sljit_ui sljit_ins;
/* For position independent code, t9 must contain the function address. */
#define PIC_ADDR_REG TMP_REG2
-/* TMP_EREG1 is used mainly for literal encoding on 64 bit. */
+/* TMP_EREGs are used mainly for arithmetic operations. */
#define TMP_EREG1 15
#define TMP_EREG2 24
/* Floating point status register. */
@@ -86,7 +86,7 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
#define FS(s) ((s) << 11)
#define FD(d) ((d) << 6)
#define IMM(imm) ((imm) & 0xffff)
-#define SH_IMM(imm) ((imm & 0x1f) << 6)
+#define SH_IMM(imm) ((imm) << 6)
#define DR(dr) (reg_map[dr])
#define HI(opcode) ((opcode) << 26)
@@ -96,8 +96,8 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
#define ABS_fmt (HI(17) | FMT_SD | LO(5))
#define ADD_fmt (HI(17) | FMT_SD | LO(0))
-#define ADDU (HI(0) | LO(33))
#define ADDIU (HI(9))
+#define ADDU (HI(0) | LO(33))
#define AND (HI(0) | LO(36))
#define ANDI (HI(12))
#define B (HI(4))
@@ -116,9 +116,25 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
#define C_UEQ_fmt (HI(17) | FMT_SD | LO(51))
#define C_ULE_fmt (HI(17) | FMT_SD | LO(55))
#define C_ULT_fmt (HI(17) | FMT_SD | LO(53))
+#define DADDIU (HI(25))
+#define DADDU (HI(0) | LO(45))
+#define DDIV (HI(0) | LO(30))
+#define DDIVU (HI(0) | LO(31))
#define DIV (HI(0) | LO(26))
#define DIVU (HI(0) | LO(27))
#define DIV_fmt (HI(17) | FMT_SD | LO(3))
+#define DMULT (HI(0) | LO(28))
+#define DMULTU (HI(0) | LO(29))
+#define DSLL (HI(0) | LO(56))
+#define DSLL32 (HI(0) | LO(60))
+#define DSLLV (HI(0) | LO(20))
+#define DSRA (HI(0) | LO(59))
+#define DSRA32 (HI(0) | LO(63))
+#define DSRAV (HI(0) | LO(23))
+#define DSRL (HI(0) | LO(58))
+#define DSRL32 (HI(0) | LO(62))
+#define DSRLV (HI(0) | LO(22))
+#define DSUBU (HI(0) | LO(47))
#define J (HI(2))
#define JAL (HI(3))
#define JALR (HI(0) | LO(9))
@@ -129,8 +145,6 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
#define MFHI (HI(0) | LO(16))
#define MFLO (HI(0) | LO(18))
#define MOV_fmt (HI(17) | FMT_SD | LO(6))
-#define MOVN (HI(0) | LO(11))
-#define MOVZ (HI(0) | LO(10))
#define MUL_fmt (HI(17) | FMT_SD | LO(2))
#define MULT (HI(0) | LO(24))
#define MULTU (HI(0) | LO(25))
@@ -158,6 +172,7 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
#define CLZ (HI(28) | LO(32))
+#define DCLZ (HI(28) | LO(36))
#define MUL (HI(28) | LO(2))
#define SEB (HI(31) | (16 << 6) | LO(32))
#define SEH (HI(31) | (24 << 6) | LO(32))
@@ -198,15 +213,20 @@ static SLJIT_INLINE sljit_ins invert_branch(sljit_si flags)
return (flags & IS_BIT26_COND) ? (1 << 26) : (1 << 16);
}
-static SLJIT_INLINE sljit_ins* optimize_jump(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
+static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
{
sljit_sw diff;
sljit_uw target_addr;
sljit_ins *inst;
sljit_ins saved_inst;
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))
+ return code_ptr;
+#else
if (jump->flags & SLJIT_REWRITABLE_JUMP)
return code_ptr;
+#endif
if (jump->flags & JUMP_ADDR)
target_addr = jump->u.target;
@@ -218,6 +238,11 @@ static SLJIT_INLINE sljit_ins* optimize_jump(struct sljit_jump *jump, sljit_ins
if (jump->flags & IS_COND)
inst--;
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if (jump->flags & IS_CALL)
+ goto keep_address;
+#endif
+
/* B instructions. */
if (jump->flags & IS_MOVABLE) {
diff = ((sljit_sw)target_addr - (sljit_sw)(inst)) >> 2;
@@ -237,24 +262,34 @@ static SLJIT_INLINE sljit_ins* optimize_jump(struct sljit_jump *jump, sljit_ins
return inst;
}
}
+ else {
+ diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1)) >> 2;
+ if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
+ jump->flags |= PATCH_B;
- diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1)) >> 2;
- if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
- jump->flags |= PATCH_B;
-
- if (!(jump->flags & IS_COND)) {
- inst[0] = (jump->flags & IS_JAL) ? BAL : B;
+ if (!(jump->flags & IS_COND)) {
+ inst[0] = (jump->flags & IS_JAL) ? BAL : B;
+ inst[1] = NOP;
+ return inst + 1;
+ }
+ inst[0] = inst[0] ^ invert_branch(jump->flags);
inst[1] = NOP;
+ jump->addr -= sizeof(sljit_ins);
return inst + 1;
}
- inst[0] = inst[0] ^ invert_branch(jump->flags);
- inst[1] = NOP;
- jump->addr -= sizeof(sljit_ins);
- return inst + 1;
}
if (jump->flags & IS_COND) {
- if ((target_addr & ~0xfffffff) == ((jump->addr + 3 * sizeof(sljit_ins)) & ~0xfffffff)) {
+ if ((jump->flags & IS_MOVABLE) && (target_addr & ~0xfffffff) == ((jump->addr + 2 * sizeof(sljit_ins)) & ~0xfffffff)) {
+ jump->flags |= PATCH_J;
+ saved_inst = inst[0];
+ inst[0] = inst[-1];
+ inst[-1] = (saved_inst & 0xffff0000) | 3;
+ inst[1] = J;
+ inst[2] = NOP;
+ return inst + 2;
+ }
+ else if ((target_addr & ~0xfffffff) == ((jump->addr + 3 * sizeof(sljit_ins)) & ~0xfffffff)) {
jump->flags |= PATCH_J;
inst[0] = (inst[0] & 0xffff0000) | 3;
inst[1] = NOP;
@@ -263,26 +298,48 @@ static SLJIT_INLINE sljit_ins* optimize_jump(struct sljit_jump *jump, sljit_ins
jump->addr += sizeof(sljit_ins);
return inst + 3;
}
- return code_ptr;
}
-
- /* J instuctions. */
- if (jump->flags & IS_MOVABLE) {
- if ((target_addr & ~0xfffffff) == (jump->addr & ~0xfffffff)) {
+ else {
+ /* J instuctions. */
+ if ((jump->flags & IS_MOVABLE) && (target_addr & ~0xfffffff) == (jump->addr & ~0xfffffff)) {
jump->flags |= PATCH_J;
inst[0] = inst[-1];
inst[-1] = (jump->flags & IS_JAL) ? JAL : J;
jump->addr -= sizeof(sljit_ins);
return inst;
}
+
+ if ((target_addr & ~0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~0xfffffff)) {
+ jump->flags |= PATCH_J;
+ inst[0] = (jump->flags & IS_JAL) ? JAL : J;
+ inst[1] = NOP;
+ return inst + 1;
+ }
}
- if ((target_addr & ~0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~0xfffffff)) {
- jump->flags |= PATCH_J;
- inst[0] = (jump->flags & IS_JAL) ? JAL : J;
- inst[1] = NOP;
- return inst + 1;
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+keep_address:
+ if (target_addr <= 0x7fffffff) {
+ jump->flags |= PATCH_ABS32;
+ if (jump->flags & IS_COND) {
+ inst[0] -= 4;
+ inst++;
+ }
+ inst[2] = inst[6];
+ inst[3] = inst[7];
+ return inst + 3;
+ }
+ if (target_addr <= 0x7fffffffffffl) {
+ jump->flags |= PATCH_ABS48;
+ if (jump->flags & IS_COND) {
+ inst[0] -= 2;
+ inst++;
+ }
+ inst[4] = inst[6];
+ inst[5] = inst[7];
+ return inst + 5;
}
+#endif
return code_ptr;
}
@@ -340,9 +397,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
jump->addr = (sljit_uw)(code_ptr - 3);
#else
-#error "Implementation required"
+ jump->addr = (sljit_uw)(code_ptr - 7);
#endif
- code_ptr = optimize_jump(jump, code_ptr, code);
+ code_ptr = detect_jump_type(jump, code_ptr, code);
jump = jump->next;
}
if (const_ && const_->addr == word_count) {
@@ -391,7 +448,23 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
#else
-#error "Implementation required"
+ if (jump->flags & PATCH_ABS32) {
+ SLJIT_ASSERT(addr <= 0x7fffffff);
+ buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
+ buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
+ }
+ else if (jump->flags & PATCH_ABS48) {
+ SLJIT_ASSERT(addr <= 0x7fffffffffffl);
+ buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 32) & 0xffff);
+ buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 16) & 0xffff);
+ buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | (addr & 0xffff);
+ }
+ else {
+ buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 48) & 0xffff);
+ buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 32) & 0xffff);
+ buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | ((addr >> 16) & 0xffff);
+ buf_ptr[5] = (buf_ptr[5] & 0xffff0000) | (addr & 0xffff);
+ }
#endif
} while (0);
jump = jump->next;
@@ -473,7 +546,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
#endif
local_size += (saveds + 1 + 4) * sizeof(sljit_sw);
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
local_size = (local_size + 15) & ~0xf;
+#else
+ local_size = (local_size + 31) & ~0x1f;
+#endif
compiler->local_size = local_size;
if (local_size <= SIMM_MAX) {
@@ -523,7 +600,11 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
#endif
local_size += (saveds + 1 + 4) * sizeof(sljit_sw);
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
compiler->local_size = (local_size + 15) & ~0xf;
+#else
+ compiler->local_size = (local_size + 31) & ~0x1f;
+#endif
}
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
@@ -612,11 +693,11 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags,
{
SLJIT_ASSERT(arg & SLJIT_MEM);
- if ((!(flags & WRITE_BACK) || !(arg & 0xf)) && !(arg & 0xf0) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
+ if ((!(flags & WRITE_BACK) || !(arg & REG_MASK)) && !(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
/* Works for both absoulte and relative addresses. */
if (SLJIT_UNLIKELY(flags & ARG_TEST))
return 1;
- FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & 0xf)
+ FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & REG_MASK)
| TA(reg_ar) | IMM(argw), ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? reg_ar : MOVABLE_INS));
return -1;
}
@@ -631,10 +712,10 @@ static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_
SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
/* Simple operation except for updates. */
- if (arg & 0xf0) {
+ if (arg & OFFS_REG_MASK) {
argw &= 0x3;
next_argw &= 0x3;
- if (argw && argw == next_argw && (arg == next_arg || (arg & 0xf0) == (next_arg & 0xf0)))
+ if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))
return 1;
return 0;
}
@@ -666,9 +747,9 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
tmp_ar = DR(TMP_REG1);
delay_slot = MOVABLE_INS;
}
- base = arg & 0xf;
+ base = arg & REG_MASK;
- if (SLJIT_UNLIKELY(arg & 0xf0)) {
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
argw &= 0x3;
if ((flags & WRITE_BACK) && reg_ar == DR(base)) {
SLJIT_ASSERT(!(flags & LOAD_DATA) && DR(TMP_REG1) != reg_ar);
@@ -681,7 +762,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
if (!(flags & WRITE_BACK)) {
if (arg == compiler->cache_arg)
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
- if ((SLJIT_MEM | (arg & 0xf0)) == compiler->cache_arg) {
+ if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
if (arg == next_arg && argw == (next_argw & 0x3)) {
compiler->cache_arg = arg;
compiler->cache_argw = argw;
@@ -693,7 +774,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
}
}
else {
- if ((SLJIT_MEM | (arg & 0xf0)) == compiler->cache_arg) {
+ if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(base), DR(base)));
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), delay_slot);
}
@@ -701,23 +782,23 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
}
if (SLJIT_UNLIKELY(argw)) {
- compiler->cache_arg = SLJIT_MEM | (arg & 0xf0);
+ compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);
compiler->cache_argw = argw;
- FAIL_IF(push_inst(compiler, SLL_W | T((arg >> 4) & 0xf) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3)));
+ FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3)));
}
if (!(flags & WRITE_BACK)) {
if (arg == next_arg && argw == (next_argw & 0x3)) {
compiler->cache_arg = arg;
compiler->cache_argw = argw;
- FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? ((arg >> 4) & 0xf) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
tmp_ar = DR(TMP_REG3);
}
else
- FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? ((arg >> 4) & 0xf) : TMP_REG3) | DA(tmp_ar), tmp_ar));
+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | DA(tmp_ar), tmp_ar));
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
}
- FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? ((arg >> 4) & 0xf) : TMP_REG3) | D(base), DR(base)));
+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(base), DR(base)));
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), delay_slot);
}
@@ -829,7 +910,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
if (GET_FLAGS(op))
flags |= UNUSED_DEST;
}
- else if (dst <= TMP_REG3) {
+ else if (FAST_IS_REG(dst)) {
dst_r = dst;
flags |= REG_DEST;
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
@@ -862,7 +943,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
}
/* Source 1. */
- if (src1 <= TMP_REG3) {
+ if (FAST_IS_REG(src1)) {
src1_r = src1;
flags |= REG1_SOURCE;
}
@@ -883,7 +964,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
}
/* Source 2. */
- if (src2 <= TMP_REG3) {
+ if (FAST_IS_REG(src2)) {
src2_r = src2;
flags |= REG2_SOURCE;
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
@@ -941,6 +1022,10 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
{
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ sljit_si int_op = op & SLJIT_INT_OP;
+#endif
+
CHECK_ERROR();
check_sljit_emit_op0(compiler, op);
@@ -952,7 +1037,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
return push_inst(compiler, NOP, UNMOVABLE_INS);
case SLJIT_UMUL:
case SLJIT_SMUL:
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ FAIL_IF(push_inst(compiler, (op == SLJIT_UMUL ? DMULTU : DMULT) | S(SLJIT_SCRATCH_REG1) | T(SLJIT_SCRATCH_REG2), MOVABLE_INS));
+#else
FAIL_IF(push_inst(compiler, (op == SLJIT_UMUL ? MULTU : MULT) | S(SLJIT_SCRATCH_REG1) | T(SLJIT_SCRATCH_REG2), MOVABLE_INS));
+#endif
FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_SCRATCH_REG1), DR(SLJIT_SCRATCH_REG1)));
return push_inst(compiler, MFHI | D(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG2));
case SLJIT_UDIV:
@@ -961,7 +1050,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
#endif
+
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if (int_op)
+ FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVU : DIV) | S(SLJIT_SCRATCH_REG1) | T(SLJIT_SCRATCH_REG2), MOVABLE_INS));
+ else
+ FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DDIVU : DDIV) | S(SLJIT_SCRATCH_REG1) | T(SLJIT_SCRATCH_REG2), MOVABLE_INS));
+#else
FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVU : DIV) | S(SLJIT_SCRATCH_REG1) | T(SLJIT_SCRATCH_REG2), MOVABLE_INS));
+#endif
+
FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_SCRATCH_REG1), DR(SLJIT_SCRATCH_REG1)));
return push_inst(compiler, MFHI | D(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG2));
}
@@ -975,6 +1073,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
{
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
# define flags 0
+#else
+ sljit_si flags = 0;
#endif
CHECK_ERROR();
@@ -982,50 +1082,74 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src, srcw);
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if ((op & SLJIT_INT_OP) && GET_OPCODE(op) >= SLJIT_NOT) {
+ flags |= INT_DATA | SIGNED_DATA;
+ if (src & SLJIT_IMM)
+ srcw = (sljit_si)srcw;
+ }
+#endif
+
switch (GET_OPCODE(op)) {
case SLJIT_MOV:
case SLJIT_MOV_P:
- return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+ return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
case SLJIT_MOV_UI:
- return emit_op(compiler, SLJIT_MOV_UI, flags | INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ return emit_op(compiler, SLJIT_MOV_UI, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+#else
+ return emit_op(compiler, SLJIT_MOV_UI, INT_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ui)srcw : srcw);
+#endif
case SLJIT_MOV_SI:
- return emit_op(compiler, SLJIT_MOV_SI, flags | INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ return emit_op(compiler, SLJIT_MOV_SI, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+#else
+ return emit_op(compiler, SLJIT_MOV_SI, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_si)srcw : srcw);
+#endif
case SLJIT_MOV_UB:
- return emit_op(compiler, SLJIT_MOV_UB, flags | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_UB, BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
case SLJIT_MOV_SB:
- return emit_op(compiler, SLJIT_MOV_SB, flags | BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_SB, BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
case SLJIT_MOV_UH:
- return emit_op(compiler, SLJIT_MOV_UH, flags | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_UH, HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
case SLJIT_MOV_SH:
- return emit_op(compiler, SLJIT_MOV_SH, flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_SH, HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
case SLJIT_MOVU:
case SLJIT_MOVU_P:
- return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+ return emit_op(compiler, SLJIT_MOV, WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
case SLJIT_MOVU_UI:
- return emit_op(compiler, SLJIT_MOV_UI, flags | INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ return emit_op(compiler, SLJIT_MOV_UI, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+#else
+ return emit_op(compiler, SLJIT_MOV_UI, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ui)srcw : srcw);
+#endif
case SLJIT_MOVU_SI:
- return emit_op(compiler, SLJIT_MOV_SI, flags | INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ return emit_op(compiler, SLJIT_MOV_SI, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+#else
+ return emit_op(compiler, SLJIT_MOV_SI, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_si)srcw : srcw);
+#endif
case SLJIT_MOVU_UB:
- return emit_op(compiler, SLJIT_MOV_UB, flags | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_UB, BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
case SLJIT_MOVU_SB:
- return emit_op(compiler, SLJIT_MOV_SB, flags | BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_SB, BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
case SLJIT_MOVU_UH:
- return emit_op(compiler, SLJIT_MOV_UH, flags | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_UH, HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
case SLJIT_MOVU_SH:
- return emit_op(compiler, SLJIT_MOV_SH, flags | HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_SH, HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
case SLJIT_NOT:
return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
@@ -1038,6 +1162,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
}
return SLJIT_SUCCESS;
+
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
# undef flags
#endif
@@ -1050,6 +1175,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
{
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
# define flags 0
+#else
+ sljit_si flags = 0;
#endif
CHECK_ERROR();
@@ -1058,6 +1185,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if (op & SLJIT_INT_OP) {
+ flags |= INT_DATA | SIGNED_DATA;
+ if (src1 & SLJIT_IMM)
+ src1w = (sljit_si)src1w;
+ if (src2 & SLJIT_IMM)
+ src2w = (sljit_si)src2w;
+ }
+#endif
+
switch (GET_OPCODE(op)) {
case SLJIT_ADD:
case SLJIT_ADDC:
@@ -1082,12 +1219,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
if (src2 & SLJIT_IMM)
src2w &= 0x1f;
#else
- SLJIT_ASSERT_STOP();
+ if (src2 & SLJIT_IMM) {
+ if (op & SLJIT_INT_OP)
+ src2w &= 0x1f;
+ else
+ src2w &= 0x3f;
+ }
#endif
return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
}
return SLJIT_SUCCESS;
+
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
# undef flags
#endif
@@ -1121,9 +1264,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *co
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
{
-#if (defined SLJIT_QEMU && SLJIT_QEMU)
- /* Qemu says fir is 0 by default. */
- return 1;
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return SLJIT_IS_FPU_AVAILABLE;
#elif defined(__GNUC__)
sljit_sw fir;
asm ("cfc1 %0, $0" : "=r"(fir));
@@ -1150,14 +1292,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
compiler->cache_argw = 0;
if (GET_OPCODE(op) == SLJIT_CMPD) {
- if (dst > SLJIT_FLOAT_REG6) {
+ if (dst & SLJIT_MEM) {
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, dst, dstw, src, srcw));
dst = TMP_FREG1;
}
else
dst <<= 1;
- if (src > SLJIT_FLOAT_REG6) {
+ if (src & SLJIT_MEM) {
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src, srcw, 0, 0));
src = TMP_FREG2;
}
@@ -1185,9 +1327,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
return push_inst(compiler, C_UN_fmt | FMT(op) | FT(src) | FS(dst), FCSR_FCC);
}
- dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : (dst << 1);
+ dst_fr = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
- if (src > SLJIT_FLOAT_REG6) {
+ if (src & SLJIT_MEM) {
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_fr, src, srcw, dst, dstw));
src = dst_fr;
}
@@ -1229,9 +1371,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
compiler->cache_arg = 0;
compiler->cache_argw = 0;
- dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG2 : (dst << 1);
+ dst_fr = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG2;
- if (src1 > SLJIT_FLOAT_REG6) {
+ if (src1 & SLJIT_MEM) {
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {
FAIL_IF(compiler->error);
src1 = TMP_FREG1;
@@ -1241,7 +1383,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
else
src1 <<= 1;
- if (src2 > SLJIT_FLOAT_REG6) {
+ if (src2 & SLJIT_MEM) {
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {
FAIL_IF(compiler->error);
src2 = TMP_FREG2;
@@ -1309,7 +1451,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
if (dst == SLJIT_UNUSED)
return SLJIT_SUCCESS;
- if (dst <= TMP_REG3)
+ if (FAST_IS_REG(dst))
return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), DR(dst));
/* Memory. */
@@ -1322,7 +1464,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
check_sljit_emit_fast_return(compiler, src, srcw);
ADJUST_LOCAL_OFFSET(src, srcw);
- if (src <= TMP_REG3)
+ if (FAST_IS_REG(src))
FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));
else if (src & SLJIT_MEM)
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
@@ -1357,7 +1499,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
#define JUMP_LENGTH 4
#else
-#error "Implementation required"
+#define JUMP_LENGTH 8
#endif
#define BR_Z(src) \
@@ -1467,7 +1609,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
} else {
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
/* Cannot be optimized out if type is >= CALL0. */
- jump->flags |= IS_JAL | (type >= SLJIT_CALL0 ? SLJIT_REWRITABLE_JUMP : 0);
+ jump->flags |= IS_JAL | (type >= SLJIT_CALL0 ? IS_CALL : 0);
PTR_FAIL_IF(push_inst(compiler, JALR | S(TMP_REG2) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
jump->addr = compiler->size;
/* A NOP if type < CALL1. */
@@ -1631,14 +1773,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile
compiler->cache_arg = 0;
compiler->cache_argw = 0;
- if (src1 > SLJIT_FLOAT_REG6) {
+ if (src1 & SLJIT_MEM) {
PTR_FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(type) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
src1 = TMP_FREG1;
}
else
src1 <<= 1;
- if (src2 > SLJIT_FLOAT_REG6) {
+ if (src2 & SLJIT_MEM) {
PTR_FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(type) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));
src2 = TMP_FREG2;
}
@@ -1714,7 +1856,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
check_sljit_emit_ijump(compiler, type, src, srcw);
ADJUST_LOCAL_OFFSET(src, srcw);
- if (src <= TMP_REG3) {
+ if (FAST_IS_REG(src)) {
if (DR(src) != 4)
src_r = src;
else
@@ -1770,6 +1912,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
{
sljit_si sugg_dst_ar, dst_ar;
sljit_si flags = GET_ALL_FLAGS(op);
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+# define mem_type WORD_DATA
+#else
+ sljit_si mem_type = (op & SLJIT_INT_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
+#endif
CHECK_ERROR();
check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type);
@@ -1779,13 +1926,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
return SLJIT_SUCCESS;
op = GET_OPCODE(op);
- sugg_dst_ar = DR((op < SLJIT_ADD && dst <= TMP_REG3) ? dst : TMP_REG2);
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if (op == SLJIT_MOV_SI || op == SLJIT_MOV_UI)
+ mem_type = INT_DATA | SIGNED_DATA;
+#endif
+ sugg_dst_ar = DR((op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2);
compiler->cache_arg = 0;
compiler->cache_argw = 0;
if (op >= SLJIT_ADD && (src & SLJIT_MEM)) {
ADJUST_LOCAL_OFFSET(src, srcw);
- FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG1), src, srcw, dst, dstw));
+ FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), src, srcw, dst, dstw));
src = TMP_REG1;
srcw = 0;
}
@@ -1853,15 +2004,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
if (op >= SLJIT_ADD) {
if (DR(TMP_REG2) != dst_ar)
FAIL_IF(push_inst(compiler, ADDU_W | SA(dst_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
- return emit_op(compiler, op | flags, CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0);
+ return emit_op(compiler, op | flags, mem_type | CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0);
}
if (dst & SLJIT_MEM)
- return emit_op_mem(compiler, WORD_DATA, dst_ar, dst, dstw);
+ return emit_op_mem(compiler, mem_type, dst_ar, dst, dstw);
if (sugg_dst_ar != dst_ar)
return push_inst(compiler, ADDU_W | SA(dst_ar) | TA(0) | DA(sugg_dst_ar), sugg_dst_ar);
return SLJIT_SUCCESS;
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+# undef mem_type
+#endif
}
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
@@ -1877,7 +2032,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
PTR_FAIL_IF(!const_);
set_const(const_, compiler);
- reg = (dst <= TMP_REG3) ? dst : TMP_REG2;
+ reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
PTR_FAIL_IF(emit_const(compiler, reg, init_value));
diff --git a/src/3rdparty/pcre/sljit/sljitNativePPC_32.c b/src/3rdparty/pcre/sljit/sljitNativePPC_32.c
index 0bd35a6e0e..b14b75ceb5 100644
--- a/src/3rdparty/pcre/sljit/sljitNativePPC_32.c
+++ b/src/3rdparty/pcre/sljit/sljitNativePPC_32.c
@@ -32,7 +32,7 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sl
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
if (!(imm & ~0xffff))
- return push_inst(compiler, ORI | S(ZERO_REG) | A(reg) | IMM(imm));
+ return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
diff --git a/src/3rdparty/pcre/sljit/sljitNativePPC_64.c b/src/3rdparty/pcre/sljit/sljitNativePPC_64.c
index 8eaeb41f4e..182ac7b3da 100644
--- a/src/3rdparty/pcre/sljit/sljitNativePPC_64.c
+++ b/src/3rdparty/pcre/sljit/sljitNativePPC_64.c
@@ -52,9 +52,9 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sl
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
if (!(imm & ~0xffff))
- return push_inst(compiler, ORI | S(ZERO_REG) | A(reg) | IMM(imm));
+ return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));
- if (imm <= SLJIT_W(0x7fffffff) && imm >= SLJIT_W(-0x80000000)) {
+ if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
}
diff --git a/src/3rdparty/pcre/sljit/sljitNativePPC_common.c b/src/3rdparty/pcre/sljit/sljitNativePPC_common.c
index 67e6898a17..5e06f2fd8e 100644
--- a/src/3rdparty/pcre/sljit/sljitNativePPC_common.c
+++ b/src/3rdparty/pcre/sljit/sljitNativePPC_common.c
@@ -33,10 +33,19 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
Both for ppc-32 and ppc-64. */
typedef sljit_ui sljit_ins;
+#if ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && (defined _AIX)) \
+ || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+#define SLJIT_PPC_STACK_FRAME_V2 1
+#endif
+
#ifdef _AIX
#include <sys/cache.h>
#endif
+#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
+#define SLJIT_PASS_ENTRY_ADDR_TO_CALL 1
+#endif
+
static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)
{
#ifdef _AIX
@@ -81,13 +90,19 @@ static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)
#define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
#define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
-#define ZERO_REG (SLJIT_NO_REGISTERS + 4)
+#define TMP_ZERO (SLJIT_NO_REGISTERS + 4)
+
+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
+#define TMP_CALL_REG (SLJIT_NO_REGISTERS + 5)
+#else
+#define TMP_CALL_REG TMP_REG2
+#endif
#define TMP_FREG1 (0)
#define TMP_FREG2 (SLJIT_FLOAT_REG6 + 1)
-static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
- 0, 3, 4, 5, 6, 7, 30, 29, 28, 27, 26, 1, 8, 9, 10, 31
+static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 6] = {
+ 0, 3, 4, 5, 6, 7, 30, 29, 28, 27, 26, 1, 8, 9, 10, 31, 12
};
/* --------------------------------------------------------------------- */
@@ -224,13 +239,19 @@ static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins)
return SLJIT_SUCCESS;
}
-static SLJIT_INLINE sljit_si optimize_jump(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
+static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
{
sljit_sw diff;
sljit_uw target_addr;
+ sljit_sw extra_jump_flags;
+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))
+ return 0;
+#else
if (jump->flags & SLJIT_REWRITABLE_JUMP)
return 0;
+#endif
if (jump->flags & JUMP_ADDR)
target_addr = jump->u.target;
@@ -238,28 +259,52 @@ static SLJIT_INLINE sljit_si optimize_jump(struct sljit_jump *jump, sljit_ins *c
SLJIT_ASSERT(jump->flags & JUMP_LABEL);
target_addr = (sljit_uw)(code + jump->u.label->size);
}
+
+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (jump->flags & IS_CALL)
+ goto keep_address;
+#endif
+
diff = ((sljit_sw)target_addr - (sljit_sw)(code_ptr)) & ~0x3l;
- if (jump->flags & UNCOND_B) {
- if (diff <= 0x01ffffff && diff >= -0x02000000) {
- jump->flags |= PATCH_B;
- return 1;
- }
- if (target_addr <= 0x03ffffff) {
- jump->flags |= PATCH_B | ABSOLUTE_B;
- return 1;
- }
- }
- else {
+ extra_jump_flags = 0;
+ if (jump->flags & IS_COND) {
if (diff <= 0x7fff && diff >= -0x8000) {
jump->flags |= PATCH_B;
return 1;
}
if (target_addr <= 0xffff) {
- jump->flags |= PATCH_B | ABSOLUTE_B;
+ jump->flags |= PATCH_B | PATCH_ABS_B;
return 1;
}
+ extra_jump_flags = REMOVE_COND;
+
+ diff -= sizeof(sljit_ins);
+ }
+
+ if (diff <= 0x01ffffff && diff >= -0x02000000) {
+ jump->flags |= PATCH_B | extra_jump_flags;
+ return 1;
}
+ if (target_addr <= 0x03ffffff) {
+ jump->flags |= PATCH_B | PATCH_ABS_B | extra_jump_flags;
+ return 1;
+ }
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
+keep_address:
+#endif
+ if (target_addr <= 0x7fffffff) {
+ jump->flags |= PATCH_ABS32;
+ return 1;
+ }
+ if (target_addr <= 0x7fffffffffffl) {
+ jump->flags |= PATCH_ABS48;
+ return 1;
+ }
+#endif
+
return 0;
}
@@ -318,19 +363,42 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
#else
jump->addr = (sljit_uw)(code_ptr - 6);
#endif
- if (optimize_jump(jump, code_ptr, code)) {
+ if (detect_jump_type(jump, code_ptr, code)) {
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
code_ptr[-3] = code_ptr[0];
code_ptr -= 3;
#else
- code_ptr[-6] = code_ptr[0];
- code_ptr -= 6;
+ if (jump->flags & PATCH_ABS32) {
+ code_ptr -= 3;
+ code_ptr[-1] = code_ptr[2];
+ code_ptr[0] = code_ptr[3];
+ }
+ else if (jump->flags & PATCH_ABS48) {
+ code_ptr--;
+ code_ptr[-1] = code_ptr[0];
+ code_ptr[0] = code_ptr[1];
+ /* rldicr rX,rX,32,31 -> rX,rX,16,47 */
+ SLJIT_ASSERT((code_ptr[-3] & 0xfc00ffff) == 0x780007c6);
+ code_ptr[-3] ^= 0x8422;
+ /* oris -> ori */
+ code_ptr[-2] ^= 0x4000000;
+ }
+ else {
+ code_ptr[-6] = code_ptr[0];
+ code_ptr -= 6;
+ }
#endif
+ if (jump->flags & REMOVE_COND) {
+ code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001);
+ code_ptr++;
+ jump->addr += sizeof(sljit_ins);
+ code_ptr[0] = Bx;
+ jump->flags -= IS_COND;
+ }
}
jump = jump->next;
}
if (const_ && const_->addr == word_count) {
- /* Just recording the address. */
const_->addr = (sljit_uw)code_ptr;
const_ = const_->next;
}
@@ -362,29 +430,27 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
buf_ptr = (sljit_ins*)jump->addr;
if (jump->flags & PATCH_B) {
- if (jump->flags & UNCOND_B) {
- if (!(jump->flags & ABSOLUTE_B)) {
+ if (jump->flags & IS_COND) {
+ if (!(jump->flags & PATCH_ABS_B)) {
addr = addr - jump->addr;
- SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000);
- *buf_ptr = Bx | (addr & 0x03fffffc) | ((*buf_ptr) & 0x1);
+ SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000);
+ *buf_ptr = BCx | (addr & 0xfffc) | ((*buf_ptr) & 0x03ff0001);
}
else {
- SLJIT_ASSERT(addr <= 0x03ffffff);
- *buf_ptr = Bx | (addr & 0x03fffffc) | 0x2 | ((*buf_ptr) & 0x1);
+ SLJIT_ASSERT(addr <= 0xffff);
+ *buf_ptr = BCx | (addr & 0xfffc) | 0x2 | ((*buf_ptr) & 0x03ff0001);
}
}
else {
- if (!(jump->flags & ABSOLUTE_B)) {
+ if (!(jump->flags & PATCH_ABS_B)) {
addr = addr - jump->addr;
- SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000);
- *buf_ptr = BCx | (addr & 0xfffc) | ((*buf_ptr) & 0x03ff0001);
+ SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000);
+ *buf_ptr = Bx | (addr & 0x03fffffc) | ((*buf_ptr) & 0x1);
}
else {
- addr = addr & ~0x3l;
- SLJIT_ASSERT(addr <= 0xffff);
- *buf_ptr = BCx | (addr & 0xfffc) | 0x2 | ((*buf_ptr) & 0x03ff0001);
+ SLJIT_ASSERT(addr <= 0x03ffffff);
+ *buf_ptr = Bx | (addr & 0x03fffffc) | 0x2 | ((*buf_ptr) & 0x1);
}
-
}
break;
}
@@ -393,6 +459,19 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
#else
+ if (jump->flags & PATCH_ABS32) {
+ SLJIT_ASSERT(addr <= 0x7fffffff);
+ buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
+ buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
+ break;
+ }
+ if (jump->flags & PATCH_ABS48) {
+ SLJIT_ASSERT(addr <= 0x7fffffffffff);
+ buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 32) & 0xffff);
+ buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 16) & 0xffff);
+ buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | (addr & 0xffff);
+ break;
+ }
buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 48) & 0xffff);
buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 32) & 0xffff);
buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | ((addr >> 16) & 0xffff);
@@ -498,7 +577,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
#endif
FAIL_IF(push_inst(compiler, MFLR | D(0)));
- FAIL_IF(push_inst(compiler, STACK_STORE | S(ZERO_REG) | A(SLJIT_LOCALS_REG) | IMM(-(sljit_si)(sizeof(sljit_sw))) ));
+ FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(SLJIT_LOCALS_REG) | IMM(-(sljit_si)(sizeof(sljit_sw))) ));
if (saveds >= 1)
FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_REG1) | A(SLJIT_LOCALS_REG) | IMM(-2 * (sljit_si)(sizeof(sljit_sw))) ));
if (saveds >= 2)
@@ -509,9 +588,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_EREG1) | A(SLJIT_LOCALS_REG) | IMM(-5 * (sljit_si)(sizeof(sljit_sw))) ));
if (saveds >= 5)
FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_EREG2) | A(SLJIT_LOCALS_REG) | IMM(-6 * (sljit_si)(sizeof(sljit_sw))) ));
+#if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
+ FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_LOCALS_REG) | IMM(2 * sizeof(sljit_sw)) ));
+#else
FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_LOCALS_REG) | IMM(sizeof(sljit_sw)) ));
+#endif
- FAIL_IF(push_inst(compiler, ADDI | D(ZERO_REG) | A(0) | 0));
+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));
if (args >= 1)
FAIL_IF(push_inst(compiler, OR | S(SLJIT_SCRATCH_REG1) | A(SLJIT_SAVED_REG1) | B(SLJIT_SCRATCH_REG1)));
if (args >= 2)
@@ -519,7 +602,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
if (args >= 3)
FAIL_IF(push_inst(compiler, OR | S(SLJIT_SCRATCH_REG3) | A(SLJIT_SAVED_REG3) | B(SLJIT_SCRATCH_REG3)));
-#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
+#if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
compiler->local_size = (1 + saveds + 6 + 8) * sizeof(sljit_sw) + local_size;
#else
compiler->local_size = (1 + saveds + 2) * sizeof(sljit_sw) + local_size;
@@ -556,7 +639,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
compiler->logical_local_size = local_size;
#endif
-#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
+#if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
compiler->local_size = (1 + saveds + 6 + 8) * sizeof(sljit_sw) + local_size;
#else
compiler->local_size = (1 + saveds + 2) * sizeof(sljit_sw) + local_size;
@@ -578,7 +661,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
FAIL_IF(push_inst(compiler, ADD | D(SLJIT_LOCALS_REG) | A(SLJIT_LOCALS_REG) | B(0)));
}
+#if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
+ FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_LOCALS_REG) | IMM(2 * sizeof(sljit_sw))));
+#else
FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_LOCALS_REG) | IMM(sizeof(sljit_sw))));
+#endif
if (compiler->saveds >= 5)
FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_EREG2) | A(SLJIT_LOCALS_REG) | IMM(-6 * (sljit_si)(sizeof(sljit_sw))) ));
if (compiler->saveds >= 4)
@@ -589,7 +676,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_REG2) | A(SLJIT_LOCALS_REG) | IMM(-3 * (sljit_si)(sizeof(sljit_sw))) ));
if (compiler->saveds >= 1)
FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_REG1) | A(SLJIT_LOCALS_REG) | IMM(-2 * (sljit_si)(sizeof(sljit_sw))) ));
- FAIL_IF(push_inst(compiler, STACK_LOAD | D(ZERO_REG) | A(SLJIT_LOCALS_REG) | IMM(-(sljit_si)(sizeof(sljit_sw))) ));
+ FAIL_IF(push_inst(compiler, STACK_LOAD | D(TMP_ZERO) | A(SLJIT_LOCALS_REG) | IMM(-(sljit_si)(sizeof(sljit_sw))) ));
FAIL_IF(push_inst(compiler, MTLR | S(0)));
FAIL_IF(push_inst(compiler, BLR));
@@ -612,7 +699,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
It contans 32 items, but not all are different. */
/* 64 bit only: [reg+imm] must be aligned to 4 bytes. */
-#define ADDR_MODE2 0x10000
+#define INT_ALIGNED 0x10000
/* 64-bit only: there is no lwau instruction. */
#define UPDATE_REQ 0x20000
@@ -623,7 +710,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
#else
#define ARCH_32_64(a, b) b
#define INST_CODE_AND_DST(inst, flags, reg) \
- (((inst) & ~(ADDR_MODE2 | UPDATE_REQ)) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
+ (((inst) & ~(INT_ALIGNED | UPDATE_REQ)) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
#endif
static SLJIT_CONST sljit_ins data_transfer_insts[64 + 8] = {
@@ -632,13 +719,13 @@ static SLJIT_CONST sljit_ins data_transfer_insts[64 + 8] = {
/* Word. */
-/* u w n i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | ADDR_MODE2 | 0x0 /* std */),
-/* u w n i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | ADDR_MODE2 | 0x0 /* ld */),
+/* u w n i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),
+/* u w n i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),
/* u w n x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
/* u w n x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
-/* u w w i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | ADDR_MODE2 | 0x1 /* stdu */),
-/* u w w i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | ADDR_MODE2 | 0x1 /* ldu */),
+/* u w w i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),
+/* u w w i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),
/* u w w x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
/* u w w x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
@@ -682,13 +769,13 @@ static SLJIT_CONST sljit_ins data_transfer_insts[64 + 8] = {
/* Word. */
-/* s w n i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | ADDR_MODE2 | 0x0 /* std */),
-/* s w n i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | ADDR_MODE2 | 0x0 /* ld */),
+/* s w n i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),
+/* s w n i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),
/* s w n x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
/* s w n x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
-/* s w w i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | ADDR_MODE2 | 0x1 /* stdu */),
-/* s w w i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | ADDR_MODE2 | 0x1 /* ldu */),
+/* s w w i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),
+/* s w w i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),
/* s w w x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
/* s w w x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
@@ -719,12 +806,12 @@ static SLJIT_CONST sljit_ins data_transfer_insts[64 + 8] = {
/* Int. */
/* s i n i s */ HI(36) /* stw */,
-/* s i n i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | ADDR_MODE2 | 0x2 /* lwa */),
+/* s i n i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x2 /* lwa */),
/* s i n x s */ HI(31) | LO(151) /* stwx */,
/* s i n x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */),
/* s i w i s */ HI(37) /* stwu */,
-/* s i w i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | ADDR_MODE2 | UPDATE_REQ | 0x2 /* lwa */),
+/* s i w i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | UPDATE_REQ | 0x2 /* lwa */),
/* s i w x s */ HI(31) | LO(183) /* stwux */,
/* s i w x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */),
@@ -748,74 +835,48 @@ static SLJIT_CONST sljit_ins data_transfer_insts[64 + 8] = {
static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si inp_flags, sljit_si reg, sljit_si arg, sljit_sw argw)
{
sljit_ins inst;
-#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- sljit_si tmp_reg;
-#endif
+ /* Should work when (arg & REG_MASK) == 0. */
+ SLJIT_COMPILE_ASSERT(A(0) == 0, a0_must_be_0);
SLJIT_ASSERT(arg & SLJIT_MEM);
- if (!(arg & 0xf)) {
-#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
- if (argw <= SIMM_MAX && argw >= SIMM_MIN) {
- if (inp_flags & ARG_TEST)
- return 1;
-
- inst = data_transfer_insts[(inp_flags & ~WRITE_BACK) & MEM_MASK];
- SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
- push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | IMM(argw));
- return -1;
- }
-#else
- inst = data_transfer_insts[(inp_flags & ~WRITE_BACK) & MEM_MASK];
- if (argw <= SIMM_MAX && argw >= SIMM_MIN &&
- (!(inst & ADDR_MODE2) || (argw & 0x3) == 0)) {
- if (inp_flags & ARG_TEST)
- return 1;
-
- push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | IMM(argw));
- return -1;
- }
-#endif
- return 0;
- }
- if (!(arg & 0xf0)) {
-#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
- if (argw <= SIMM_MAX && argw >= SIMM_MIN) {
- if (inp_flags & ARG_TEST)
- return 1;
-
- inst = data_transfer_insts[inp_flags & MEM_MASK];
- SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
- push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & 0xf) | IMM(argw));
- return -1;
- }
-#else
- inst = data_transfer_insts[inp_flags & MEM_MASK];
- if (argw <= SIMM_MAX && argw >= SIMM_MIN && (!(inst & ADDR_MODE2) || (argw & 0x3) == 0)) {
- if (inp_flags & ARG_TEST)
- return 1;
-
- if ((inp_flags & WRITE_BACK) && (inst & UPDATE_REQ)) {
- tmp_reg = (inp_flags & LOAD_DATA) ? (arg & 0xf) : TMP_REG3;
- if (push_inst(compiler, ADDI | D(tmp_reg) | A(arg & 0xf) | IMM(argw)))
- return -1;
- arg = tmp_reg | SLJIT_MEM;
- argw = 0;
- }
- push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & 0xf) | IMM(argw));
- return -1;
- }
-#endif
- }
- else if (!(argw & 0x3)) {
+ if (arg & OFFS_REG_MASK) {
+ if (argw & 0x3)
+ return 0;
if (inp_flags & ARG_TEST)
return 1;
+
inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
- SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
- push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & 0xf) | B((arg >> 4) & 0xf));
+ SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ)));
+ FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(OFFS_REG(arg))));
return -1;
}
- return 0;
+
+ if (SLJIT_UNLIKELY(!(arg & REG_MASK)))
+ inp_flags &= ~WRITE_BACK;
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ inst = data_transfer_insts[inp_flags & MEM_MASK];
+ SLJIT_ASSERT((arg & REG_MASK) || !(inst & UPDATE_REQ));
+
+ if (argw > SIMM_MAX || argw < SIMM_MIN || ((inst & INT_ALIGNED) && (argw & 0x3)) || (inst & UPDATE_REQ))
+ return 0;
+ if (inp_flags & ARG_TEST)
+ return 1;
+#endif
+
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ if (argw > SIMM_MAX || argw < SIMM_MIN)
+ return 0;
+ if (inp_flags & ARG_TEST)
+ return 1;
+
+ inst = data_transfer_insts[inp_flags & MEM_MASK];
+ SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ)));
+#endif
+
+ FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | IMM(argw)));
+ return -1;
}
/* See getput_arg below.
@@ -823,35 +884,50 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si inp_fl
uses word arguments without write back. */
static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
{
+ sljit_sw high_short, next_high_short;
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ sljit_sw diff;
+#endif
+
SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
- if (!(arg & 0xf))
- return (next_arg & SLJIT_MEM) && ((sljit_uw)argw - (sljit_uw)next_argw <= SIMM_MAX || (sljit_uw)next_argw - (sljit_uw)argw <= SIMM_MAX);
+ if (arg & OFFS_REG_MASK)
+ return ((arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK) && (argw & 0x3) == (next_argw & 0x3));
- if (arg & 0xf0)
- return ((arg & 0xf0) == (next_arg & 0xf0) && (argw & 0x3) == (next_argw & 0x3));
+ if (next_arg & OFFS_REG_MASK)
+ return 0;
- if (argw <= SIMM_MAX && argw >= SIMM_MIN) {
- if (arg == next_arg && (next_argw >= SIMM_MAX && next_argw <= SIMM_MIN))
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ high_short = (argw + ((argw & 0x8000) << 1)) & ~0xffff;
+ next_high_short = (next_argw + ((next_argw & 0x8000) << 1)) & ~0xffff;
+ return high_short == next_high_short;
+#else
+ if (argw <= 0x7fffffffl && argw >= -0x80000000l) {
+ high_short = (argw + ((argw & 0x8000) << 1)) & ~0xffff;
+ next_high_short = (next_argw + ((next_argw & 0x8000) << 1)) & ~0xffff;
+ if (high_short == next_high_short)
return 1;
}
- if (arg == next_arg && ((sljit_uw)argw - (sljit_uw)next_argw <= SIMM_MAX || (sljit_uw)next_argw - (sljit_uw)argw <= SIMM_MAX))
+ diff = argw - next_argw;
+ if (!(arg & REG_MASK))
+ return diff <= SIMM_MAX && diff >= SIMM_MIN;
+
+ if (arg == next_arg && diff <= SIMM_MAX && diff >= SIMM_MIN)
return 1;
return 0;
+#endif
}
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
#define ADJUST_CACHED_IMM(imm) \
- if ((inst & ADDR_MODE2) && (imm & 0x3)) { \
+ if ((inst & INT_ALIGNED) && (imm & 0x3)) { \
/* Adjust cached value. Fortunately this is really a rare case */ \
compiler->cache_argw += imm & 0x3; \
FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG3) | A(TMP_REG3) | (imm & 0x3))); \
imm &= ~0x3; \
}
-#else
-#define ADJUST_CACHED_IMM(imm)
#endif
/* Emit the necessary instructions. See can_cache above. */
@@ -859,72 +935,125 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
{
sljit_si tmp_r;
sljit_ins inst;
+ sljit_sw high_short, next_high_short;
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ sljit_sw diff;
+#endif
SLJIT_ASSERT(arg & SLJIT_MEM);
tmp_r = ((inp_flags & LOAD_DATA) && ((inp_flags) & MEM_MASK) <= GPR_REG) ? reg : TMP_REG1;
/* Special case for "mov reg, [reg, ... ]". */
- if ((arg & 0xf) == tmp_r)
+ if ((arg & REG_MASK) == tmp_r)
tmp_r = TMP_REG1;
- if (!(arg & 0xf)) {
- inst = data_transfer_insts[(inp_flags & ~WRITE_BACK) & MEM_MASK];
- if ((compiler->cache_arg & SLJIT_IMM) && (((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= SIMM_MAX || ((sljit_uw)compiler->cache_argw - (sljit_uw)argw) <= SIMM_MAX)) {
- argw = argw - compiler->cache_argw;
- ADJUST_CACHED_IMM(argw);
- SLJIT_ASSERT(!(inst & UPDATE_REQ));
- return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(TMP_REG3) | IMM(argw));
- }
-
- if ((next_arg & SLJIT_MEM) && (argw - next_argw <= SIMM_MAX || next_argw - argw <= SIMM_MAX)) {
- SLJIT_ASSERT(inp_flags & LOAD_DATA);
-
- compiler->cache_arg = SLJIT_IMM;
- compiler->cache_argw = argw;
- tmp_r = TMP_REG3;
- }
-
- FAIL_IF(load_immediate(compiler, tmp_r, argw));
- return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_r));
- }
-
- if (SLJIT_UNLIKELY(arg & 0xf0)) {
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
argw &= 0x3;
/* Otherwise getput_arg_fast would capture it. */
SLJIT_ASSERT(argw);
- if ((SLJIT_MEM | (arg & 0xf0)) == compiler->cache_arg && argw == compiler->cache_argw)
+ if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg && argw == compiler->cache_argw)
tmp_r = TMP_REG3;
else {
- if ((arg & 0xf0) == (next_arg & 0xf0) && argw == (next_argw & 0x3)) {
- compiler->cache_arg = SLJIT_MEM | (arg & 0xf0);
+ if ((arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK) && argw == (next_argw & 0x3)) {
+ compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);
compiler->cache_argw = argw;
tmp_r = TMP_REG3;
}
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
- FAIL_IF(push_inst(compiler, RLWINM | S((arg >> 4) & 0xf) | A(tmp_r) | (argw << 11) | ((31 - argw) << 1)));
+ FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(arg)) | A(tmp_r) | (argw << 11) | ((31 - argw) << 1)));
#else
- FAIL_IF(push_inst(compiler, RLDI(tmp_r, (arg >> 4) & 0xf, argw, 63 - argw, 1)));
+ FAIL_IF(push_inst(compiler, RLDI(tmp_r, OFFS_REG(arg), argw, 63 - argw, 1)));
#endif
}
inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
- SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
- return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & 0xf) | B(tmp_r));
+ SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ)));
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(tmp_r));
}
+ if (SLJIT_UNLIKELY(!(arg & REG_MASK)))
+ inp_flags &= ~WRITE_BACK;
+
inst = data_transfer_insts[inp_flags & MEM_MASK];
+ SLJIT_ASSERT((arg & REG_MASK) || !(inst & UPDATE_REQ));
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (argw <= 0x7fff7fffl && argw >= -0x80000000l
+ && (!(inst & INT_ALIGNED) || !(argw & 0x3)) && !(inst & UPDATE_REQ)) {
+#endif
+
+ arg &= REG_MASK;
+ high_short = (sljit_si)(argw + ((argw & 0x8000) << 1)) & ~0xffff;
+ /* The getput_arg_fast should handle this otherwise. */
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ SLJIT_ASSERT(high_short && high_short <= 0x7fffffffl && high_short >= -0x80000000l);
+#else
+ SLJIT_ASSERT(high_short && !(inst & (INT_ALIGNED | UPDATE_REQ)));
+#endif
- if (compiler->cache_arg == arg && ((sljit_uw)argw - (sljit_uw)compiler->cache_argw <= SIMM_MAX || (sljit_uw)compiler->cache_argw - (sljit_uw)argw <= SIMM_MAX)) {
- SLJIT_ASSERT(!(inp_flags & WRITE_BACK));
- argw = argw - compiler->cache_argw;
- ADJUST_CACHED_IMM(argw);
- return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(TMP_REG3) | IMM(argw));
+ if (inp_flags & WRITE_BACK) {
+ if (arg == reg) {
+ FAIL_IF(push_inst(compiler, OR | S(reg) | A(tmp_r) | B(reg)));
+ reg = tmp_r;
+ }
+ tmp_r = arg;
+ FAIL_IF(push_inst(compiler, ADDIS | D(arg) | A(arg) | IMM(high_short >> 16)));
+ }
+ else if (compiler->cache_arg != arg || high_short != compiler->cache_argw) {
+ if ((next_arg & SLJIT_MEM) && !(next_arg & OFFS_REG_MASK)) {
+ next_high_short = (sljit_si)(next_argw + ((next_argw & 0x8000) << 1)) & ~0xffff;
+ if (high_short == next_high_short) {
+ compiler->cache_arg = SLJIT_IMM | arg;
+ compiler->cache_argw = next_high_short;
+ tmp_r = TMP_REG3;
+ }
+ }
+ FAIL_IF(push_inst(compiler, ADDIS | D(tmp_r) | A(arg & REG_MASK) | IMM(high_short >> 16)));
+ }
+ else
+ tmp_r = TMP_REG3;
+
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_r) | IMM(argw));
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ }
+
+ /* Everything else is PPC-64 only. */
+ if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {
+ diff = argw - compiler->cache_argw;
+ if ((compiler->cache_arg & SLJIT_IMM) && diff <= SIMM_MAX && diff >= SIMM_MIN) {
+ ADJUST_CACHED_IMM(diff);
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(TMP_REG3) | IMM(diff));
+ }
+
+ diff = argw - next_argw;
+ if ((next_arg & SLJIT_MEM) && diff <= SIMM_MAX && diff >= SIMM_MIN) {
+ SLJIT_ASSERT(inp_flags & LOAD_DATA);
+
+ compiler->cache_arg = SLJIT_IMM;
+ compiler->cache_argw = argw;
+ tmp_r = TMP_REG3;
+ }
+
+ FAIL_IF(load_immediate(compiler, tmp_r, argw));
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_r));
+ }
+
+ diff = argw - compiler->cache_argw;
+ if (compiler->cache_arg == arg && diff <= SIMM_MAX && diff >= SIMM_MIN) {
+ SLJIT_ASSERT(!(inp_flags & WRITE_BACK) && !(inst & UPDATE_REQ));
+ ADJUST_CACHED_IMM(diff);
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(TMP_REG3) | IMM(diff));
}
- if ((compiler->cache_arg & SLJIT_IMM) && compiler->cache_argw == argw) {
+ if ((compiler->cache_arg & SLJIT_IMM) && diff <= SIMM_MAX && diff >= SIMM_MIN) {
inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
- SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
- return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & 0xf) | B(TMP_REG3));
+ SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ)));
+ if (compiler->cache_argw != argw) {
+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG3) | A(TMP_REG3) | IMM(diff)));
+ compiler->cache_argw = argw;
+ }
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(TMP_REG3));
}
if (argw == next_argw && (next_arg & SLJIT_MEM)) {
@@ -935,14 +1064,15 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
compiler->cache_argw = argw;
inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
- SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
- return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & 0xf) | B(TMP_REG3));
+ SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ)));
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(TMP_REG3));
}
- if (arg == next_arg && !(inp_flags & WRITE_BACK) && ((sljit_uw)argw - (sljit_uw)next_argw <= SIMM_MAX || (sljit_uw)next_argw - (sljit_uw)argw <= SIMM_MAX)) {
+ diff = argw - next_argw;
+ if (arg == next_arg && !(inp_flags & WRITE_BACK) && diff <= SIMM_MAX && diff >= SIMM_MIN) {
SLJIT_ASSERT(inp_flags & LOAD_DATA);
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
- FAIL_IF(push_inst(compiler, ADD | D(TMP_REG3) | A(TMP_REG3) | B(arg & 0xf)));
+ FAIL_IF(push_inst(compiler, ADD | D(TMP_REG3) | A(TMP_REG3) | B(arg & REG_MASK)));
compiler->cache_arg = arg;
compiler->cache_argw = argw;
@@ -950,11 +1080,22 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(TMP_REG3));
}
+ if ((next_arg & SLJIT_MEM) && !(next_arg & OFFS_REG_MASK) && diff <= SIMM_MAX && diff >= SIMM_MIN) {
+ SLJIT_ASSERT(inp_flags & LOAD_DATA);
+ FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+
+ compiler->cache_arg = SLJIT_IMM;
+ compiler->cache_argw = argw;
+ tmp_r = TMP_REG3;
+ }
+ else
+ FAIL_IF(load_immediate(compiler, tmp_r, argw));
+
/* Get the indexed version instead of the normal one. */
inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
- SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
- FAIL_IF(load_immediate(compiler, tmp_r, argw));
- return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & 0xf) | B(tmp_r));
+ SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ)));
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(tmp_r));
+#endif
}
static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg1, sljit_sw arg1w, sljit_si arg2, sljit_sw arg2w)
@@ -990,7 +1131,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si i
return SLJIT_SUCCESS;
dst_r = TMP_REG2;
}
- else if (dst <= ZERO_REG) {
+ else if (FAST_IS_REG(dst)) {
dst_r = dst;
flags |= REG_DEST;
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
@@ -1009,7 +1150,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si i
}
/* Source 1. */
- if (src1 <= ZERO_REG) {
+ if (FAST_IS_REG(src1)) {
src1_r = src1;
flags |= REG1_SOURCE;
}
@@ -1025,7 +1166,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si i
src1_r = 0;
/* Source 2. */
- if (src2 <= ZERO_REG) {
+ if (FAST_IS_REG(src2)) {
src2_r = src2;
flags |= REG2_SOURCE;
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
@@ -1095,38 +1236,42 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si i
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
{
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ sljit_si int_op = op & SLJIT_INT_OP;
+#endif
+
CHECK_ERROR();
check_sljit_emit_op0(compiler, op);
- switch (GET_OPCODE(op)) {
+ op = GET_OPCODE(op);
+ switch (op) {
case SLJIT_BREAKPOINT:
case SLJIT_NOP:
return push_inst(compiler, NOP);
- break;
case SLJIT_UMUL:
case SLJIT_SMUL:
FAIL_IF(push_inst(compiler, OR | S(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG1)));
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2)));
- return push_inst(compiler, (GET_OPCODE(op) == SLJIT_UMUL ? MULHDU : MULHD) | D(SLJIT_SCRATCH_REG2) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2));
+ return push_inst(compiler, (op == SLJIT_UMUL ? MULHDU : MULHD) | D(SLJIT_SCRATCH_REG2) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2));
#else
FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2)));
- return push_inst(compiler, (GET_OPCODE(op) == SLJIT_UMUL ? MULHWU : MULHW) | D(SLJIT_SCRATCH_REG2) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2));
+ return push_inst(compiler, (op == SLJIT_UMUL ? MULHWU : MULHW) | D(SLJIT_SCRATCH_REG2) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2));
#endif
case SLJIT_UDIV:
case SLJIT_SDIV:
FAIL_IF(push_inst(compiler, OR | S(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG1)));
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- if (op & SLJIT_INT_OP) {
- FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_UDIV ? DIVWU : DIVW) | D(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2)));
+ if (int_op) {
+ FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVWU : DIVW) | D(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2)));
FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_SCRATCH_REG2) | A(SLJIT_SCRATCH_REG1) | B(SLJIT_SCRATCH_REG2)));
- return push_inst(compiler, SUBF | D(SLJIT_SCRATCH_REG2) | A(SLJIT_SCRATCH_REG2) | B(TMP_REG1));
+ } else {
+ FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVDU : DIVD) | D(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2)));
+ FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_SCRATCH_REG2) | A(SLJIT_SCRATCH_REG1) | B(SLJIT_SCRATCH_REG2)));
}
- FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_UDIV ? DIVDU : DIVD) | D(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2)));
- FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_SCRATCH_REG2) | A(SLJIT_SCRATCH_REG1) | B(SLJIT_SCRATCH_REG2)));
return push_inst(compiler, SUBF | D(SLJIT_SCRATCH_REG2) | A(SLJIT_SCRATCH_REG2) | B(TMP_REG1));
#else
- FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_UDIV ? DIVWU : DIVW) | D(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2)));
+ FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVWU : DIVW) | D(SLJIT_SCRATCH_REG1) | A(TMP_REG1) | B(SLJIT_SCRATCH_REG2)));
FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_SCRATCH_REG2) | A(SLJIT_SCRATCH_REG1) | B(SLJIT_SCRATCH_REG2)));
return push_inst(compiler, SUBF | D(SLJIT_SCRATCH_REG2) | A(SLJIT_SCRATCH_REG2) | B(TMP_REG1));
#endif
@@ -1152,14 +1297,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
op = GET_OPCODE(op);
if ((src & SLJIT_IMM) && srcw == 0)
- src = ZERO_REG;
+ src = TMP_ZERO;
if (op_flags & SLJIT_SET_O)
- FAIL_IF(push_inst(compiler, MTXER | S(ZERO_REG)));
+ FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
if (op_flags & SLJIT_INT_OP) {
- if (op >= SLJIT_MOV && op <= SLJIT_MOVU_P) {
- if (src <= ZERO_REG && src == dst) {
+ if (op < SLJIT_NOT) {
+ if (FAST_IS_REG(src) && src == dst) {
if (!TYPE_CAST_NEEDED(op))
return SLJIT_SUCCESS;
}
@@ -1268,7 +1413,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
#define TEST_SH_IMM(src, srcw) \
- (((src) & SLJIT_IMM) && !((srcw) & 0xffff) && (srcw) <= SLJIT_W(0x7fffffff) && (srcw) >= SLJIT_W(-0x80000000))
+ (((src) & SLJIT_IMM) && !((srcw) & 0xffff) && (srcw) <= 0x7fffffffl && (srcw) >= -0x80000000l)
#else
#define TEST_SH_IMM(src, srcw) \
(((src) & SLJIT_IMM) && !((srcw) & 0xffff))
@@ -1279,7 +1424,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
#define TEST_ADD_IMM(src, srcw) \
- (((src) & SLJIT_IMM) && (srcw) <= SLJIT_W(0x7fff7fff) && (srcw) >= SLJIT_W(-0x80000000))
+ (((src) & SLJIT_IMM) && (srcw) <= 0x7fff7fffl && (srcw) >= -0x80000000l)
#else
#define TEST_ADD_IMM(src, srcw) \
((src) & SLJIT_IMM)
@@ -1307,9 +1452,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
ADJUST_LOCAL_OFFSET(src2, src2w);
if ((src1 & SLJIT_IMM) && src1w == 0)
- src1 = ZERO_REG;
+ src1 = TMP_ZERO;
if ((src2 & SLJIT_IMM) && src2w == 0)
- src2 = ZERO_REG;
+ src2 = TMP_ZERO;
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
if (op & SLJIT_INT_OP) {
@@ -1324,7 +1469,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
}
#endif
if (op & SLJIT_SET_O)
- FAIL_IF(push_inst(compiler, MTXER | S(ZERO_REG)));
+ FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
if (src2 == TMP_REG2)
flags |= ALT_KEEP_CACHE;
@@ -1392,7 +1537,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
}
}
- if (dst == SLJIT_UNUSED && (op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U)) && !(op & (SLJIT_SET_O | SLJIT_SET_C))) {
+ if (dst == SLJIT_UNUSED && (op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S)) && !(op & (SLJIT_SET_O | SLJIT_SET_C))) {
if (!(op & SLJIT_SET_U)) {
/* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */
if (TEST_SL_IMM(src2, src2w)) {
@@ -1418,7 +1563,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
}
return emit_op(compiler, SLJIT_SUB, flags | ((op & SLJIT_SET_U) ? ALT_FORM4 : 0) | ((op & (SLJIT_SET_E | SLJIT_SET_S)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
}
- if (!(op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O))) {
+ if (!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O))) {
if (TEST_SL_IMM(src2, -src2w)) {
compiler->imm = (-src2w) & 0xffff;
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
@@ -1529,8 +1674,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *co
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
{
- /* Always available. */
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return SLJIT_IS_FPU_AVAILABLE;
+#else
+ /* Available by default. */
return 1;
+#endif
}
#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_SINGLE_OP) >> 6))
@@ -1550,12 +1699,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
compiler->cache_argw = 0;
if (GET_OPCODE(op) == SLJIT_CMPD) {
- if (dst > SLJIT_FLOAT_REG6) {
+ if (dst & SLJIT_MEM) {
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, dst, dstw, src, srcw));
dst = TMP_FREG1;
}
- if (src > SLJIT_FLOAT_REG6) {
+ if (src & SLJIT_MEM) {
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src, srcw, 0, 0));
src = TMP_FREG2;
}
@@ -1563,9 +1712,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
return push_inst(compiler, FCMPU | CRD(4) | FA(dst) | FB(src));
}
- dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : dst;
+ dst_fr = FAST_IS_REG(dst) ? dst : TMP_FREG1;
- if (src > SLJIT_FLOAT_REG6) {
+ if (src & SLJIT_MEM) {
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_fr, src, srcw, dst, dstw));
src = dst_fr;
}
@@ -1605,9 +1754,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
compiler->cache_arg = 0;
compiler->cache_argw = 0;
- dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG2 : dst;
+ dst_fr = FAST_IS_REG(dst) ? dst : TMP_FREG2;
- if (src1 > SLJIT_FLOAT_REG6) {
+ if (src1 & SLJIT_MEM) {
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {
FAIL_IF(compiler->error);
src1 = TMP_FREG1;
@@ -1615,7 +1764,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
flags |= ALT_FORM1;
}
- if (src2 > SLJIT_FLOAT_REG6) {
+ if (src2 & SLJIT_MEM) {
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {
FAIL_IF(compiler->error);
src2 = TMP_FREG2;
@@ -1684,7 +1833,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
if (dst == SLJIT_UNUSED)
return SLJIT_SUCCESS;
- if (dst <= ZERO_REG)
+ if (FAST_IS_REG(dst))
return push_inst(compiler, MFLR | D(dst));
/* Memory. */
@@ -1698,7 +1847,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
check_sljit_emit_fast_return(compiler, src, srcw);
ADJUST_LOCAL_OFFSET(src, srcw);
- if (src <= ZERO_REG)
+ if (FAST_IS_REG(src))
FAIL_IF(push_inst(compiler, MTLR | S(src)));
else {
if (src & SLJIT_MEM)
@@ -1811,11 +1960,15 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
type &= 0xff;
/* In PPC, we don't need to touch the arguments. */
- if (type >= SLJIT_JUMP)
- jump->flags |= UNCOND_B;
+ if (type < SLJIT_JUMP)
+ jump->flags |= IS_COND;
+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
+ if (type >= SLJIT_CALL0)
+ jump->flags |= IS_CALL;
+#endif
- PTR_FAIL_IF(emit_const(compiler, TMP_REG1, 0));
- PTR_FAIL_IF(push_inst(compiler, MTCTR | S(TMP_REG1)));
+ PTR_FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0));
+ PTR_FAIL_IF(push_inst(compiler, MTCTR | S(TMP_CALL_REG)));
jump->addr = compiler->size;
PTR_FAIL_IF(push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0)));
return jump;
@@ -1830,20 +1983,32 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
check_sljit_emit_ijump(compiler, type, src, srcw);
ADJUST_LOCAL_OFFSET(src, srcw);
- if (src <= ZERO_REG)
+ if (FAST_IS_REG(src)) {
+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
+ if (type >= SLJIT_CALL0) {
+ FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));
+ src_r = TMP_CALL_REG;
+ }
+ else
+ src_r = src;
+#else
src_r = src;
- else if (src & SLJIT_IMM) {
+#endif
+ } else if (src & SLJIT_IMM) {
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
FAIL_IF(!jump);
- set_jump(jump, compiler, JUMP_ADDR | UNCOND_B);
+ set_jump(jump, compiler, JUMP_ADDR);
jump->u.target = srcw;
-
- FAIL_IF(emit_const(compiler, TMP_REG2, 0));
- src_r = TMP_REG2;
+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
+ if (type >= SLJIT_CALL0)
+ jump->flags |= IS_CALL;
+#endif
+ FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0));
+ src_r = TMP_CALL_REG;
}
else {
- FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
- src_r = TMP_REG2;
+ FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw));
+ src_r = TMP_CALL_REG;
}
FAIL_IF(push_inst(compiler, MTCTR | S(src_r)));
@@ -1867,6 +2032,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
{
sljit_si reg, input_flags;
sljit_si flags = GET_ALL_FLAGS(op);
+ sljit_sw original_dstw = dstw;
CHECK_ERROR();
check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type);
@@ -1876,7 +2042,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
return SLJIT_SUCCESS;
op = GET_OPCODE(op);
- reg = (op < SLJIT_ADD && dst <= ZERO_REG) ? dst : TMP_REG2;
+ reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
compiler->cache_arg = 0;
compiler->cache_argw = 0;
@@ -1988,13 +2154,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
op = SLJIT_MOV;
input_flags = WORD_DATA;
#endif
- return (reg == TMP_REG2) ? emit_op(compiler, op, input_flags, dst, dstw, TMP_REG1, 0, TMP_REG2, 0) : SLJIT_SUCCESS;
+ if (reg != TMP_REG2)
+ return SLJIT_SUCCESS;
+ return emit_op(compiler, op, input_flags, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
}
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
compiler->skip_checks = 1;
#endif
- return sljit_emit_op2(compiler, op | flags, dst, dstw, src, srcw, TMP_REG2, 0);
+ return sljit_emit_op2(compiler, op | flags, dst, original_dstw, src, srcw, TMP_REG2, 0);
}
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
@@ -2010,7 +2178,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
PTR_FAIL_IF(!const_);
set_const(const_, compiler);
- reg = (dst <= ZERO_REG) ? dst : TMP_REG2;
+ reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
PTR_FAIL_IF(emit_const(compiler, reg, init_value));
diff --git a/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c b/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c
index e5571ee6dd..d6a1e12bfe 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c
@@ -87,7 +87,7 @@ static void sparc_cache_flush(sljit_ins *from, sljit_ins *to)
#define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
#define TMP_REG4 (SLJIT_NO_REGISTERS + 4)
-#define LINK_REG (SLJIT_NO_REGISTERS + 5)
+#define TMP_LINK (SLJIT_NO_REGISTERS + 5)
#define TMP_FREG1 (0)
#define TMP_FREG2 ((SLJIT_FLOAT_REG6 + 1) << 1)
@@ -190,7 +190,7 @@ static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_
return SLJIT_SUCCESS;
}
-static SLJIT_INLINE sljit_ins* optimize_jump(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
+static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
{
sljit_sw diff;
sljit_uw target_addr;
@@ -311,7 +311,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
#else
jump->addr = (sljit_uw)(code_ptr - 6);
#endif
- code_ptr = optimize_jump(jump, code_ptr, code);
+ code_ptr = detect_jump_type(jump, code_ptr, code);
jump = jump->next;
}
if (const_ && const_->addr == word_count) {
@@ -465,7 +465,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
CHECK_ERROR();
check_sljit_emit_return(compiler, op, src, srcw);
- if (op != SLJIT_MOV || !(src <= TMP_REG3)) {
+ if (op != SLJIT_MOV || !FAST_IS_REG(src)) {
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
src = SLJIT_SCRATCH_REG1;
}
@@ -516,15 +516,15 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags,
{
SLJIT_ASSERT(arg & SLJIT_MEM);
- if (!(flags & WRITE_BACK) || !(arg & 0xf)) {
- if ((!(arg & 0xf0) && argw <= SIMM_MAX && argw >= SIMM_MIN)
- || ((arg & 0xf0) && (argw & 0x3) == 0)) {
+ if (!(flags & WRITE_BACK) || !(arg & REG_MASK)) {
+ if ((!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN)
+ || ((arg & OFFS_REG_MASK) && (argw & 0x3) == 0)) {
/* Works for both absoulte and relative addresses (immediate case). */
if (SLJIT_UNLIKELY(flags & ARG_TEST))
return 1;
FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK]
| ((flags & MEM_MASK) <= GPR_REG ? D(reg) : DA(reg))
- | S1(arg & 0xf) | ((arg & 0xf0) ? S2((arg >> 4) & 0xf) : IMM(argw)),
+ | S1(arg & REG_MASK) | ((arg & OFFS_REG_MASK) ? S2(OFFS_REG(arg)) : IMM(argw)),
((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS));
return -1;
}
@@ -540,11 +540,11 @@ static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_
SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
/* Simple operation except for updates. */
- if (arg & 0xf0) {
+ if (arg & OFFS_REG_MASK) {
argw &= 0x3;
SLJIT_ASSERT(argw);
next_argw &= 0x3;
- if ((arg & 0xf0) == (next_arg & 0xf0) && argw == next_argw)
+ if ((arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK) && argw == next_argw)
return 1;
return 0;
}
@@ -566,25 +566,25 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
next_argw = 0;
}
- base = arg & 0xf;
- if (SLJIT_UNLIKELY(arg & 0xf0)) {
+ base = arg & REG_MASK;
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
argw &= 0x3;
SLJIT_ASSERT(argw != 0);
/* Using the cache. */
- if (((SLJIT_MEM | (arg & 0xf0)) == compiler->cache_arg) && (argw == compiler->cache_argw))
+ if (((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) && (argw == compiler->cache_argw))
arg2 = TMP_REG3;
else {
- if ((arg & 0xf0) == (next_arg & 0xf0) && argw == (next_argw & 0x3)) {
- compiler->cache_arg = SLJIT_MEM | (arg & 0xf0);
+ if ((arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK) && argw == (next_argw & 0x3)) {
+ compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);
compiler->cache_argw = argw;
arg2 = TMP_REG3;
}
- else if ((flags & LOAD_DATA) && ((flags & MEM_MASK) <= GPR_REG) && reg != base && (reg << 4) != (arg & 0xf0))
+ else if ((flags & LOAD_DATA) && ((flags & MEM_MASK) <= GPR_REG) && reg != base && reg != OFFS_REG(arg))
arg2 = reg;
else /* It must be a mov operation, so tmp1 must be free to use. */
arg2 = TMP_REG1;
- FAIL_IF(push_inst(compiler, SLL_W | D(arg2) | S1((arg >> 4) & 0xf) | IMM_ARG | argw, DR(arg2)));
+ FAIL_IF(push_inst(compiler, SLL_W | D(arg2) | S1(OFFS_REG(arg)) | IMM_ARG | argw, DR(arg2)));
}
}
else {
@@ -658,7 +658,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
return SLJIT_SUCCESS;
}
- else if (dst <= TMP_REG3) {
+ else if (FAST_IS_REG(dst)) {
dst_r = dst;
flags |= REG_DEST;
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
@@ -689,7 +689,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
}
/* Source 1. */
- if (src1 <= TMP_REG3)
+ if (FAST_IS_REG(src1))
src1_r = src1;
else if (src1 & SLJIT_IMM) {
if (src1w) {
@@ -708,7 +708,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
}
/* Source 2. */
- if (src2 <= TMP_REG3) {
+ if (FAST_IS_REG(src2)) {
src2_r = src2;
flags |= REG2_SOURCE;
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
@@ -943,7 +943,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *co
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
{
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return SLJIT_IS_FPU_AVAILABLE;
+#else
+ /* Available by default. */
return 1;
+#endif
}
#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_SINGLE_OP) >> 7))
@@ -963,14 +968,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
compiler->cache_argw = 0;
if (GET_OPCODE(op) == SLJIT_CMPD) {
- if (dst > SLJIT_FLOAT_REG6) {
+ if (dst & SLJIT_MEM) {
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, dst, dstw, src, srcw));
dst = TMP_FREG1;
}
else
dst <<= 1;
- if (src > SLJIT_FLOAT_REG6) {
+ if (src & SLJIT_MEM) {
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src, srcw, 0, 0));
src = TMP_FREG2;
}
@@ -980,9 +985,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
return push_inst(compiler, SELECT_FOP(op, FCMPS, FCMPD) | S1A(dst) | S2A(src), FCC_IS_SET | MOVABLE_INS);
}
- dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : (dst << 1);
+ dst_fr = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
- if (src > SLJIT_FLOAT_REG6) {
+ if (src & SLJIT_MEM) {
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_fr, src, srcw, dst, dstw));
src = dst_fr;
}
@@ -1031,9 +1036,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
compiler->cache_arg = 0;
compiler->cache_argw = 0;
- dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG2 : (dst << 1);
+ dst_fr = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG2;
- if (src1 > SLJIT_FLOAT_REG6) {
+ if (src1 & SLJIT_MEM) {
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {
FAIL_IF(compiler->error);
src1 = TMP_FREG1;
@@ -1043,7 +1048,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
else
src1 <<= 1;
- if (src2 > SLJIT_FLOAT_REG6) {
+ if (src2 & SLJIT_MEM) {
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {
FAIL_IF(compiler->error);
src2 = TMP_FREG2;
@@ -1114,11 +1119,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
if (dst == SLJIT_UNUSED)
return SLJIT_SUCCESS;
- if (dst <= TMP_REG3)
- return push_inst(compiler, OR | D(dst) | S1(0) | S2(LINK_REG), DR(dst));
+ if (FAST_IS_REG(dst))
+ return push_inst(compiler, OR | D(dst) | S1(0) | S2(TMP_LINK), DR(dst));
/* Memory. */
- return emit_op_mem(compiler, WORD_DATA, LINK_REG, dst, dstw);
+ return emit_op_mem(compiler, WORD_DATA, TMP_LINK, dst, dstw);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
@@ -1127,14 +1132,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
check_sljit_emit_fast_return(compiler, src, srcw);
ADJUST_LOCAL_OFFSET(src, srcw);
- if (src <= TMP_REG3)
- FAIL_IF(push_inst(compiler, OR | D(LINK_REG) | S1(0) | S2(src), DR(LINK_REG)));
+ if (FAST_IS_REG(src))
+ FAIL_IF(push_inst(compiler, OR | D(TMP_LINK) | S1(0) | S2(src), DR(TMP_LINK)));
else if (src & SLJIT_MEM)
- FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, LINK_REG, src, srcw));
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_LINK, src, srcw));
else if (src & SLJIT_IMM)
- FAIL_IF(load_immediate(compiler, LINK_REG, srcw));
+ FAIL_IF(load_immediate(compiler, TMP_LINK, srcw));
- FAIL_IF(push_inst(compiler, JMPL | D(0) | S1(LINK_REG) | IMM(8), UNMOVABLE_INS));
+ FAIL_IF(push_inst(compiler, JMPL | D(0) | S1(TMP_LINK) | IMM(8), UNMOVABLE_INS));
return push_inst(compiler, NOP, UNMOVABLE_INS);
}
@@ -1269,7 +1274,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
}
PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));
- PTR_FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? LINK_REG : 0) | S1(TMP_REG2) | IMM(0), UNMOVABLE_INS));
+ PTR_FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? TMP_LINK : 0) | S1(TMP_REG2) | IMM(0), UNMOVABLE_INS));
jump->addr = compiler->size;
PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
@@ -1285,7 +1290,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
check_sljit_emit_ijump(compiler, type, src, srcw);
ADJUST_LOCAL_OFFSET(src, srcw);
- if (src <= TMP_REG3)
+ if (FAST_IS_REG(src))
src_r = src;
else if (src & SLJIT_IMM) {
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
@@ -1305,7 +1310,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
src_r = TMP_REG2;
}
- FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? LINK_REG : 0) | S1(src_r) | IMM(0), UNMOVABLE_INS));
+ FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? TMP_LINK : 0) | S1(src_r) | IMM(0), UNMOVABLE_INS));
if (jump)
jump->addr = compiler->size;
return push_inst(compiler, NOP, UNMOVABLE_INS);
@@ -1327,7 +1332,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
op = GET_OPCODE(op);
- reg = (op < SLJIT_ADD && dst <= TMP_REG3) ? dst : TMP_REG2;
+ reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
compiler->cache_arg = 0;
compiler->cache_argw = 0;
@@ -1368,12 +1373,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
PTR_FAIL_IF(!const_);
set_const(const_, compiler);
- reg = (dst <= TMP_REG3) ? dst : TMP_REG2;
+ reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
PTR_FAIL_IF(emit_const(compiler, reg, init_value));
if (dst & SLJIT_MEM)
PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
-
return const_;
}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeTILEGX-encoder.c b/src/3rdparty/pcre/sljit/sljitNativeTILEGX-encoder.c
new file mode 100644
index 0000000000..719632908c
--- /dev/null
+++ b/src/3rdparty/pcre/sljit/sljitNativeTILEGX-encoder.c
@@ -0,0 +1,10159 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright 2013-2013 Tilera Corporation(jiwang@tilera.com). All rights reserved.
+ * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.
+ */
+
+/* This code is owned by Tilera Corporation, and distributed as part
+ of multiple projects. In sljit, the code is under BSD licence. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define BFD_RELOC(x) R_##x
+
+/* Special registers. */
+#define TREG_LR 55
+#define TREG_SN 56
+#define TREG_ZERO 63
+
+/* Canonical name of each register. */
+const char *const tilegx_register_names[] =
+{
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+ "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
+ "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
+ "r48", "r49", "r50", "r51", "r52", "tp", "sp", "lr",
+ "sn", "idn0", "idn1", "udn0", "udn1", "udn2", "udn3", "zero"
+};
+
+enum
+{
+ R_NONE = 0,
+ R_TILEGX_NONE = 0,
+ R_TILEGX_64 = 1,
+ R_TILEGX_32 = 2,
+ R_TILEGX_16 = 3,
+ R_TILEGX_8 = 4,
+ R_TILEGX_64_PCREL = 5,
+ R_TILEGX_32_PCREL = 6,
+ R_TILEGX_16_PCREL = 7,
+ R_TILEGX_8_PCREL = 8,
+ R_TILEGX_HW0 = 9,
+ R_TILEGX_HW1 = 10,
+ R_TILEGX_HW2 = 11,
+ R_TILEGX_HW3 = 12,
+ R_TILEGX_HW0_LAST = 13,
+ R_TILEGX_HW1_LAST = 14,
+ R_TILEGX_HW2_LAST = 15,
+ R_TILEGX_COPY = 16,
+ R_TILEGX_GLOB_DAT = 17,
+ R_TILEGX_JMP_SLOT = 18,
+ R_TILEGX_RELATIVE = 19,
+ R_TILEGX_BROFF_X1 = 20,
+ R_TILEGX_JUMPOFF_X1 = 21,
+ R_TILEGX_JUMPOFF_X1_PLT = 22,
+ R_TILEGX_IMM8_X0 = 23,
+ R_TILEGX_IMM8_Y0 = 24,
+ R_TILEGX_IMM8_X1 = 25,
+ R_TILEGX_IMM8_Y1 = 26,
+ R_TILEGX_DEST_IMM8_X1 = 27,
+ R_TILEGX_MT_IMM14_X1 = 28,
+ R_TILEGX_MF_IMM14_X1 = 29,
+ R_TILEGX_MMSTART_X0 = 30,
+ R_TILEGX_MMEND_X0 = 31,
+ R_TILEGX_SHAMT_X0 = 32,
+ R_TILEGX_SHAMT_X1 = 33,
+ R_TILEGX_SHAMT_Y0 = 34,
+ R_TILEGX_SHAMT_Y1 = 35,
+ R_TILEGX_IMM16_X0_HW0 = 36,
+ R_TILEGX_IMM16_X1_HW0 = 37,
+ R_TILEGX_IMM16_X0_HW1 = 38,
+ R_TILEGX_IMM16_X1_HW1 = 39,
+ R_TILEGX_IMM16_X0_HW2 = 40,
+ R_TILEGX_IMM16_X1_HW2 = 41,
+ R_TILEGX_IMM16_X0_HW3 = 42,
+ R_TILEGX_IMM16_X1_HW3 = 43,
+ R_TILEGX_IMM16_X0_HW0_LAST = 44,
+ R_TILEGX_IMM16_X1_HW0_LAST = 45,
+ R_TILEGX_IMM16_X0_HW1_LAST = 46,
+ R_TILEGX_IMM16_X1_HW1_LAST = 47,
+ R_TILEGX_IMM16_X0_HW2_LAST = 48,
+ R_TILEGX_IMM16_X1_HW2_LAST = 49,
+ R_TILEGX_IMM16_X0_HW0_PCREL = 50,
+ R_TILEGX_IMM16_X1_HW0_PCREL = 51,
+ R_TILEGX_IMM16_X0_HW1_PCREL = 52,
+ R_TILEGX_IMM16_X1_HW1_PCREL = 53,
+ R_TILEGX_IMM16_X0_HW2_PCREL = 54,
+ R_TILEGX_IMM16_X1_HW2_PCREL = 55,
+ R_TILEGX_IMM16_X0_HW3_PCREL = 56,
+ R_TILEGX_IMM16_X1_HW3_PCREL = 57,
+ R_TILEGX_IMM16_X0_HW0_LAST_PCREL = 58,
+ R_TILEGX_IMM16_X1_HW0_LAST_PCREL = 59,
+ R_TILEGX_IMM16_X0_HW1_LAST_PCREL = 60,
+ R_TILEGX_IMM16_X1_HW1_LAST_PCREL = 61,
+ R_TILEGX_IMM16_X0_HW2_LAST_PCREL = 62,
+ R_TILEGX_IMM16_X1_HW2_LAST_PCREL = 63,
+ R_TILEGX_IMM16_X0_HW0_GOT = 64,
+ R_TILEGX_IMM16_X1_HW0_GOT = 65,
+
+ R_TILEGX_IMM16_X0_HW0_PLT_PCREL = 66,
+ R_TILEGX_IMM16_X1_HW0_PLT_PCREL = 67,
+ R_TILEGX_IMM16_X0_HW1_PLT_PCREL = 68,
+ R_TILEGX_IMM16_X1_HW1_PLT_PCREL = 69,
+ R_TILEGX_IMM16_X0_HW2_PLT_PCREL = 70,
+ R_TILEGX_IMM16_X1_HW2_PLT_PCREL = 71,
+
+ R_TILEGX_IMM16_X0_HW0_LAST_GOT = 72,
+ R_TILEGX_IMM16_X1_HW0_LAST_GOT = 73,
+ R_TILEGX_IMM16_X0_HW1_LAST_GOT = 74,
+ R_TILEGX_IMM16_X1_HW1_LAST_GOT = 75,
+ R_TILEGX_IMM16_X0_HW0_TLS_GD = 78,
+ R_TILEGX_IMM16_X1_HW0_TLS_GD = 79,
+ R_TILEGX_IMM16_X0_HW0_TLS_LE = 80,
+ R_TILEGX_IMM16_X1_HW0_TLS_LE = 81,
+ R_TILEGX_IMM16_X0_HW0_LAST_TLS_LE = 82,
+ R_TILEGX_IMM16_X1_HW0_LAST_TLS_LE = 83,
+ R_TILEGX_IMM16_X0_HW1_LAST_TLS_LE = 84,
+ R_TILEGX_IMM16_X1_HW1_LAST_TLS_LE = 85,
+ R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD = 86,
+ R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD = 87,
+ R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD = 88,
+ R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD = 89,
+ R_TILEGX_IMM16_X0_HW0_TLS_IE = 92,
+ R_TILEGX_IMM16_X1_HW0_TLS_IE = 93,
+
+ R_TILEGX_IMM16_X0_HW0_LAST_PLT_PCREL = 94,
+ R_TILEGX_IMM16_X1_HW0_LAST_PLT_PCREL = 95,
+ R_TILEGX_IMM16_X0_HW1_LAST_PLT_PCREL = 96,
+ R_TILEGX_IMM16_X1_HW1_LAST_PLT_PCREL = 97,
+ R_TILEGX_IMM16_X0_HW2_LAST_PLT_PCREL = 98,
+ R_TILEGX_IMM16_X1_HW2_LAST_PLT_PCREL = 99,
+
+ R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE = 100,
+ R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE = 101,
+ R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE = 102,
+ R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE = 103,
+ R_TILEGX_TLS_DTPMOD64 = 106,
+ R_TILEGX_TLS_DTPOFF64 = 107,
+ R_TILEGX_TLS_TPOFF64 = 108,
+ R_TILEGX_TLS_DTPMOD32 = 109,
+ R_TILEGX_TLS_DTPOFF32 = 110,
+ R_TILEGX_TLS_TPOFF32 = 111,
+ R_TILEGX_TLS_GD_CALL = 112,
+ R_TILEGX_IMM8_X0_TLS_GD_ADD = 113,
+ R_TILEGX_IMM8_X1_TLS_GD_ADD = 114,
+ R_TILEGX_IMM8_Y0_TLS_GD_ADD = 115,
+ R_TILEGX_IMM8_Y1_TLS_GD_ADD = 116,
+ R_TILEGX_TLS_IE_LOAD = 117,
+ R_TILEGX_IMM8_X0_TLS_ADD = 118,
+ R_TILEGX_IMM8_X1_TLS_ADD = 119,
+ R_TILEGX_IMM8_Y0_TLS_ADD = 120,
+ R_TILEGX_IMM8_Y1_TLS_ADD = 121,
+ R_TILEGX_GNU_VTINHERIT = 128,
+ R_TILEGX_GNU_VTENTRY = 129,
+ R_TILEGX_IRELATIVE = 130,
+ R_TILEGX_NUM = 131
+};
+
+typedef enum
+{
+ TILEGX_PIPELINE_X0,
+ TILEGX_PIPELINE_X1,
+ TILEGX_PIPELINE_Y0,
+ TILEGX_PIPELINE_Y1,
+ TILEGX_PIPELINE_Y2,
+} tilegx_pipeline;
+
+typedef unsigned long long tilegx_bundle_bits;
+
+/* These are the bits that determine if a bundle is in the X encoding. */
+#define TILEGX_BUNDLE_MODE_MASK ((tilegx_bundle_bits)3 << 62)
+
+enum
+{
+ /* Maximum number of instructions in a bundle (2 for X, 3 for Y). */
+ TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE = 3,
+
+ /* How many different pipeline encodings are there? X0, X1, Y0, Y1, Y2. */
+ TILEGX_NUM_PIPELINE_ENCODINGS = 5,
+
+ /* Log base 2 of TILEGX_BUNDLE_SIZE_IN_BYTES. */
+ TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES = 3,
+
+ /* Instructions take this many bytes. */
+ TILEGX_BUNDLE_SIZE_IN_BYTES = 1 << TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES,
+
+ /* Log base 2 of TILEGX_BUNDLE_ALIGNMENT_IN_BYTES. */
+ TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES = 3,
+
+ /* Bundles should be aligned modulo this number of bytes. */
+ TILEGX_BUNDLE_ALIGNMENT_IN_BYTES =
+ (1 << TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES),
+
+ /* Number of registers (some are magic, such as network I/O). */
+ TILEGX_NUM_REGISTERS = 64,
+};
+
+/* Make a few "tile_" variables to simplify common code between
+ architectures. */
+
+typedef tilegx_bundle_bits tile_bundle_bits;
+#define TILE_BUNDLE_SIZE_IN_BYTES TILEGX_BUNDLE_SIZE_IN_BYTES
+#define TILE_BUNDLE_ALIGNMENT_IN_BYTES TILEGX_BUNDLE_ALIGNMENT_IN_BYTES
+#define TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES \
+ TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES
+
+/* 64-bit pattern for a { bpt ; nop } bundle. */
+#define TILEGX_BPT_BUNDLE 0x286a44ae51485000ULL
+
+typedef enum
+{
+ TILEGX_OP_TYPE_REGISTER,
+ TILEGX_OP_TYPE_IMMEDIATE,
+ TILEGX_OP_TYPE_ADDRESS,
+ TILEGX_OP_TYPE_SPR
+} tilegx_operand_type;
+
+struct tilegx_operand
+{
+ /* Is this operand a register, immediate or address? */
+ tilegx_operand_type type;
+
+ /* The default relocation type for this operand. */
+ signed int default_reloc : 16;
+
+ /* How many bits is this value? (used for range checking) */
+ unsigned int num_bits : 5;
+
+ /* Is the value signed? (used for range checking) */
+ unsigned int is_signed : 1;
+
+ /* Is this operand a source register? */
+ unsigned int is_src_reg : 1;
+
+ /* Is this operand written? (i.e. is it a destination register) */
+ unsigned int is_dest_reg : 1;
+
+ /* Is this operand PC-relative? */
+ unsigned int is_pc_relative : 1;
+
+ /* By how many bits do we right shift the value before inserting? */
+ unsigned int rightshift : 2;
+
+ /* Return the bits for this operand to be ORed into an existing bundle. */
+ tilegx_bundle_bits (*insert) (int op);
+
+ /* Extract this operand and return it. */
+ unsigned int (*extract) (tilegx_bundle_bits bundle);
+};
+
+typedef enum
+{
+ TILEGX_OPC_BPT,
+ TILEGX_OPC_INFO,
+ TILEGX_OPC_INFOL,
+ TILEGX_OPC_LD4S_TLS,
+ TILEGX_OPC_LD_TLS,
+ TILEGX_OPC_MOVE,
+ TILEGX_OPC_MOVEI,
+ TILEGX_OPC_MOVELI,
+ TILEGX_OPC_PREFETCH,
+ TILEGX_OPC_PREFETCH_ADD_L1,
+ TILEGX_OPC_PREFETCH_ADD_L1_FAULT,
+ TILEGX_OPC_PREFETCH_ADD_L2,
+ TILEGX_OPC_PREFETCH_ADD_L2_FAULT,
+ TILEGX_OPC_PREFETCH_ADD_L3,
+ TILEGX_OPC_PREFETCH_ADD_L3_FAULT,
+ TILEGX_OPC_PREFETCH_L1,
+ TILEGX_OPC_PREFETCH_L1_FAULT,
+ TILEGX_OPC_PREFETCH_L2,
+ TILEGX_OPC_PREFETCH_L2_FAULT,
+ TILEGX_OPC_PREFETCH_L3,
+ TILEGX_OPC_PREFETCH_L3_FAULT,
+ TILEGX_OPC_RAISE,
+ TILEGX_OPC_ADD,
+ TILEGX_OPC_ADDI,
+ TILEGX_OPC_ADDLI,
+ TILEGX_OPC_ADDX,
+ TILEGX_OPC_ADDXI,
+ TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXSC,
+ TILEGX_OPC_AND,
+ TILEGX_OPC_ANDI,
+ TILEGX_OPC_BEQZ,
+ TILEGX_OPC_BEQZT,
+ TILEGX_OPC_BFEXTS,
+ TILEGX_OPC_BFEXTU,
+ TILEGX_OPC_BFINS,
+ TILEGX_OPC_BGEZ,
+ TILEGX_OPC_BGEZT,
+ TILEGX_OPC_BGTZ,
+ TILEGX_OPC_BGTZT,
+ TILEGX_OPC_BLBC,
+ TILEGX_OPC_BLBCT,
+ TILEGX_OPC_BLBS,
+ TILEGX_OPC_BLBST,
+ TILEGX_OPC_BLEZ,
+ TILEGX_OPC_BLEZT,
+ TILEGX_OPC_BLTZ,
+ TILEGX_OPC_BLTZT,
+ TILEGX_OPC_BNEZ,
+ TILEGX_OPC_BNEZT,
+ TILEGX_OPC_CLZ,
+ TILEGX_OPC_CMOVEQZ,
+ TILEGX_OPC_CMOVNEZ,
+ TILEGX_OPC_CMPEQ,
+ TILEGX_OPC_CMPEQI,
+ TILEGX_OPC_CMPEXCH,
+ TILEGX_OPC_CMPEXCH4,
+ TILEGX_OPC_CMPLES,
+ TILEGX_OPC_CMPLEU,
+ TILEGX_OPC_CMPLTS,
+ TILEGX_OPC_CMPLTSI,
+ TILEGX_OPC_CMPLTU,
+ TILEGX_OPC_CMPLTUI,
+ TILEGX_OPC_CMPNE,
+ TILEGX_OPC_CMUL,
+ TILEGX_OPC_CMULA,
+ TILEGX_OPC_CMULAF,
+ TILEGX_OPC_CMULF,
+ TILEGX_OPC_CMULFR,
+ TILEGX_OPC_CMULH,
+ TILEGX_OPC_CMULHR,
+ TILEGX_OPC_CRC32_32,
+ TILEGX_OPC_CRC32_8,
+ TILEGX_OPC_CTZ,
+ TILEGX_OPC_DBLALIGN,
+ TILEGX_OPC_DBLALIGN2,
+ TILEGX_OPC_DBLALIGN4,
+ TILEGX_OPC_DBLALIGN6,
+ TILEGX_OPC_DRAIN,
+ TILEGX_OPC_DTLBPR,
+ TILEGX_OPC_EXCH,
+ TILEGX_OPC_EXCH4,
+ TILEGX_OPC_FDOUBLE_ADD_FLAGS,
+ TILEGX_OPC_FDOUBLE_ADDSUB,
+ TILEGX_OPC_FDOUBLE_MUL_FLAGS,
+ TILEGX_OPC_FDOUBLE_PACK1,
+ TILEGX_OPC_FDOUBLE_PACK2,
+ TILEGX_OPC_FDOUBLE_SUB_FLAGS,
+ TILEGX_OPC_FDOUBLE_UNPACK_MAX,
+ TILEGX_OPC_FDOUBLE_UNPACK_MIN,
+ TILEGX_OPC_FETCHADD,
+ TILEGX_OPC_FETCHADD4,
+ TILEGX_OPC_FETCHADDGEZ,
+ TILEGX_OPC_FETCHADDGEZ4,
+ TILEGX_OPC_FETCHAND,
+ TILEGX_OPC_FETCHAND4,
+ TILEGX_OPC_FETCHOR,
+ TILEGX_OPC_FETCHOR4,
+ TILEGX_OPC_FINV,
+ TILEGX_OPC_FLUSH,
+ TILEGX_OPC_FLUSHWB,
+ TILEGX_OPC_FNOP,
+ TILEGX_OPC_FSINGLE_ADD1,
+ TILEGX_OPC_FSINGLE_ADDSUB2,
+ TILEGX_OPC_FSINGLE_MUL1,
+ TILEGX_OPC_FSINGLE_MUL2,
+ TILEGX_OPC_FSINGLE_PACK1,
+ TILEGX_OPC_FSINGLE_PACK2,
+ TILEGX_OPC_FSINGLE_SUB1,
+ TILEGX_OPC_ICOH,
+ TILEGX_OPC_ILL,
+ TILEGX_OPC_INV,
+ TILEGX_OPC_IRET,
+ TILEGX_OPC_J,
+ TILEGX_OPC_JAL,
+ TILEGX_OPC_JALR,
+ TILEGX_OPC_JALRP,
+ TILEGX_OPC_JR,
+ TILEGX_OPC_JRP,
+ TILEGX_OPC_LD,
+ TILEGX_OPC_LD1S,
+ TILEGX_OPC_LD1S_ADD,
+ TILEGX_OPC_LD1U,
+ TILEGX_OPC_LD1U_ADD,
+ TILEGX_OPC_LD2S,
+ TILEGX_OPC_LD2S_ADD,
+ TILEGX_OPC_LD2U,
+ TILEGX_OPC_LD2U_ADD,
+ TILEGX_OPC_LD4S,
+ TILEGX_OPC_LD4S_ADD,
+ TILEGX_OPC_LD4U,
+ TILEGX_OPC_LD4U_ADD,
+ TILEGX_OPC_LD_ADD,
+ TILEGX_OPC_LDNA,
+ TILEGX_OPC_LDNA_ADD,
+ TILEGX_OPC_LDNT,
+ TILEGX_OPC_LDNT1S,
+ TILEGX_OPC_LDNT1S_ADD,
+ TILEGX_OPC_LDNT1U,
+ TILEGX_OPC_LDNT1U_ADD,
+ TILEGX_OPC_LDNT2S,
+ TILEGX_OPC_LDNT2S_ADD,
+ TILEGX_OPC_LDNT2U,
+ TILEGX_OPC_LDNT2U_ADD,
+ TILEGX_OPC_LDNT4S,
+ TILEGX_OPC_LDNT4S_ADD,
+ TILEGX_OPC_LDNT4U,
+ TILEGX_OPC_LDNT4U_ADD,
+ TILEGX_OPC_LDNT_ADD,
+ TILEGX_OPC_LNK,
+ TILEGX_OPC_MF,
+ TILEGX_OPC_MFSPR,
+ TILEGX_OPC_MM,
+ TILEGX_OPC_MNZ,
+ TILEGX_OPC_MTSPR,
+ TILEGX_OPC_MUL_HS_HS,
+ TILEGX_OPC_MUL_HS_HU,
+ TILEGX_OPC_MUL_HS_LS,
+ TILEGX_OPC_MUL_HS_LU,
+ TILEGX_OPC_MUL_HU_HU,
+ TILEGX_OPC_MUL_HU_LS,
+ TILEGX_OPC_MUL_HU_LU,
+ TILEGX_OPC_MUL_LS_LS,
+ TILEGX_OPC_MUL_LS_LU,
+ TILEGX_OPC_MUL_LU_LU,
+ TILEGX_OPC_MULA_HS_HS,
+ TILEGX_OPC_MULA_HS_HU,
+ TILEGX_OPC_MULA_HS_LS,
+ TILEGX_OPC_MULA_HS_LU,
+ TILEGX_OPC_MULA_HU_HU,
+ TILEGX_OPC_MULA_HU_LS,
+ TILEGX_OPC_MULA_HU_LU,
+ TILEGX_OPC_MULA_LS_LS,
+ TILEGX_OPC_MULA_LS_LU,
+ TILEGX_OPC_MULA_LU_LU,
+ TILEGX_OPC_MULAX,
+ TILEGX_OPC_MULX,
+ TILEGX_OPC_MZ,
+ TILEGX_OPC_NAP,
+ TILEGX_OPC_NOP,
+ TILEGX_OPC_NOR,
+ TILEGX_OPC_OR,
+ TILEGX_OPC_ORI,
+ TILEGX_OPC_PCNT,
+ TILEGX_OPC_REVBITS,
+ TILEGX_OPC_REVBYTES,
+ TILEGX_OPC_ROTL,
+ TILEGX_OPC_ROTLI,
+ TILEGX_OPC_SHL,
+ TILEGX_OPC_SHL16INSLI,
+ TILEGX_OPC_SHL1ADD,
+ TILEGX_OPC_SHL1ADDX,
+ TILEGX_OPC_SHL2ADD,
+ TILEGX_OPC_SHL2ADDX,
+ TILEGX_OPC_SHL3ADD,
+ TILEGX_OPC_SHL3ADDX,
+ TILEGX_OPC_SHLI,
+ TILEGX_OPC_SHLX,
+ TILEGX_OPC_SHLXI,
+ TILEGX_OPC_SHRS,
+ TILEGX_OPC_SHRSI,
+ TILEGX_OPC_SHRU,
+ TILEGX_OPC_SHRUI,
+ TILEGX_OPC_SHRUX,
+ TILEGX_OPC_SHRUXI,
+ TILEGX_OPC_SHUFFLEBYTES,
+ TILEGX_OPC_ST,
+ TILEGX_OPC_ST1,
+ TILEGX_OPC_ST1_ADD,
+ TILEGX_OPC_ST2,
+ TILEGX_OPC_ST2_ADD,
+ TILEGX_OPC_ST4,
+ TILEGX_OPC_ST4_ADD,
+ TILEGX_OPC_ST_ADD,
+ TILEGX_OPC_STNT,
+ TILEGX_OPC_STNT1,
+ TILEGX_OPC_STNT1_ADD,
+ TILEGX_OPC_STNT2,
+ TILEGX_OPC_STNT2_ADD,
+ TILEGX_OPC_STNT4,
+ TILEGX_OPC_STNT4_ADD,
+ TILEGX_OPC_STNT_ADD,
+ TILEGX_OPC_SUB,
+ TILEGX_OPC_SUBX,
+ TILEGX_OPC_SUBXSC,
+ TILEGX_OPC_SWINT0,
+ TILEGX_OPC_SWINT1,
+ TILEGX_OPC_SWINT2,
+ TILEGX_OPC_SWINT3,
+ TILEGX_OPC_TBLIDXB0,
+ TILEGX_OPC_TBLIDXB1,
+ TILEGX_OPC_TBLIDXB2,
+ TILEGX_OPC_TBLIDXB3,
+ TILEGX_OPC_V1ADD,
+ TILEGX_OPC_V1ADDI,
+ TILEGX_OPC_V1ADDUC,
+ TILEGX_OPC_V1ADIFFU,
+ TILEGX_OPC_V1AVGU,
+ TILEGX_OPC_V1CMPEQ,
+ TILEGX_OPC_V1CMPEQI,
+ TILEGX_OPC_V1CMPLES,
+ TILEGX_OPC_V1CMPLEU,
+ TILEGX_OPC_V1CMPLTS,
+ TILEGX_OPC_V1CMPLTSI,
+ TILEGX_OPC_V1CMPLTU,
+ TILEGX_OPC_V1CMPLTUI,
+ TILEGX_OPC_V1CMPNE,
+ TILEGX_OPC_V1DDOTPU,
+ TILEGX_OPC_V1DDOTPUA,
+ TILEGX_OPC_V1DDOTPUS,
+ TILEGX_OPC_V1DDOTPUSA,
+ TILEGX_OPC_V1DOTP,
+ TILEGX_OPC_V1DOTPA,
+ TILEGX_OPC_V1DOTPU,
+ TILEGX_OPC_V1DOTPUA,
+ TILEGX_OPC_V1DOTPUS,
+ TILEGX_OPC_V1DOTPUSA,
+ TILEGX_OPC_V1INT_H,
+ TILEGX_OPC_V1INT_L,
+ TILEGX_OPC_V1MAXU,
+ TILEGX_OPC_V1MAXUI,
+ TILEGX_OPC_V1MINU,
+ TILEGX_OPC_V1MINUI,
+ TILEGX_OPC_V1MNZ,
+ TILEGX_OPC_V1MULTU,
+ TILEGX_OPC_V1MULU,
+ TILEGX_OPC_V1MULUS,
+ TILEGX_OPC_V1MZ,
+ TILEGX_OPC_V1SADAU,
+ TILEGX_OPC_V1SADU,
+ TILEGX_OPC_V1SHL,
+ TILEGX_OPC_V1SHLI,
+ TILEGX_OPC_V1SHRS,
+ TILEGX_OPC_V1SHRSI,
+ TILEGX_OPC_V1SHRU,
+ TILEGX_OPC_V1SHRUI,
+ TILEGX_OPC_V1SUB,
+ TILEGX_OPC_V1SUBUC,
+ TILEGX_OPC_V2ADD,
+ TILEGX_OPC_V2ADDI,
+ TILEGX_OPC_V2ADDSC,
+ TILEGX_OPC_V2ADIFFS,
+ TILEGX_OPC_V2AVGS,
+ TILEGX_OPC_V2CMPEQ,
+ TILEGX_OPC_V2CMPEQI,
+ TILEGX_OPC_V2CMPLES,
+ TILEGX_OPC_V2CMPLEU,
+ TILEGX_OPC_V2CMPLTS,
+ TILEGX_OPC_V2CMPLTSI,
+ TILEGX_OPC_V2CMPLTU,
+ TILEGX_OPC_V2CMPLTUI,
+ TILEGX_OPC_V2CMPNE,
+ TILEGX_OPC_V2DOTP,
+ TILEGX_OPC_V2DOTPA,
+ TILEGX_OPC_V2INT_H,
+ TILEGX_OPC_V2INT_L,
+ TILEGX_OPC_V2MAXS,
+ TILEGX_OPC_V2MAXSI,
+ TILEGX_OPC_V2MINS,
+ TILEGX_OPC_V2MINSI,
+ TILEGX_OPC_V2MNZ,
+ TILEGX_OPC_V2MULFSC,
+ TILEGX_OPC_V2MULS,
+ TILEGX_OPC_V2MULTS,
+ TILEGX_OPC_V2MZ,
+ TILEGX_OPC_V2PACKH,
+ TILEGX_OPC_V2PACKL,
+ TILEGX_OPC_V2PACKUC,
+ TILEGX_OPC_V2SADAS,
+ TILEGX_OPC_V2SADAU,
+ TILEGX_OPC_V2SADS,
+ TILEGX_OPC_V2SADU,
+ TILEGX_OPC_V2SHL,
+ TILEGX_OPC_V2SHLI,
+ TILEGX_OPC_V2SHLSC,
+ TILEGX_OPC_V2SHRS,
+ TILEGX_OPC_V2SHRSI,
+ TILEGX_OPC_V2SHRU,
+ TILEGX_OPC_V2SHRUI,
+ TILEGX_OPC_V2SUB,
+ TILEGX_OPC_V2SUBSC,
+ TILEGX_OPC_V4ADD,
+ TILEGX_OPC_V4ADDSC,
+ TILEGX_OPC_V4INT_H,
+ TILEGX_OPC_V4INT_L,
+ TILEGX_OPC_V4PACKSC,
+ TILEGX_OPC_V4SHL,
+ TILEGX_OPC_V4SHLSC,
+ TILEGX_OPC_V4SHRS,
+ TILEGX_OPC_V4SHRU,
+ TILEGX_OPC_V4SUB,
+ TILEGX_OPC_V4SUBSC,
+ TILEGX_OPC_WH64,
+ TILEGX_OPC_XOR,
+ TILEGX_OPC_XORI,
+ TILEGX_OPC_NONE
+} tilegx_mnemonic;
+
+enum
+{
+ TILEGX_MAX_OPERANDS = 4 /* bfexts */
+};
+
+struct tilegx_opcode
+{
+ /* The opcode mnemonic, e.g. "add" */
+ const char *name;
+
+ /* The enum value for this mnemonic. */
+ tilegx_mnemonic mnemonic;
+
+ /* A bit mask of which of the five pipes this instruction
+ is compatible with:
+ X0 0x01
+ X1 0x02
+ Y0 0x04
+ Y1 0x08
+ Y2 0x10 */
+ unsigned char pipes;
+
+ /* How many operands are there? */
+ unsigned char num_operands;
+
+ /* Which register does this write implicitly, or TREG_ZERO if none? */
+ unsigned char implicitly_written_register;
+
+ /* Can this be bundled with other instructions (almost always true). */
+ unsigned char can_bundle;
+
+ /* The description of the operands. Each of these is an
+ * index into the tilegx_operands[] table. */
+ unsigned char operands[TILEGX_NUM_PIPELINE_ENCODINGS][TILEGX_MAX_OPERANDS];
+
+ /* A mask of which bits have predefined values for each pipeline.
+ * This is useful for disassembly. */
+ tilegx_bundle_bits fixed_bit_masks[TILEGX_NUM_PIPELINE_ENCODINGS];
+
+ /* For each bit set in fixed_bit_masks, what the value is for this
+ * instruction. */
+ tilegx_bundle_bits fixed_bit_values[TILEGX_NUM_PIPELINE_ENCODINGS];
+};
+
+/* Used for non-textual disassembly into structs. */
+struct tilegx_decoded_instruction
+{
+ const struct tilegx_opcode *opcode;
+ const struct tilegx_operand *operands[TILEGX_MAX_OPERANDS];
+ long long operand_values[TILEGX_MAX_OPERANDS];
+};
+
+enum
+{
+ ADDI_IMM8_OPCODE_X0 = 1,
+ ADDI_IMM8_OPCODE_X1 = 1,
+ ADDI_OPCODE_Y0 = 0,
+ ADDI_OPCODE_Y1 = 1,
+ ADDLI_OPCODE_X0 = 1,
+ ADDLI_OPCODE_X1 = 0,
+ ADDXI_IMM8_OPCODE_X0 = 2,
+ ADDXI_IMM8_OPCODE_X1 = 2,
+ ADDXI_OPCODE_Y0 = 1,
+ ADDXI_OPCODE_Y1 = 2,
+ ADDXLI_OPCODE_X0 = 2,
+ ADDXLI_OPCODE_X1 = 1,
+ ADDXSC_RRR_0_OPCODE_X0 = 1,
+ ADDXSC_RRR_0_OPCODE_X1 = 1,
+ ADDX_RRR_0_OPCODE_X0 = 2,
+ ADDX_RRR_0_OPCODE_X1 = 2,
+ ADDX_RRR_0_OPCODE_Y0 = 0,
+ ADDX_SPECIAL_0_OPCODE_Y1 = 0,
+ ADD_RRR_0_OPCODE_X0 = 3,
+ ADD_RRR_0_OPCODE_X1 = 3,
+ ADD_RRR_0_OPCODE_Y0 = 1,
+ ADD_SPECIAL_0_OPCODE_Y1 = 1,
+ ANDI_IMM8_OPCODE_X0 = 3,
+ ANDI_IMM8_OPCODE_X1 = 3,
+ ANDI_OPCODE_Y0 = 2,
+ ANDI_OPCODE_Y1 = 3,
+ AND_RRR_0_OPCODE_X0 = 4,
+ AND_RRR_0_OPCODE_X1 = 4,
+ AND_RRR_5_OPCODE_Y0 = 0,
+ AND_RRR_5_OPCODE_Y1 = 0,
+ BEQZT_BRANCH_OPCODE_X1 = 16,
+ BEQZ_BRANCH_OPCODE_X1 = 17,
+ BFEXTS_BF_OPCODE_X0 = 4,
+ BFEXTU_BF_OPCODE_X0 = 5,
+ BFINS_BF_OPCODE_X0 = 6,
+ BF_OPCODE_X0 = 3,
+ BGEZT_BRANCH_OPCODE_X1 = 18,
+ BGEZ_BRANCH_OPCODE_X1 = 19,
+ BGTZT_BRANCH_OPCODE_X1 = 20,
+ BGTZ_BRANCH_OPCODE_X1 = 21,
+ BLBCT_BRANCH_OPCODE_X1 = 22,
+ BLBC_BRANCH_OPCODE_X1 = 23,
+ BLBST_BRANCH_OPCODE_X1 = 24,
+ BLBS_BRANCH_OPCODE_X1 = 25,
+ BLEZT_BRANCH_OPCODE_X1 = 26,
+ BLEZ_BRANCH_OPCODE_X1 = 27,
+ BLTZT_BRANCH_OPCODE_X1 = 28,
+ BLTZ_BRANCH_OPCODE_X1 = 29,
+ BNEZT_BRANCH_OPCODE_X1 = 30,
+ BNEZ_BRANCH_OPCODE_X1 = 31,
+ BRANCH_OPCODE_X1 = 2,
+ CMOVEQZ_RRR_0_OPCODE_X0 = 5,
+ CMOVEQZ_RRR_4_OPCODE_Y0 = 0,
+ CMOVNEZ_RRR_0_OPCODE_X0 = 6,
+ CMOVNEZ_RRR_4_OPCODE_Y0 = 1,
+ CMPEQI_IMM8_OPCODE_X0 = 4,
+ CMPEQI_IMM8_OPCODE_X1 = 4,
+ CMPEQI_OPCODE_Y0 = 3,
+ CMPEQI_OPCODE_Y1 = 4,
+ CMPEQ_RRR_0_OPCODE_X0 = 7,
+ CMPEQ_RRR_0_OPCODE_X1 = 5,
+ CMPEQ_RRR_3_OPCODE_Y0 = 0,
+ CMPEQ_RRR_3_OPCODE_Y1 = 2,
+ CMPEXCH4_RRR_0_OPCODE_X1 = 6,
+ CMPEXCH_RRR_0_OPCODE_X1 = 7,
+ CMPLES_RRR_0_OPCODE_X0 = 8,
+ CMPLES_RRR_0_OPCODE_X1 = 8,
+ CMPLES_RRR_2_OPCODE_Y0 = 0,
+ CMPLES_RRR_2_OPCODE_Y1 = 0,
+ CMPLEU_RRR_0_OPCODE_X0 = 9,
+ CMPLEU_RRR_0_OPCODE_X1 = 9,
+ CMPLEU_RRR_2_OPCODE_Y0 = 1,
+ CMPLEU_RRR_2_OPCODE_Y1 = 1,
+ CMPLTSI_IMM8_OPCODE_X0 = 5,
+ CMPLTSI_IMM8_OPCODE_X1 = 5,
+ CMPLTSI_OPCODE_Y0 = 4,
+ CMPLTSI_OPCODE_Y1 = 5,
+ CMPLTS_RRR_0_OPCODE_X0 = 10,
+ CMPLTS_RRR_0_OPCODE_X1 = 10,
+ CMPLTS_RRR_2_OPCODE_Y0 = 2,
+ CMPLTS_RRR_2_OPCODE_Y1 = 2,
+ CMPLTUI_IMM8_OPCODE_X0 = 6,
+ CMPLTUI_IMM8_OPCODE_X1 = 6,
+ CMPLTU_RRR_0_OPCODE_X0 = 11,
+ CMPLTU_RRR_0_OPCODE_X1 = 11,
+ CMPLTU_RRR_2_OPCODE_Y0 = 3,
+ CMPLTU_RRR_2_OPCODE_Y1 = 3,
+ CMPNE_RRR_0_OPCODE_X0 = 12,
+ CMPNE_RRR_0_OPCODE_X1 = 12,
+ CMPNE_RRR_3_OPCODE_Y0 = 1,
+ CMPNE_RRR_3_OPCODE_Y1 = 3,
+ CMULAF_RRR_0_OPCODE_X0 = 13,
+ CMULA_RRR_0_OPCODE_X0 = 14,
+ CMULFR_RRR_0_OPCODE_X0 = 15,
+ CMULF_RRR_0_OPCODE_X0 = 16,
+ CMULHR_RRR_0_OPCODE_X0 = 17,
+ CMULH_RRR_0_OPCODE_X0 = 18,
+ CMUL_RRR_0_OPCODE_X0 = 19,
+ CNTLZ_UNARY_OPCODE_X0 = 1,
+ CNTLZ_UNARY_OPCODE_Y0 = 1,
+ CNTTZ_UNARY_OPCODE_X0 = 2,
+ CNTTZ_UNARY_OPCODE_Y0 = 2,
+ CRC32_32_RRR_0_OPCODE_X0 = 20,
+ CRC32_8_RRR_0_OPCODE_X0 = 21,
+ DBLALIGN2_RRR_0_OPCODE_X0 = 22,
+ DBLALIGN2_RRR_0_OPCODE_X1 = 13,
+ DBLALIGN4_RRR_0_OPCODE_X0 = 23,
+ DBLALIGN4_RRR_0_OPCODE_X1 = 14,
+ DBLALIGN6_RRR_0_OPCODE_X0 = 24,
+ DBLALIGN6_RRR_0_OPCODE_X1 = 15,
+ DBLALIGN_RRR_0_OPCODE_X0 = 25,
+ DRAIN_UNARY_OPCODE_X1 = 1,
+ DTLBPR_UNARY_OPCODE_X1 = 2,
+ EXCH4_RRR_0_OPCODE_X1 = 16,
+ EXCH_RRR_0_OPCODE_X1 = 17,
+ FDOUBLE_ADDSUB_RRR_0_OPCODE_X0 = 26,
+ FDOUBLE_ADD_FLAGS_RRR_0_OPCODE_X0 = 27,
+ FDOUBLE_MUL_FLAGS_RRR_0_OPCODE_X0 = 28,
+ FDOUBLE_PACK1_RRR_0_OPCODE_X0 = 29,
+ FDOUBLE_PACK2_RRR_0_OPCODE_X0 = 30,
+ FDOUBLE_SUB_FLAGS_RRR_0_OPCODE_X0 = 31,
+ FDOUBLE_UNPACK_MAX_RRR_0_OPCODE_X0 = 32,
+ FDOUBLE_UNPACK_MIN_RRR_0_OPCODE_X0 = 33,
+ FETCHADD4_RRR_0_OPCODE_X1 = 18,
+ FETCHADDGEZ4_RRR_0_OPCODE_X1 = 19,
+ FETCHADDGEZ_RRR_0_OPCODE_X1 = 20,
+ FETCHADD_RRR_0_OPCODE_X1 = 21,
+ FETCHAND4_RRR_0_OPCODE_X1 = 22,
+ FETCHAND_RRR_0_OPCODE_X1 = 23,
+ FETCHOR4_RRR_0_OPCODE_X1 = 24,
+ FETCHOR_RRR_0_OPCODE_X1 = 25,
+ FINV_UNARY_OPCODE_X1 = 3,
+ FLUSHWB_UNARY_OPCODE_X1 = 4,
+ FLUSH_UNARY_OPCODE_X1 = 5,
+ FNOP_UNARY_OPCODE_X0 = 3,
+ FNOP_UNARY_OPCODE_X1 = 6,
+ FNOP_UNARY_OPCODE_Y0 = 3,
+ FNOP_UNARY_OPCODE_Y1 = 8,
+ FSINGLE_ADD1_RRR_0_OPCODE_X0 = 34,
+ FSINGLE_ADDSUB2_RRR_0_OPCODE_X0 = 35,
+ FSINGLE_MUL1_RRR_0_OPCODE_X0 = 36,
+ FSINGLE_MUL2_RRR_0_OPCODE_X0 = 37,
+ FSINGLE_PACK1_UNARY_OPCODE_X0 = 4,
+ FSINGLE_PACK1_UNARY_OPCODE_Y0 = 4,
+ FSINGLE_PACK2_RRR_0_OPCODE_X0 = 38,
+ FSINGLE_SUB1_RRR_0_OPCODE_X0 = 39,
+ ICOH_UNARY_OPCODE_X1 = 7,
+ ILL_UNARY_OPCODE_X1 = 8,
+ ILL_UNARY_OPCODE_Y1 = 9,
+ IMM8_OPCODE_X0 = 4,
+ IMM8_OPCODE_X1 = 3,
+ INV_UNARY_OPCODE_X1 = 9,
+ IRET_UNARY_OPCODE_X1 = 10,
+ JALRP_UNARY_OPCODE_X1 = 11,
+ JALRP_UNARY_OPCODE_Y1 = 10,
+ JALR_UNARY_OPCODE_X1 = 12,
+ JALR_UNARY_OPCODE_Y1 = 11,
+ JAL_JUMP_OPCODE_X1 = 0,
+ JRP_UNARY_OPCODE_X1 = 13,
+ JRP_UNARY_OPCODE_Y1 = 12,
+ JR_UNARY_OPCODE_X1 = 14,
+ JR_UNARY_OPCODE_Y1 = 13,
+ JUMP_OPCODE_X1 = 4,
+ J_JUMP_OPCODE_X1 = 1,
+ LD1S_ADD_IMM8_OPCODE_X1 = 7,
+ LD1S_OPCODE_Y2 = 0,
+ LD1S_UNARY_OPCODE_X1 = 15,
+ LD1U_ADD_IMM8_OPCODE_X1 = 8,
+ LD1U_OPCODE_Y2 = 1,
+ LD1U_UNARY_OPCODE_X1 = 16,
+ LD2S_ADD_IMM8_OPCODE_X1 = 9,
+ LD2S_OPCODE_Y2 = 2,
+ LD2S_UNARY_OPCODE_X1 = 17,
+ LD2U_ADD_IMM8_OPCODE_X1 = 10,
+ LD2U_OPCODE_Y2 = 3,
+ LD2U_UNARY_OPCODE_X1 = 18,
+ LD4S_ADD_IMM8_OPCODE_X1 = 11,
+ LD4S_OPCODE_Y2 = 1,
+ LD4S_UNARY_OPCODE_X1 = 19,
+ LD4U_ADD_IMM8_OPCODE_X1 = 12,
+ LD4U_OPCODE_Y2 = 2,
+ LD4U_UNARY_OPCODE_X1 = 20,
+ LDNA_UNARY_OPCODE_X1 = 21,
+ LDNT1S_ADD_IMM8_OPCODE_X1 = 13,
+ LDNT1S_UNARY_OPCODE_X1 = 22,
+ LDNT1U_ADD_IMM8_OPCODE_X1 = 14,
+ LDNT1U_UNARY_OPCODE_X1 = 23,
+ LDNT2S_ADD_IMM8_OPCODE_X1 = 15,
+ LDNT2S_UNARY_OPCODE_X1 = 24,
+ LDNT2U_ADD_IMM8_OPCODE_X1 = 16,
+ LDNT2U_UNARY_OPCODE_X1 = 25,
+ LDNT4S_ADD_IMM8_OPCODE_X1 = 17,
+ LDNT4S_UNARY_OPCODE_X1 = 26,
+ LDNT4U_ADD_IMM8_OPCODE_X1 = 18,
+ LDNT4U_UNARY_OPCODE_X1 = 27,
+ LDNT_ADD_IMM8_OPCODE_X1 = 19,
+ LDNT_UNARY_OPCODE_X1 = 28,
+ LD_ADD_IMM8_OPCODE_X1 = 20,
+ LD_OPCODE_Y2 = 3,
+ LD_UNARY_OPCODE_X1 = 29,
+ LNK_UNARY_OPCODE_X1 = 30,
+ LNK_UNARY_OPCODE_Y1 = 14,
+ LWNA_ADD_IMM8_OPCODE_X1 = 21,
+ MFSPR_IMM8_OPCODE_X1 = 22,
+ MF_UNARY_OPCODE_X1 = 31,
+ MM_BF_OPCODE_X0 = 7,
+ MNZ_RRR_0_OPCODE_X0 = 40,
+ MNZ_RRR_0_OPCODE_X1 = 26,
+ MNZ_RRR_4_OPCODE_Y0 = 2,
+ MNZ_RRR_4_OPCODE_Y1 = 2,
+ MODE_OPCODE_YA2 = 1,
+ MODE_OPCODE_YB2 = 2,
+ MODE_OPCODE_YC2 = 3,
+ MTSPR_IMM8_OPCODE_X1 = 23,
+ MULAX_RRR_0_OPCODE_X0 = 41,
+ MULAX_RRR_3_OPCODE_Y0 = 2,
+ MULA_HS_HS_RRR_0_OPCODE_X0 = 42,
+ MULA_HS_HS_RRR_9_OPCODE_Y0 = 0,
+ MULA_HS_HU_RRR_0_OPCODE_X0 = 43,
+ MULA_HS_LS_RRR_0_OPCODE_X0 = 44,
+ MULA_HS_LU_RRR_0_OPCODE_X0 = 45,
+ MULA_HU_HU_RRR_0_OPCODE_X0 = 46,
+ MULA_HU_HU_RRR_9_OPCODE_Y0 = 1,
+ MULA_HU_LS_RRR_0_OPCODE_X0 = 47,
+ MULA_HU_LU_RRR_0_OPCODE_X0 = 48,
+ MULA_LS_LS_RRR_0_OPCODE_X0 = 49,
+ MULA_LS_LS_RRR_9_OPCODE_Y0 = 2,
+ MULA_LS_LU_RRR_0_OPCODE_X0 = 50,
+ MULA_LU_LU_RRR_0_OPCODE_X0 = 51,
+ MULA_LU_LU_RRR_9_OPCODE_Y0 = 3,
+ MULX_RRR_0_OPCODE_X0 = 52,
+ MULX_RRR_3_OPCODE_Y0 = 3,
+ MUL_HS_HS_RRR_0_OPCODE_X0 = 53,
+ MUL_HS_HS_RRR_8_OPCODE_Y0 = 0,
+ MUL_HS_HU_RRR_0_OPCODE_X0 = 54,
+ MUL_HS_LS_RRR_0_OPCODE_X0 = 55,
+ MUL_HS_LU_RRR_0_OPCODE_X0 = 56,
+ MUL_HU_HU_RRR_0_OPCODE_X0 = 57,
+ MUL_HU_HU_RRR_8_OPCODE_Y0 = 1,
+ MUL_HU_LS_RRR_0_OPCODE_X0 = 58,
+ MUL_HU_LU_RRR_0_OPCODE_X0 = 59,
+ MUL_LS_LS_RRR_0_OPCODE_X0 = 60,
+ MUL_LS_LS_RRR_8_OPCODE_Y0 = 2,
+ MUL_LS_LU_RRR_0_OPCODE_X0 = 61,
+ MUL_LU_LU_RRR_0_OPCODE_X0 = 62,
+ MUL_LU_LU_RRR_8_OPCODE_Y0 = 3,
+ MZ_RRR_0_OPCODE_X0 = 63,
+ MZ_RRR_0_OPCODE_X1 = 27,
+ MZ_RRR_4_OPCODE_Y0 = 3,
+ MZ_RRR_4_OPCODE_Y1 = 3,
+ NAP_UNARY_OPCODE_X1 = 32,
+ NOP_UNARY_OPCODE_X0 = 5,
+ NOP_UNARY_OPCODE_X1 = 33,
+ NOP_UNARY_OPCODE_Y0 = 5,
+ NOP_UNARY_OPCODE_Y1 = 15,
+ NOR_RRR_0_OPCODE_X0 = 64,
+ NOR_RRR_0_OPCODE_X1 = 28,
+ NOR_RRR_5_OPCODE_Y0 = 1,
+ NOR_RRR_5_OPCODE_Y1 = 1,
+ ORI_IMM8_OPCODE_X0 = 7,
+ ORI_IMM8_OPCODE_X1 = 24,
+ OR_RRR_0_OPCODE_X0 = 65,
+ OR_RRR_0_OPCODE_X1 = 29,
+ OR_RRR_5_OPCODE_Y0 = 2,
+ OR_RRR_5_OPCODE_Y1 = 2,
+ PCNT_UNARY_OPCODE_X0 = 6,
+ PCNT_UNARY_OPCODE_Y0 = 6,
+ REVBITS_UNARY_OPCODE_X0 = 7,
+ REVBITS_UNARY_OPCODE_Y0 = 7,
+ REVBYTES_UNARY_OPCODE_X0 = 8,
+ REVBYTES_UNARY_OPCODE_Y0 = 8,
+ ROTLI_SHIFT_OPCODE_X0 = 1,
+ ROTLI_SHIFT_OPCODE_X1 = 1,
+ ROTLI_SHIFT_OPCODE_Y0 = 0,
+ ROTLI_SHIFT_OPCODE_Y1 = 0,
+ ROTL_RRR_0_OPCODE_X0 = 66,
+ ROTL_RRR_0_OPCODE_X1 = 30,
+ ROTL_RRR_6_OPCODE_Y0 = 0,
+ ROTL_RRR_6_OPCODE_Y1 = 0,
+ RRR_0_OPCODE_X0 = 5,
+ RRR_0_OPCODE_X1 = 5,
+ RRR_0_OPCODE_Y0 = 5,
+ RRR_0_OPCODE_Y1 = 6,
+ RRR_1_OPCODE_Y0 = 6,
+ RRR_1_OPCODE_Y1 = 7,
+ RRR_2_OPCODE_Y0 = 7,
+ RRR_2_OPCODE_Y1 = 8,
+ RRR_3_OPCODE_Y0 = 8,
+ RRR_3_OPCODE_Y1 = 9,
+ RRR_4_OPCODE_Y0 = 9,
+ RRR_4_OPCODE_Y1 = 10,
+ RRR_5_OPCODE_Y0 = 10,
+ RRR_5_OPCODE_Y1 = 11,
+ RRR_6_OPCODE_Y0 = 11,
+ RRR_6_OPCODE_Y1 = 12,
+ RRR_7_OPCODE_Y0 = 12,
+ RRR_7_OPCODE_Y1 = 13,
+ RRR_8_OPCODE_Y0 = 13,
+ RRR_9_OPCODE_Y0 = 14,
+ SHIFT_OPCODE_X0 = 6,
+ SHIFT_OPCODE_X1 = 6,
+ SHIFT_OPCODE_Y0 = 15,
+ SHIFT_OPCODE_Y1 = 14,
+ SHL16INSLI_OPCODE_X0 = 7,
+ SHL16INSLI_OPCODE_X1 = 7,
+ SHL1ADDX_RRR_0_OPCODE_X0 = 67,
+ SHL1ADDX_RRR_0_OPCODE_X1 = 31,
+ SHL1ADDX_RRR_7_OPCODE_Y0 = 1,
+ SHL1ADDX_RRR_7_OPCODE_Y1 = 1,
+ SHL1ADD_RRR_0_OPCODE_X0 = 68,
+ SHL1ADD_RRR_0_OPCODE_X1 = 32,
+ SHL1ADD_RRR_1_OPCODE_Y0 = 0,
+ SHL1ADD_RRR_1_OPCODE_Y1 = 0,
+ SHL2ADDX_RRR_0_OPCODE_X0 = 69,
+ SHL2ADDX_RRR_0_OPCODE_X1 = 33,
+ SHL2ADDX_RRR_7_OPCODE_Y0 = 2,
+ SHL2ADDX_RRR_7_OPCODE_Y1 = 2,
+ SHL2ADD_RRR_0_OPCODE_X0 = 70,
+ SHL2ADD_RRR_0_OPCODE_X1 = 34,
+ SHL2ADD_RRR_1_OPCODE_Y0 = 1,
+ SHL2ADD_RRR_1_OPCODE_Y1 = 1,
+ SHL3ADDX_RRR_0_OPCODE_X0 = 71,
+ SHL3ADDX_RRR_0_OPCODE_X1 = 35,
+ SHL3ADDX_RRR_7_OPCODE_Y0 = 3,
+ SHL3ADDX_RRR_7_OPCODE_Y1 = 3,
+ SHL3ADD_RRR_0_OPCODE_X0 = 72,
+ SHL3ADD_RRR_0_OPCODE_X1 = 36,
+ SHL3ADD_RRR_1_OPCODE_Y0 = 2,
+ SHL3ADD_RRR_1_OPCODE_Y1 = 2,
+ SHLI_SHIFT_OPCODE_X0 = 2,
+ SHLI_SHIFT_OPCODE_X1 = 2,
+ SHLI_SHIFT_OPCODE_Y0 = 1,
+ SHLI_SHIFT_OPCODE_Y1 = 1,
+ SHLXI_SHIFT_OPCODE_X0 = 3,
+ SHLXI_SHIFT_OPCODE_X1 = 3,
+ SHLX_RRR_0_OPCODE_X0 = 73,
+ SHLX_RRR_0_OPCODE_X1 = 37,
+ SHL_RRR_0_OPCODE_X0 = 74,
+ SHL_RRR_0_OPCODE_X1 = 38,
+ SHL_RRR_6_OPCODE_Y0 = 1,
+ SHL_RRR_6_OPCODE_Y1 = 1,
+ SHRSI_SHIFT_OPCODE_X0 = 4,
+ SHRSI_SHIFT_OPCODE_X1 = 4,
+ SHRSI_SHIFT_OPCODE_Y0 = 2,
+ SHRSI_SHIFT_OPCODE_Y1 = 2,
+ SHRS_RRR_0_OPCODE_X0 = 75,
+ SHRS_RRR_0_OPCODE_X1 = 39,
+ SHRS_RRR_6_OPCODE_Y0 = 2,
+ SHRS_RRR_6_OPCODE_Y1 = 2,
+ SHRUI_SHIFT_OPCODE_X0 = 5,
+ SHRUI_SHIFT_OPCODE_X1 = 5,
+ SHRUI_SHIFT_OPCODE_Y0 = 3,
+ SHRUI_SHIFT_OPCODE_Y1 = 3,
+ SHRUXI_SHIFT_OPCODE_X0 = 6,
+ SHRUXI_SHIFT_OPCODE_X1 = 6,
+ SHRUX_RRR_0_OPCODE_X0 = 76,
+ SHRUX_RRR_0_OPCODE_X1 = 40,
+ SHRU_RRR_0_OPCODE_X0 = 77,
+ SHRU_RRR_0_OPCODE_X1 = 41,
+ SHRU_RRR_6_OPCODE_Y0 = 3,
+ SHRU_RRR_6_OPCODE_Y1 = 3,
+ SHUFFLEBYTES_RRR_0_OPCODE_X0 = 78,
+ ST1_ADD_IMM8_OPCODE_X1 = 25,
+ ST1_OPCODE_Y2 = 0,
+ ST1_RRR_0_OPCODE_X1 = 42,
+ ST2_ADD_IMM8_OPCODE_X1 = 26,
+ ST2_OPCODE_Y2 = 1,
+ ST2_RRR_0_OPCODE_X1 = 43,
+ ST4_ADD_IMM8_OPCODE_X1 = 27,
+ ST4_OPCODE_Y2 = 2,
+ ST4_RRR_0_OPCODE_X1 = 44,
+ STNT1_ADD_IMM8_OPCODE_X1 = 28,
+ STNT1_RRR_0_OPCODE_X1 = 45,
+ STNT2_ADD_IMM8_OPCODE_X1 = 29,
+ STNT2_RRR_0_OPCODE_X1 = 46,
+ STNT4_ADD_IMM8_OPCODE_X1 = 30,
+ STNT4_RRR_0_OPCODE_X1 = 47,
+ STNT_ADD_IMM8_OPCODE_X1 = 31,
+ STNT_RRR_0_OPCODE_X1 = 48,
+ ST_ADD_IMM8_OPCODE_X1 = 32,
+ ST_OPCODE_Y2 = 3,
+ ST_RRR_0_OPCODE_X1 = 49,
+ SUBXSC_RRR_0_OPCODE_X0 = 79,
+ SUBXSC_RRR_0_OPCODE_X1 = 50,
+ SUBX_RRR_0_OPCODE_X0 = 80,
+ SUBX_RRR_0_OPCODE_X1 = 51,
+ SUBX_RRR_0_OPCODE_Y0 = 2,
+ SUBX_RRR_0_OPCODE_Y1 = 2,
+ SUB_RRR_0_OPCODE_X0 = 81,
+ SUB_RRR_0_OPCODE_X1 = 52,
+ SUB_RRR_0_OPCODE_Y0 = 3,
+ SUB_RRR_0_OPCODE_Y1 = 3,
+ SWINT0_UNARY_OPCODE_X1 = 34,
+ SWINT1_UNARY_OPCODE_X1 = 35,
+ SWINT2_UNARY_OPCODE_X1 = 36,
+ SWINT3_UNARY_OPCODE_X1 = 37,
+ TBLIDXB0_UNARY_OPCODE_X0 = 9,
+ TBLIDXB0_UNARY_OPCODE_Y0 = 9,
+ TBLIDXB1_UNARY_OPCODE_X0 = 10,
+ TBLIDXB1_UNARY_OPCODE_Y0 = 10,
+ TBLIDXB2_UNARY_OPCODE_X0 = 11,
+ TBLIDXB2_UNARY_OPCODE_Y0 = 11,
+ TBLIDXB3_UNARY_OPCODE_X0 = 12,
+ TBLIDXB3_UNARY_OPCODE_Y0 = 12,
+ UNARY_RRR_0_OPCODE_X0 = 82,
+ UNARY_RRR_0_OPCODE_X1 = 53,
+ UNARY_RRR_1_OPCODE_Y0 = 3,
+ UNARY_RRR_1_OPCODE_Y1 = 3,
+ V1ADDI_IMM8_OPCODE_X0 = 8,
+ V1ADDI_IMM8_OPCODE_X1 = 33,
+ V1ADDUC_RRR_0_OPCODE_X0 = 83,
+ V1ADDUC_RRR_0_OPCODE_X1 = 54,
+ V1ADD_RRR_0_OPCODE_X0 = 84,
+ V1ADD_RRR_0_OPCODE_X1 = 55,
+ V1ADIFFU_RRR_0_OPCODE_X0 = 85,
+ V1AVGU_RRR_0_OPCODE_X0 = 86,
+ V1CMPEQI_IMM8_OPCODE_X0 = 9,
+ V1CMPEQI_IMM8_OPCODE_X1 = 34,
+ V1CMPEQ_RRR_0_OPCODE_X0 = 87,
+ V1CMPEQ_RRR_0_OPCODE_X1 = 56,
+ V1CMPLES_RRR_0_OPCODE_X0 = 88,
+ V1CMPLES_RRR_0_OPCODE_X1 = 57,
+ V1CMPLEU_RRR_0_OPCODE_X0 = 89,
+ V1CMPLEU_RRR_0_OPCODE_X1 = 58,
+ V1CMPLTSI_IMM8_OPCODE_X0 = 10,
+ V1CMPLTSI_IMM8_OPCODE_X1 = 35,
+ V1CMPLTS_RRR_0_OPCODE_X0 = 90,
+ V1CMPLTS_RRR_0_OPCODE_X1 = 59,
+ V1CMPLTUI_IMM8_OPCODE_X0 = 11,
+ V1CMPLTUI_IMM8_OPCODE_X1 = 36,
+ V1CMPLTU_RRR_0_OPCODE_X0 = 91,
+ V1CMPLTU_RRR_0_OPCODE_X1 = 60,
+ V1CMPNE_RRR_0_OPCODE_X0 = 92,
+ V1CMPNE_RRR_0_OPCODE_X1 = 61,
+ V1DDOTPUA_RRR_0_OPCODE_X0 = 161,
+ V1DDOTPUSA_RRR_0_OPCODE_X0 = 93,
+ V1DDOTPUS_RRR_0_OPCODE_X0 = 94,
+ V1DDOTPU_RRR_0_OPCODE_X0 = 162,
+ V1DOTPA_RRR_0_OPCODE_X0 = 95,
+ V1DOTPUA_RRR_0_OPCODE_X0 = 163,
+ V1DOTPUSA_RRR_0_OPCODE_X0 = 96,
+ V1DOTPUS_RRR_0_OPCODE_X0 = 97,
+ V1DOTPU_RRR_0_OPCODE_X0 = 164,
+ V1DOTP_RRR_0_OPCODE_X0 = 98,
+ V1INT_H_RRR_0_OPCODE_X0 = 99,
+ V1INT_H_RRR_0_OPCODE_X1 = 62,
+ V1INT_L_RRR_0_OPCODE_X0 = 100,
+ V1INT_L_RRR_0_OPCODE_X1 = 63,
+ V1MAXUI_IMM8_OPCODE_X0 = 12,
+ V1MAXUI_IMM8_OPCODE_X1 = 37,
+ V1MAXU_RRR_0_OPCODE_X0 = 101,
+ V1MAXU_RRR_0_OPCODE_X1 = 64,
+ V1MINUI_IMM8_OPCODE_X0 = 13,
+ V1MINUI_IMM8_OPCODE_X1 = 38,
+ V1MINU_RRR_0_OPCODE_X0 = 102,
+ V1MINU_RRR_0_OPCODE_X1 = 65,
+ V1MNZ_RRR_0_OPCODE_X0 = 103,
+ V1MNZ_RRR_0_OPCODE_X1 = 66,
+ V1MULTU_RRR_0_OPCODE_X0 = 104,
+ V1MULUS_RRR_0_OPCODE_X0 = 105,
+ V1MULU_RRR_0_OPCODE_X0 = 106,
+ V1MZ_RRR_0_OPCODE_X0 = 107,
+ V1MZ_RRR_0_OPCODE_X1 = 67,
+ V1SADAU_RRR_0_OPCODE_X0 = 108,
+ V1SADU_RRR_0_OPCODE_X0 = 109,
+ V1SHLI_SHIFT_OPCODE_X0 = 7,
+ V1SHLI_SHIFT_OPCODE_X1 = 7,
+ V1SHL_RRR_0_OPCODE_X0 = 110,
+ V1SHL_RRR_0_OPCODE_X1 = 68,
+ V1SHRSI_SHIFT_OPCODE_X0 = 8,
+ V1SHRSI_SHIFT_OPCODE_X1 = 8,
+ V1SHRS_RRR_0_OPCODE_X0 = 111,
+ V1SHRS_RRR_0_OPCODE_X1 = 69,
+ V1SHRUI_SHIFT_OPCODE_X0 = 9,
+ V1SHRUI_SHIFT_OPCODE_X1 = 9,
+ V1SHRU_RRR_0_OPCODE_X0 = 112,
+ V1SHRU_RRR_0_OPCODE_X1 = 70,
+ V1SUBUC_RRR_0_OPCODE_X0 = 113,
+ V1SUBUC_RRR_0_OPCODE_X1 = 71,
+ V1SUB_RRR_0_OPCODE_X0 = 114,
+ V1SUB_RRR_0_OPCODE_X1 = 72,
+ V2ADDI_IMM8_OPCODE_X0 = 14,
+ V2ADDI_IMM8_OPCODE_X1 = 39,
+ V2ADDSC_RRR_0_OPCODE_X0 = 115,
+ V2ADDSC_RRR_0_OPCODE_X1 = 73,
+ V2ADD_RRR_0_OPCODE_X0 = 116,
+ V2ADD_RRR_0_OPCODE_X1 = 74,
+ V2ADIFFS_RRR_0_OPCODE_X0 = 117,
+ V2AVGS_RRR_0_OPCODE_X0 = 118,
+ V2CMPEQI_IMM8_OPCODE_X0 = 15,
+ V2CMPEQI_IMM8_OPCODE_X1 = 40,
+ V2CMPEQ_RRR_0_OPCODE_X0 = 119,
+ V2CMPEQ_RRR_0_OPCODE_X1 = 75,
+ V2CMPLES_RRR_0_OPCODE_X0 = 120,
+ V2CMPLES_RRR_0_OPCODE_X1 = 76,
+ V2CMPLEU_RRR_0_OPCODE_X0 = 121,
+ V2CMPLEU_RRR_0_OPCODE_X1 = 77,
+ V2CMPLTSI_IMM8_OPCODE_X0 = 16,
+ V2CMPLTSI_IMM8_OPCODE_X1 = 41,
+ V2CMPLTS_RRR_0_OPCODE_X0 = 122,
+ V2CMPLTS_RRR_0_OPCODE_X1 = 78,
+ V2CMPLTUI_IMM8_OPCODE_X0 = 17,
+ V2CMPLTUI_IMM8_OPCODE_X1 = 42,
+ V2CMPLTU_RRR_0_OPCODE_X0 = 123,
+ V2CMPLTU_RRR_0_OPCODE_X1 = 79,
+ V2CMPNE_RRR_0_OPCODE_X0 = 124,
+ V2CMPNE_RRR_0_OPCODE_X1 = 80,
+ V2DOTPA_RRR_0_OPCODE_X0 = 125,
+ V2DOTP_RRR_0_OPCODE_X0 = 126,
+ V2INT_H_RRR_0_OPCODE_X0 = 127,
+ V2INT_H_RRR_0_OPCODE_X1 = 81,
+ V2INT_L_RRR_0_OPCODE_X0 = 128,
+ V2INT_L_RRR_0_OPCODE_X1 = 82,
+ V2MAXSI_IMM8_OPCODE_X0 = 18,
+ V2MAXSI_IMM8_OPCODE_X1 = 43,
+ V2MAXS_RRR_0_OPCODE_X0 = 129,
+ V2MAXS_RRR_0_OPCODE_X1 = 83,
+ V2MINSI_IMM8_OPCODE_X0 = 19,
+ V2MINSI_IMM8_OPCODE_X1 = 44,
+ V2MINS_RRR_0_OPCODE_X0 = 130,
+ V2MINS_RRR_0_OPCODE_X1 = 84,
+ V2MNZ_RRR_0_OPCODE_X0 = 131,
+ V2MNZ_RRR_0_OPCODE_X1 = 85,
+ V2MULFSC_RRR_0_OPCODE_X0 = 132,
+ V2MULS_RRR_0_OPCODE_X0 = 133,
+ V2MULTS_RRR_0_OPCODE_X0 = 134,
+ V2MZ_RRR_0_OPCODE_X0 = 135,
+ V2MZ_RRR_0_OPCODE_X1 = 86,
+ V2PACKH_RRR_0_OPCODE_X0 = 136,
+ V2PACKH_RRR_0_OPCODE_X1 = 87,
+ V2PACKL_RRR_0_OPCODE_X0 = 137,
+ V2PACKL_RRR_0_OPCODE_X1 = 88,
+ V2PACKUC_RRR_0_OPCODE_X0 = 138,
+ V2PACKUC_RRR_0_OPCODE_X1 = 89,
+ V2SADAS_RRR_0_OPCODE_X0 = 139,
+ V2SADAU_RRR_0_OPCODE_X0 = 140,
+ V2SADS_RRR_0_OPCODE_X0 = 141,
+ V2SADU_RRR_0_OPCODE_X0 = 142,
+ V2SHLI_SHIFT_OPCODE_X0 = 10,
+ V2SHLI_SHIFT_OPCODE_X1 = 10,
+ V2SHLSC_RRR_0_OPCODE_X0 = 143,
+ V2SHLSC_RRR_0_OPCODE_X1 = 90,
+ V2SHL_RRR_0_OPCODE_X0 = 144,
+ V2SHL_RRR_0_OPCODE_X1 = 91,
+ V2SHRSI_SHIFT_OPCODE_X0 = 11,
+ V2SHRSI_SHIFT_OPCODE_X1 = 11,
+ V2SHRS_RRR_0_OPCODE_X0 = 145,
+ V2SHRS_RRR_0_OPCODE_X1 = 92,
+ V2SHRUI_SHIFT_OPCODE_X0 = 12,
+ V2SHRUI_SHIFT_OPCODE_X1 = 12,
+ V2SHRU_RRR_0_OPCODE_X0 = 146,
+ V2SHRU_RRR_0_OPCODE_X1 = 93,
+ V2SUBSC_RRR_0_OPCODE_X0 = 147,
+ V2SUBSC_RRR_0_OPCODE_X1 = 94,
+ V2SUB_RRR_0_OPCODE_X0 = 148,
+ V2SUB_RRR_0_OPCODE_X1 = 95,
+ V4ADDSC_RRR_0_OPCODE_X0 = 149,
+ V4ADDSC_RRR_0_OPCODE_X1 = 96,
+ V4ADD_RRR_0_OPCODE_X0 = 150,
+ V4ADD_RRR_0_OPCODE_X1 = 97,
+ V4INT_H_RRR_0_OPCODE_X0 = 151,
+ V4INT_H_RRR_0_OPCODE_X1 = 98,
+ V4INT_L_RRR_0_OPCODE_X0 = 152,
+ V4INT_L_RRR_0_OPCODE_X1 = 99,
+ V4PACKSC_RRR_0_OPCODE_X0 = 153,
+ V4PACKSC_RRR_0_OPCODE_X1 = 100,
+ V4SHLSC_RRR_0_OPCODE_X0 = 154,
+ V4SHLSC_RRR_0_OPCODE_X1 = 101,
+ V4SHL_RRR_0_OPCODE_X0 = 155,
+ V4SHL_RRR_0_OPCODE_X1 = 102,
+ V4SHRS_RRR_0_OPCODE_X0 = 156,
+ V4SHRS_RRR_0_OPCODE_X1 = 103,
+ V4SHRU_RRR_0_OPCODE_X0 = 157,
+ V4SHRU_RRR_0_OPCODE_X1 = 104,
+ V4SUBSC_RRR_0_OPCODE_X0 = 158,
+ V4SUBSC_RRR_0_OPCODE_X1 = 105,
+ V4SUB_RRR_0_OPCODE_X0 = 159,
+ V4SUB_RRR_0_OPCODE_X1 = 106,
+ WH64_UNARY_OPCODE_X1 = 38,
+ XORI_IMM8_OPCODE_X0 = 20,
+ XORI_IMM8_OPCODE_X1 = 45,
+ XOR_RRR_0_OPCODE_X0 = 160,
+ XOR_RRR_0_OPCODE_X1 = 107,
+ XOR_RRR_5_OPCODE_Y0 = 3,
+ XOR_RRR_5_OPCODE_Y1 = 3
+};
+
+static __inline unsigned int
+get_BFEnd_X0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_BFOpcodeExtension_X0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 24)) & 0xf);
+}
+
+static __inline unsigned int
+get_BFStart_X0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 18)) & 0x3f);
+}
+
+static __inline unsigned int
+get_BrOff_X1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 31)) & 0x0000003f) |
+ (((unsigned int)(n >> 37)) & 0x0001ffc0);
+}
+
+static __inline unsigned int
+get_BrType_X1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 54)) & 0x1f);
+}
+
+static __inline unsigned int
+get_Dest_Imm8_X1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 31)) & 0x0000003f) |
+ (((unsigned int)(n >> 43)) & 0x000000c0);
+}
+
+static __inline unsigned int
+get_Dest_X0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 0)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_X1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 31)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_Y0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 0)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_Y1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 31)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Imm16_X0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 12)) & 0xffff);
+}
+
+static __inline unsigned int
+get_Imm16_X1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 43)) & 0xffff);
+}
+
+static __inline unsigned int
+get_Imm8OpcodeExtension_X0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 20)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8OpcodeExtension_X1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 51)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_X0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 12)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_X1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 43)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_Y0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 12)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_Y1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 43)) & 0xff);
+}
+
+static __inline unsigned int
+get_JumpOff_X1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 31)) & 0x7ffffff);
+}
+
+static __inline unsigned int
+get_JumpOpcodeExtension_X1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 58)) & 0x1);
+}
+
+static __inline unsigned int
+get_MF_Imm14_X1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 37)) & 0x3fff);
+}
+
+static __inline unsigned int
+get_MT_Imm14_X1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 31)) & 0x0000003f) |
+ (((unsigned int)(n >> 37)) & 0x00003fc0);
+}
+
+static __inline unsigned int
+get_Mode(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 62)) & 0x3);
+}
+
+static __inline unsigned int
+get_Opcode_X0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 28)) & 0x7);
+}
+
+static __inline unsigned int
+get_Opcode_X1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 59)) & 0x7);
+}
+
+static __inline unsigned int
+get_Opcode_Y0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 27)) & 0xf);
+}
+
+static __inline unsigned int
+get_Opcode_Y1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 58)) & 0xf);
+}
+
+static __inline unsigned int
+get_Opcode_Y2(tilegx_bundle_bits n)
+{
+ return (((n >> 26)) & 0x00000001) |
+ (((unsigned int)(n >> 56)) & 0x00000002);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_X0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 18)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_X1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 49)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_Y0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 18)) & 0x3);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_Y1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 49)) & 0x3);
+}
+
+static __inline unsigned int
+get_ShAmt_X0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_ShAmt_X1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_ShAmt_Y0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_ShAmt_Y1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_ShiftOpcodeExtension_X0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 18)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_ShiftOpcodeExtension_X1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 49)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_ShiftOpcodeExtension_Y0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 18)) & 0x3);
+}
+
+static __inline unsigned int
+get_ShiftOpcodeExtension_Y1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 49)) & 0x3);
+}
+
+static __inline unsigned int
+get_SrcA_X0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 6)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_X1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 37)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 6)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 37)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y2(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 20)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcBDest_Y2(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 51)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_X0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_X1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_Y0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_Y1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_UnaryOpcodeExtension_X0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_UnaryOpcodeExtension_X1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_UnaryOpcodeExtension_Y0(tilegx_bundle_bits num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_UnaryOpcodeExtension_Y1(tilegx_bundle_bits n)
+{
+ return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline int
+sign_extend(int n, int num_bits)
+{
+ int shift = (int)(sizeof(int) * 8 - num_bits);
+ return (n << shift) >> shift;
+}
+
+static __inline tilegx_bundle_bits
+create_BFEnd_X0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_BFOpcodeExtension_X0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0xf) << 24);
+}
+
+static __inline tilegx_bundle_bits
+create_BFStart_X0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0x3f) << 18);
+}
+
+static __inline tilegx_bundle_bits
+create_BrOff_X1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
+ (((tilegx_bundle_bits)(n & 0x0001ffc0)) << 37);
+}
+
+static __inline tilegx_bundle_bits
+create_BrType_X1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x1f)) << 54);
+}
+
+static __inline tilegx_bundle_bits
+create_Dest_Imm8_X1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
+ (((tilegx_bundle_bits)(n & 0x000000c0)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_Dest_X0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0x3f) << 0);
+}
+
+static __inline tilegx_bundle_bits
+create_Dest_X1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x3f)) << 31);
+}
+
+static __inline tilegx_bundle_bits
+create_Dest_Y0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0x3f) << 0);
+}
+
+static __inline tilegx_bundle_bits
+create_Dest_Y1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x3f)) << 31);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm16_X0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0xffff) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm16_X1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0xffff)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8OpcodeExtension_X0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0xff) << 20);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8OpcodeExtension_X1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0xff)) << 51);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8_X0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0xff) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8_X1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0xff)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8_Y0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0xff) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8_Y1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0xff)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_JumpOff_X1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x7ffffff)) << 31);
+}
+
+static __inline tilegx_bundle_bits
+create_JumpOpcodeExtension_X1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x1)) << 58);
+}
+
+static __inline tilegx_bundle_bits
+create_MF_Imm14_X1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x3fff)) << 37);
+}
+
+static __inline tilegx_bundle_bits
+create_MT_Imm14_X1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
+ (((tilegx_bundle_bits)(n & 0x00003fc0)) << 37);
+}
+
+static __inline tilegx_bundle_bits
+create_Mode(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x3)) << 62);
+}
+
+static __inline tilegx_bundle_bits
+create_Opcode_X0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0x7) << 28);
+}
+
+static __inline tilegx_bundle_bits
+create_Opcode_X1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x7)) << 59);
+}
+
+static __inline tilegx_bundle_bits
+create_Opcode_Y0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0xf) << 27);
+}
+
+static __inline tilegx_bundle_bits
+create_Opcode_Y1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0xf)) << 58);
+}
+
+static __inline tilegx_bundle_bits
+create_Opcode_Y2(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0x00000001) << 26) |
+ (((tilegx_bundle_bits)(n & 0x00000002)) << 56);
+}
+
+static __inline tilegx_bundle_bits
+create_RRROpcodeExtension_X0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0x3ff) << 18);
+}
+
+static __inline tilegx_bundle_bits
+create_RRROpcodeExtension_X1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x3ff)) << 49);
+}
+
+static __inline tilegx_bundle_bits
+create_RRROpcodeExtension_Y0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0x3) << 18);
+}
+
+static __inline tilegx_bundle_bits
+create_RRROpcodeExtension_Y1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x3)) << 49);
+}
+
+static __inline tilegx_bundle_bits
+create_ShAmt_X0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_ShAmt_X1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_ShAmt_Y0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_ShAmt_Y1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_ShiftOpcodeExtension_X0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0x3ff) << 18);
+}
+
+static __inline tilegx_bundle_bits
+create_ShiftOpcodeExtension_X1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x3ff)) << 49);
+}
+
+static __inline tilegx_bundle_bits
+create_ShiftOpcodeExtension_Y0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0x3) << 18);
+}
+
+static __inline tilegx_bundle_bits
+create_ShiftOpcodeExtension_Y1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x3)) << 49);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcA_X0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0x3f) << 6);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcA_X1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x3f)) << 37);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcA_Y0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0x3f) << 6);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcA_Y1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x3f)) << 37);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcA_Y2(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0x3f) << 20);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcBDest_Y2(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x3f)) << 51);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcB_X0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcB_X1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcB_Y0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcB_Y1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_UnaryOpcodeExtension_X0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_UnaryOpcodeExtension_X1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_UnaryOpcodeExtension_Y0(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_UnaryOpcodeExtension_Y1(int num)
+{
+ const unsigned int n = (unsigned int)num;
+ return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+const struct tilegx_opcode tilegx_opcodes[336] =
+{
+ { "bpt", TILEGX_OPC_BPT, 0x2, 0, TREG_ZERO, 0,
+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xffffffff80000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286a44ae00000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "info", TILEGX_OPC_INFO, 0xf, 1, TREG_ZERO, 1,
+ { { 0 }, { 1 }, { 2 }, { 3 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00fffULL,
+ 0xfff807ff80000000ULL,
+ 0x0000000078000fffULL,
+ 0x3c0007ff80000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000040300fffULL,
+ 0x181807ff80000000ULL,
+ 0x0000000010000fffULL,
+ 0x0c0007ff80000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "infol", TILEGX_OPC_INFOL, 0x3, 1, TREG_ZERO, 1,
+ { { 4 }, { 5 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc000000070000fffULL,
+ 0xf80007ff80000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000070000fffULL,
+ 0x380007ff80000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ld4s_tls", TILEGX_OPC_LD4S_TLS, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1858000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ld_tls", TILEGX_OPC_LD_TLS, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x18a0000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "move", TILEGX_OPC_MOVE, 0xf, 2, TREG_ZERO, 1,
+ { { 8, 9 }, { 6, 7 }, { 10, 11 }, { 12, 13 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffff000ULL,
+ 0xfffff80000000000ULL,
+ 0x00000000780ff000ULL,
+ 0x3c07f80000000000ULL,
+ 0ULL
+ },
+ {
+ 0x000000005107f000ULL,
+ 0x283bf80000000000ULL,
+ 0x00000000500bf000ULL,
+ 0x2c05f80000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "movei", TILEGX_OPC_MOVEI, 0xf, 2, TREG_ZERO, 1,
+ { { 8, 0 }, { 6, 1 }, { 10, 2 }, { 12, 3 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00fc0ULL,
+ 0xfff807e000000000ULL,
+ 0x0000000078000fc0ULL,
+ 0x3c0007e000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000040100fc0ULL,
+ 0x180807e000000000ULL,
+ 0x0000000000000fc0ULL,
+ 0x040007e000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "moveli", TILEGX_OPC_MOVELI, 0x3, 2, TREG_ZERO, 1,
+ { { 8, 4 }, { 6, 5 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc000000070000fc0ULL,
+ 0xf80007e000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000010000fc0ULL,
+ 0x000007e000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "prefetch", TILEGX_OPC_PREFETCH, 0x12, 1, TREG_ZERO, 1,
+ { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff81f80000000ULL,
+ 0ULL,
+ 0ULL,
+ 0xc3f8000004000000ULL
+ },
+ {
+ -1ULL,
+ 0x286a801f80000000ULL,
+ -1ULL,
+ -1ULL,
+ 0x41f8000004000000ULL
+ }
+#endif
+ },
+ { "prefetch_add_l1", TILEGX_OPC_PREFETCH_ADD_L1, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8001f80000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1840001f80000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "prefetch_add_l1_fault", TILEGX_OPC_PREFETCH_ADD_L1_FAULT, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8001f80000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1838001f80000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "prefetch_add_l2", TILEGX_OPC_PREFETCH_ADD_L2, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8001f80000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1850001f80000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "prefetch_add_l2_fault", TILEGX_OPC_PREFETCH_ADD_L2_FAULT, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8001f80000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1848001f80000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "prefetch_add_l3", TILEGX_OPC_PREFETCH_ADD_L3, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8001f80000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1860001f80000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "prefetch_add_l3_fault", TILEGX_OPC_PREFETCH_ADD_L3_FAULT, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8001f80000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1858001f80000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "prefetch_l1", TILEGX_OPC_PREFETCH_L1, 0x12, 1, TREG_ZERO, 1,
+ { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff81f80000000ULL,
+ 0ULL,
+ 0ULL,
+ 0xc3f8000004000000ULL
+ },
+ {
+ -1ULL,
+ 0x286a801f80000000ULL,
+ -1ULL,
+ -1ULL,
+ 0x41f8000004000000ULL
+ }
+#endif
+ },
+ { "prefetch_l1_fault", TILEGX_OPC_PREFETCH_L1_FAULT, 0x12, 1, TREG_ZERO, 1,
+ { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff81f80000000ULL,
+ 0ULL,
+ 0ULL,
+ 0xc3f8000004000000ULL
+ },
+ {
+ -1ULL,
+ 0x286a781f80000000ULL,
+ -1ULL,
+ -1ULL,
+ 0x41f8000000000000ULL
+ }
+#endif
+ },
+ { "prefetch_l2", TILEGX_OPC_PREFETCH_L2, 0x12, 1, TREG_ZERO, 1,
+ { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff81f80000000ULL,
+ 0ULL,
+ 0ULL,
+ 0xc3f8000004000000ULL
+ },
+ {
+ -1ULL,
+ 0x286a901f80000000ULL,
+ -1ULL,
+ -1ULL,
+ 0x43f8000004000000ULL
+ }
+#endif
+ },
+ { "prefetch_l2_fault", TILEGX_OPC_PREFETCH_L2_FAULT, 0x12, 1, TREG_ZERO, 1,
+ { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff81f80000000ULL,
+ 0ULL,
+ 0ULL,
+ 0xc3f8000004000000ULL
+ },
+ {
+ -1ULL,
+ 0x286a881f80000000ULL,
+ -1ULL,
+ -1ULL,
+ 0x43f8000000000000ULL
+ }
+#endif
+ },
+ { "prefetch_l3", TILEGX_OPC_PREFETCH_L3, 0x12, 1, TREG_ZERO, 1,
+ { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff81f80000000ULL,
+ 0ULL,
+ 0ULL,
+ 0xc3f8000004000000ULL
+ },
+ {
+ -1ULL,
+ 0x286aa01f80000000ULL,
+ -1ULL,
+ -1ULL,
+ 0x83f8000000000000ULL
+ }
+#endif
+ },
+ { "prefetch_l3_fault", TILEGX_OPC_PREFETCH_L3_FAULT, 0x12, 1, TREG_ZERO, 1,
+ { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff81f80000000ULL,
+ 0ULL,
+ 0ULL,
+ 0xc3f8000004000000ULL
+ },
+ {
+ -1ULL,
+ 0x286a981f80000000ULL,
+ -1ULL,
+ -1ULL,
+ 0x81f8000004000000ULL
+ }
+#endif
+ },
+ { "raise", TILEGX_OPC_RAISE, 0x2, 0, TREG_ZERO, 1,
+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xffffffff80000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286a44ae80000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "add", TILEGX_OPC_ADD, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x00000000500c0000ULL,
+ 0x2806000000000000ULL,
+ 0x0000000028040000ULL,
+ 0x1802000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "addi", TILEGX_OPC_ADDI, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 0 }, { 6, 7, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00000ULL,
+ 0xfff8000000000000ULL,
+ 0x0000000078000000ULL,
+ 0x3c00000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000040100000ULL,
+ 0x1808000000000000ULL,
+ 0ULL,
+ 0x0400000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "addli", TILEGX_OPC_ADDLI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 4 }, { 6, 7, 5 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc000000070000000ULL,
+ 0xf800000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000010000000ULL,
+ 0ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "addx", TILEGX_OPC_ADDX, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050080000ULL,
+ 0x2804000000000000ULL,
+ 0x0000000028000000ULL,
+ 0x1800000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "addxi", TILEGX_OPC_ADDXI, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 0 }, { 6, 7, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00000ULL,
+ 0xfff8000000000000ULL,
+ 0x0000000078000000ULL,
+ 0x3c00000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000040200000ULL,
+ 0x1810000000000000ULL,
+ 0x0000000008000000ULL,
+ 0x0800000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "addxli", TILEGX_OPC_ADDXLI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 4 }, { 6, 7, 5 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc000000070000000ULL,
+ 0xf800000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000020000000ULL,
+ 0x0800000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "addxsc", TILEGX_OPC_ADDXSC, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050040000ULL,
+ 0x2802000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "and", TILEGX_OPC_AND, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050100000ULL,
+ 0x2808000000000000ULL,
+ 0x0000000050000000ULL,
+ 0x2c00000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "andi", TILEGX_OPC_ANDI, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 0 }, { 6, 7, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00000ULL,
+ 0xfff8000000000000ULL,
+ 0x0000000078000000ULL,
+ 0x3c00000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000040300000ULL,
+ 0x1818000000000000ULL,
+ 0x0000000010000000ULL,
+ 0x0c00000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "beqz", TILEGX_OPC_BEQZ, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xffc0000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1440000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "beqzt", TILEGX_OPC_BEQZT, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xffc0000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1400000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "bfexts", TILEGX_OPC_BFEXTS, 0x1, 4, TREG_ZERO, 1,
+ { { 8, 9, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007f000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000034000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "bfextu", TILEGX_OPC_BFEXTU, 0x1, 4, TREG_ZERO, 1,
+ { { 8, 9, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007f000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000035000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "bfins", TILEGX_OPC_BFINS, 0x1, 4, TREG_ZERO, 1,
+ { { 23, 9, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007f000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000036000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "bgez", TILEGX_OPC_BGEZ, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xffc0000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x14c0000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "bgezt", TILEGX_OPC_BGEZT, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xffc0000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1480000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "bgtz", TILEGX_OPC_BGTZ, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xffc0000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1540000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "bgtzt", TILEGX_OPC_BGTZT, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xffc0000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1500000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "blbc", TILEGX_OPC_BLBC, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xffc0000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x15c0000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "blbct", TILEGX_OPC_BLBCT, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xffc0000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1580000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "blbs", TILEGX_OPC_BLBS, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xffc0000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1640000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "blbst", TILEGX_OPC_BLBST, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xffc0000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1600000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "blez", TILEGX_OPC_BLEZ, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xffc0000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x16c0000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "blezt", TILEGX_OPC_BLEZT, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xffc0000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1680000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "bltz", TILEGX_OPC_BLTZ, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xffc0000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1740000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "bltzt", TILEGX_OPC_BLTZT, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xffc0000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1700000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "bnez", TILEGX_OPC_BNEZ, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xffc0000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x17c0000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "bnezt", TILEGX_OPC_BNEZT, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xffc0000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1780000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "clz", TILEGX_OPC_CLZ, 0x5, 2, TREG_ZERO, 1,
+ { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffff000ULL,
+ 0ULL,
+ 0x00000000780ff000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051481000ULL,
+ -1ULL,
+ 0x00000000300c1000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "cmoveqz", TILEGX_OPC_CMOVEQZ, 0x5, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0x00000000780c0000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050140000ULL,
+ -1ULL,
+ 0x0000000048000000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "cmovnez", TILEGX_OPC_CMOVNEZ, 0x5, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0x00000000780c0000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050180000ULL,
+ -1ULL,
+ 0x0000000048040000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "cmpeq", TILEGX_OPC_CMPEQ, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x00000000501c0000ULL,
+ 0x280a000000000000ULL,
+ 0x0000000040000000ULL,
+ 0x2404000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "cmpeqi", TILEGX_OPC_CMPEQI, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 0 }, { 6, 7, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00000ULL,
+ 0xfff8000000000000ULL,
+ 0x0000000078000000ULL,
+ 0x3c00000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000040400000ULL,
+ 0x1820000000000000ULL,
+ 0x0000000018000000ULL,
+ 0x1000000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "cmpexch", TILEGX_OPC_CMPEXCH, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x280e000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "cmpexch4", TILEGX_OPC_CMPEXCH4, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x280c000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "cmples", TILEGX_OPC_CMPLES, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050200000ULL,
+ 0x2810000000000000ULL,
+ 0x0000000038000000ULL,
+ 0x2000000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "cmpleu", TILEGX_OPC_CMPLEU, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050240000ULL,
+ 0x2812000000000000ULL,
+ 0x0000000038040000ULL,
+ 0x2002000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "cmplts", TILEGX_OPC_CMPLTS, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050280000ULL,
+ 0x2814000000000000ULL,
+ 0x0000000038080000ULL,
+ 0x2004000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "cmpltsi", TILEGX_OPC_CMPLTSI, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 0 }, { 6, 7, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00000ULL,
+ 0xfff8000000000000ULL,
+ 0x0000000078000000ULL,
+ 0x3c00000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000040500000ULL,
+ 0x1828000000000000ULL,
+ 0x0000000020000000ULL,
+ 0x1400000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "cmpltu", TILEGX_OPC_CMPLTU, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x00000000502c0000ULL,
+ 0x2816000000000000ULL,
+ 0x00000000380c0000ULL,
+ 0x2006000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "cmpltui", TILEGX_OPC_CMPLTUI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00000ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000040600000ULL,
+ 0x1830000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "cmpne", TILEGX_OPC_CMPNE, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050300000ULL,
+ 0x2818000000000000ULL,
+ 0x0000000040040000ULL,
+ 0x2406000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "cmul", TILEGX_OPC_CMUL, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000504c0000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "cmula", TILEGX_OPC_CMULA, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050380000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "cmulaf", TILEGX_OPC_CMULAF, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050340000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "cmulf", TILEGX_OPC_CMULF, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050400000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "cmulfr", TILEGX_OPC_CMULFR, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000503c0000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "cmulh", TILEGX_OPC_CMULH, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050480000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "cmulhr", TILEGX_OPC_CMULHR, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050440000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "crc32_32", TILEGX_OPC_CRC32_32, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050500000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "crc32_8", TILEGX_OPC_CRC32_8, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050540000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ctz", TILEGX_OPC_CTZ, 0x5, 2, TREG_ZERO, 1,
+ { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffff000ULL,
+ 0ULL,
+ 0x00000000780ff000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051482000ULL,
+ -1ULL,
+ 0x00000000300c2000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "dblalign", TILEGX_OPC_DBLALIGN, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050640000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "dblalign2", TILEGX_OPC_DBLALIGN2, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050580000ULL,
+ 0x281a000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "dblalign4", TILEGX_OPC_DBLALIGN4, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000505c0000ULL,
+ 0x281c000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "dblalign6", TILEGX_OPC_DBLALIGN6, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050600000ULL,
+ 0x281e000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "drain", TILEGX_OPC_DRAIN, 0x2, 0, TREG_ZERO, 0,
+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286a080000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "dtlbpr", TILEGX_OPC_DTLBPR, 0x2, 1, TREG_ZERO, 1,
+ { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286a100000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "exch", TILEGX_OPC_EXCH, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x2822000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "exch4", TILEGX_OPC_EXCH4, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x2820000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fdouble_add_flags", TILEGX_OPC_FDOUBLE_ADD_FLAGS, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000506c0000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fdouble_addsub", TILEGX_OPC_FDOUBLE_ADDSUB, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050680000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fdouble_mul_flags", TILEGX_OPC_FDOUBLE_MUL_FLAGS, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050700000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fdouble_pack1", TILEGX_OPC_FDOUBLE_PACK1, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050740000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fdouble_pack2", TILEGX_OPC_FDOUBLE_PACK2, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050780000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fdouble_sub_flags", TILEGX_OPC_FDOUBLE_SUB_FLAGS, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000507c0000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fdouble_unpack_max", TILEGX_OPC_FDOUBLE_UNPACK_MAX, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050800000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fdouble_unpack_min", TILEGX_OPC_FDOUBLE_UNPACK_MIN, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050840000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fetchadd", TILEGX_OPC_FETCHADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x282a000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fetchadd4", TILEGX_OPC_FETCHADD4, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x2824000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fetchaddgez", TILEGX_OPC_FETCHADDGEZ, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x2828000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fetchaddgez4", TILEGX_OPC_FETCHADDGEZ4, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x2826000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fetchand", TILEGX_OPC_FETCHAND, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x282e000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fetchand4", TILEGX_OPC_FETCHAND4, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x282c000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fetchor", TILEGX_OPC_FETCHOR, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x2832000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fetchor4", TILEGX_OPC_FETCHOR4, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x2830000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "finv", TILEGX_OPC_FINV, 0x2, 1, TREG_ZERO, 1,
+ { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286a180000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "flush", TILEGX_OPC_FLUSH, 0x2, 1, TREG_ZERO, 1,
+ { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286a280000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "flushwb", TILEGX_OPC_FLUSHWB, 0x2, 0, TREG_ZERO, 1,
+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286a200000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fnop", TILEGX_OPC_FNOP, 0xf, 0, TREG_ZERO, 1,
+ { { }, { }, { }, { }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffff000ULL,
+ 0xfffff80000000000ULL,
+ 0x00000000780ff000ULL,
+ 0x3c07f80000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051483000ULL,
+ 0x286a300000000000ULL,
+ 0x00000000300c3000ULL,
+ 0x1c06400000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fsingle_add1", TILEGX_OPC_FSINGLE_ADD1, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050880000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fsingle_addsub2", TILEGX_OPC_FSINGLE_ADDSUB2, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000508c0000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fsingle_mul1", TILEGX_OPC_FSINGLE_MUL1, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050900000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fsingle_mul2", TILEGX_OPC_FSINGLE_MUL2, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050940000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fsingle_pack1", TILEGX_OPC_FSINGLE_PACK1, 0x5, 2, TREG_ZERO, 1,
+ { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffff000ULL,
+ 0ULL,
+ 0x00000000780ff000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051484000ULL,
+ -1ULL,
+ 0x00000000300c4000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fsingle_pack2", TILEGX_OPC_FSINGLE_PACK2, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050980000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "fsingle_sub1", TILEGX_OPC_FSINGLE_SUB1, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000509c0000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "icoh", TILEGX_OPC_ICOH, 0x2, 1, TREG_ZERO, 1,
+ { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286a380000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ill", TILEGX_OPC_ILL, 0xa, 0, TREG_ZERO, 1,
+ { { 0, }, { }, { 0, }, { }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0x3c07f80000000000ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286a400000000000ULL,
+ -1ULL,
+ 0x1c06480000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "inv", TILEGX_OPC_INV, 0x2, 1, TREG_ZERO, 1,
+ { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286a480000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "iret", TILEGX_OPC_IRET, 0x2, 0, TREG_ZERO, 1,
+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286a500000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "j", TILEGX_OPC_J, 0x2, 1, TREG_ZERO, 1,
+ { { 0, }, { 25 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfc00000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x2400000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "jal", TILEGX_OPC_JAL, 0x2, 1, TREG_LR, 1,
+ { { 0, }, { 25 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfc00000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x2000000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "jalr", TILEGX_OPC_JALR, 0xa, 1, TREG_LR, 1,
+ { { 0, }, { 7 }, { 0, }, { 13 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0x3c07f80000000000ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286a600000000000ULL,
+ -1ULL,
+ 0x1c06580000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "jalrp", TILEGX_OPC_JALRP, 0xa, 1, TREG_LR, 1,
+ { { 0, }, { 7 }, { 0, }, { 13 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0x3c07f80000000000ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286a580000000000ULL,
+ -1ULL,
+ 0x1c06500000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "jr", TILEGX_OPC_JR, 0xa, 1, TREG_ZERO, 1,
+ { { 0, }, { 7 }, { 0, }, { 13 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0x3c07f80000000000ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286a700000000000ULL,
+ -1ULL,
+ 0x1c06680000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "jrp", TILEGX_OPC_JRP, 0xa, 1, TREG_ZERO, 1,
+ { { 0, }, { 7 }, { 0, }, { 13 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0x3c07f80000000000ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286a680000000000ULL,
+ -1ULL,
+ 0x1c06600000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ld", TILEGX_OPC_LD, 0x12, 2, TREG_ZERO, 1,
+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0xc200000004000000ULL
+ },
+ {
+ -1ULL,
+ 0x286ae80000000000ULL,
+ -1ULL,
+ -1ULL,
+ 0x8200000004000000ULL
+ }
+#endif
+ },
+ { "ld1s", TILEGX_OPC_LD1S, 0x12, 2, TREG_ZERO, 1,
+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0xc200000004000000ULL
+ },
+ {
+ -1ULL,
+ 0x286a780000000000ULL,
+ -1ULL,
+ -1ULL,
+ 0x4000000000000000ULL
+ }
+#endif
+ },
+ { "ld1s_add", TILEGX_OPC_LD1S_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1838000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ld1u", TILEGX_OPC_LD1U, 0x12, 2, TREG_ZERO, 1,
+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0xc200000004000000ULL
+ },
+ {
+ -1ULL,
+ 0x286a800000000000ULL,
+ -1ULL,
+ -1ULL,
+ 0x4000000004000000ULL
+ }
+#endif
+ },
+ { "ld1u_add", TILEGX_OPC_LD1U_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1840000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ld2s", TILEGX_OPC_LD2S, 0x12, 2, TREG_ZERO, 1,
+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0xc200000004000000ULL
+ },
+ {
+ -1ULL,
+ 0x286a880000000000ULL,
+ -1ULL,
+ -1ULL,
+ 0x4200000000000000ULL
+ }
+#endif
+ },
+ { "ld2s_add", TILEGX_OPC_LD2S_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1848000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ld2u", TILEGX_OPC_LD2U, 0x12, 2, TREG_ZERO, 1,
+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0xc200000004000000ULL
+ },
+ {
+ -1ULL,
+ 0x286a900000000000ULL,
+ -1ULL,
+ -1ULL,
+ 0x4200000004000000ULL
+ }
+#endif
+ },
+ { "ld2u_add", TILEGX_OPC_LD2U_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1850000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ld4s", TILEGX_OPC_LD4S, 0x12, 2, TREG_ZERO, 1,
+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0xc200000004000000ULL
+ },
+ {
+ -1ULL,
+ 0x286a980000000000ULL,
+ -1ULL,
+ -1ULL,
+ 0x8000000004000000ULL
+ }
+#endif
+ },
+ { "ld4s_add", TILEGX_OPC_LD4S_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1858000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ld4u", TILEGX_OPC_LD4U, 0x12, 2, TREG_ZERO, 1,
+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0xc200000004000000ULL
+ },
+ {
+ -1ULL,
+ 0x286aa00000000000ULL,
+ -1ULL,
+ -1ULL,
+ 0x8200000000000000ULL
+ }
+#endif
+ },
+ { "ld4u_add", TILEGX_OPC_LD4U_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1860000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ld_add", TILEGX_OPC_LD_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x18a0000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ldna", TILEGX_OPC_LDNA, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286aa80000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ldna_add", TILEGX_OPC_LDNA_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x18a8000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ldnt", TILEGX_OPC_LDNT, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286ae00000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ldnt1s", TILEGX_OPC_LDNT1S, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286ab00000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ldnt1s_add", TILEGX_OPC_LDNT1S_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1868000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ldnt1u", TILEGX_OPC_LDNT1U, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286ab80000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ldnt1u_add", TILEGX_OPC_LDNT1U_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1870000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ldnt2s", TILEGX_OPC_LDNT2S, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286ac00000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ldnt2s_add", TILEGX_OPC_LDNT2S_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1878000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ldnt2u", TILEGX_OPC_LDNT2U, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286ac80000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ldnt2u_add", TILEGX_OPC_LDNT2U_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1880000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ldnt4s", TILEGX_OPC_LDNT4S, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286ad00000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ldnt4s_add", TILEGX_OPC_LDNT4S_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1888000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ldnt4u", TILEGX_OPC_LDNT4U, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286ad80000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ldnt4u_add", TILEGX_OPC_LDNT4U_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1890000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ldnt_add", TILEGX_OPC_LDNT_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1898000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "lnk", TILEGX_OPC_LNK, 0xa, 1, TREG_ZERO, 1,
+ { { 0, }, { 6 }, { 0, }, { 12 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0x3c07f80000000000ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286af00000000000ULL,
+ -1ULL,
+ 0x1c06700000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mf", TILEGX_OPC_MF, 0x2, 0, TREG_ZERO, 1,
+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286af80000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mfspr", TILEGX_OPC_MFSPR, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 6, 27 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x18b0000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mm", TILEGX_OPC_MM, 0x1, 4, TREG_ZERO, 1,
+ { { 23, 9, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007f000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000037000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mnz", TILEGX_OPC_MNZ, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050a00000ULL,
+ 0x2834000000000000ULL,
+ 0x0000000048080000ULL,
+ 0x2804000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mtspr", TILEGX_OPC_MTSPR, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 28, 7 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x18b8000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mul_hs_hs", TILEGX_OPC_MUL_HS_HS, 0x5, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0x00000000780c0000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050d40000ULL,
+ -1ULL,
+ 0x0000000068000000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mul_hs_hu", TILEGX_OPC_MUL_HS_HU, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050d80000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mul_hs_ls", TILEGX_OPC_MUL_HS_LS, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050dc0000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mul_hs_lu", TILEGX_OPC_MUL_HS_LU, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050e00000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mul_hu_hu", TILEGX_OPC_MUL_HU_HU, 0x5, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0x00000000780c0000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050e40000ULL,
+ -1ULL,
+ 0x0000000068040000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mul_hu_ls", TILEGX_OPC_MUL_HU_LS, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050e80000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mul_hu_lu", TILEGX_OPC_MUL_HU_LU, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050ec0000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mul_ls_ls", TILEGX_OPC_MUL_LS_LS, 0x5, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0x00000000780c0000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050f00000ULL,
+ -1ULL,
+ 0x0000000068080000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mul_ls_lu", TILEGX_OPC_MUL_LS_LU, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050f40000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mul_lu_lu", TILEGX_OPC_MUL_LU_LU, 0x5, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0x00000000780c0000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050f80000ULL,
+ -1ULL,
+ 0x00000000680c0000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mula_hs_hs", TILEGX_OPC_MULA_HS_HS, 0x5, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0x00000000780c0000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050a80000ULL,
+ -1ULL,
+ 0x0000000070000000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mula_hs_hu", TILEGX_OPC_MULA_HS_HU, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050ac0000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mula_hs_ls", TILEGX_OPC_MULA_HS_LS, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050b00000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mula_hs_lu", TILEGX_OPC_MULA_HS_LU, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050b40000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mula_hu_hu", TILEGX_OPC_MULA_HU_HU, 0x5, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0x00000000780c0000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050b80000ULL,
+ -1ULL,
+ 0x0000000070040000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mula_hu_ls", TILEGX_OPC_MULA_HU_LS, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050bc0000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mula_hu_lu", TILEGX_OPC_MULA_HU_LU, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050c00000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mula_ls_ls", TILEGX_OPC_MULA_LS_LS, 0x5, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0x00000000780c0000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050c40000ULL,
+ -1ULL,
+ 0x0000000070080000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mula_ls_lu", TILEGX_OPC_MULA_LS_LU, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050c80000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mula_lu_lu", TILEGX_OPC_MULA_LU_LU, 0x5, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0x00000000780c0000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050cc0000ULL,
+ -1ULL,
+ 0x00000000700c0000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mulax", TILEGX_OPC_MULAX, 0x5, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0x00000000780c0000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050a40000ULL,
+ -1ULL,
+ 0x0000000040080000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mulx", TILEGX_OPC_MULX, 0x5, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0x00000000780c0000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050d00000ULL,
+ -1ULL,
+ 0x00000000400c0000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "mz", TILEGX_OPC_MZ, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000050fc0000ULL,
+ 0x2836000000000000ULL,
+ 0x00000000480c0000ULL,
+ 0x2806000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "nap", TILEGX_OPC_NAP, 0x2, 0, TREG_ZERO, 0,
+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286b000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "nop", TILEGX_OPC_NOP, 0xf, 0, TREG_ZERO, 1,
+ { { }, { }, { }, { }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffff000ULL,
+ 0xfffff80000000000ULL,
+ 0x00000000780ff000ULL,
+ 0x3c07f80000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051485000ULL,
+ 0x286b080000000000ULL,
+ 0x00000000300c5000ULL,
+ 0x1c06780000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "nor", TILEGX_OPC_NOR, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051000000ULL,
+ 0x2838000000000000ULL,
+ 0x0000000050040000ULL,
+ 0x2c02000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "or", TILEGX_OPC_OR, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051040000ULL,
+ 0x283a000000000000ULL,
+ 0x0000000050080000ULL,
+ 0x2c04000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "ori", TILEGX_OPC_ORI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00000ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000040700000ULL,
+ 0x18c0000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "pcnt", TILEGX_OPC_PCNT, 0x5, 2, TREG_ZERO, 1,
+ { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffff000ULL,
+ 0ULL,
+ 0x00000000780ff000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051486000ULL,
+ -1ULL,
+ 0x00000000300c6000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "revbits", TILEGX_OPC_REVBITS, 0x5, 2, TREG_ZERO, 1,
+ { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffff000ULL,
+ 0ULL,
+ 0x00000000780ff000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051487000ULL,
+ -1ULL,
+ 0x00000000300c7000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "revbytes", TILEGX_OPC_REVBYTES, 0x5, 2, TREG_ZERO, 1,
+ { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffff000ULL,
+ 0ULL,
+ 0x00000000780ff000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051488000ULL,
+ -1ULL,
+ 0x00000000300c8000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "rotl", TILEGX_OPC_ROTL, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051080000ULL,
+ 0x283c000000000000ULL,
+ 0x0000000058000000ULL,
+ 0x3000000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "rotli", TILEGX_OPC_ROTLI, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 29 }, { 6, 7, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000060040000ULL,
+ 0x3002000000000000ULL,
+ 0x0000000078000000ULL,
+ 0x3800000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "shl", TILEGX_OPC_SHL, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051280000ULL,
+ 0x284c000000000000ULL,
+ 0x0000000058040000ULL,
+ 0x3002000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "shl16insli", TILEGX_OPC_SHL16INSLI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 4 }, { 6, 7, 5 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc000000070000000ULL,
+ 0xf800000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000070000000ULL,
+ 0x3800000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "shl1add", TILEGX_OPC_SHL1ADD, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051100000ULL,
+ 0x2840000000000000ULL,
+ 0x0000000030000000ULL,
+ 0x1c00000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "shl1addx", TILEGX_OPC_SHL1ADDX, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x00000000510c0000ULL,
+ 0x283e000000000000ULL,
+ 0x0000000060040000ULL,
+ 0x3402000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "shl2add", TILEGX_OPC_SHL2ADD, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051180000ULL,
+ 0x2844000000000000ULL,
+ 0x0000000030040000ULL,
+ 0x1c02000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "shl2addx", TILEGX_OPC_SHL2ADDX, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051140000ULL,
+ 0x2842000000000000ULL,
+ 0x0000000060080000ULL,
+ 0x3404000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "shl3add", TILEGX_OPC_SHL3ADD, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051200000ULL,
+ 0x2848000000000000ULL,
+ 0x0000000030080000ULL,
+ 0x1c04000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "shl3addx", TILEGX_OPC_SHL3ADDX, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x00000000511c0000ULL,
+ 0x2846000000000000ULL,
+ 0x00000000600c0000ULL,
+ 0x3406000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "shli", TILEGX_OPC_SHLI, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 29 }, { 6, 7, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000060080000ULL,
+ 0x3004000000000000ULL,
+ 0x0000000078040000ULL,
+ 0x3802000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "shlx", TILEGX_OPC_SHLX, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051240000ULL,
+ 0x284a000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "shlxi", TILEGX_OPC_SHLXI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000600c0000ULL,
+ 0x3006000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "shrs", TILEGX_OPC_SHRS, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x00000000512c0000ULL,
+ 0x284e000000000000ULL,
+ 0x0000000058080000ULL,
+ 0x3004000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "shrsi", TILEGX_OPC_SHRSI, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 29 }, { 6, 7, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000060100000ULL,
+ 0x3008000000000000ULL,
+ 0x0000000078080000ULL,
+ 0x3804000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "shru", TILEGX_OPC_SHRU, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051340000ULL,
+ 0x2852000000000000ULL,
+ 0x00000000580c0000ULL,
+ 0x3006000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "shrui", TILEGX_OPC_SHRUI, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 29 }, { 6, 7, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000060140000ULL,
+ 0x300a000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3806000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "shrux", TILEGX_OPC_SHRUX, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051300000ULL,
+ 0x2850000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "shruxi", TILEGX_OPC_SHRUXI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000060180000ULL,
+ 0x300c000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "shufflebytes", TILEGX_OPC_SHUFFLEBYTES, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051380000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "st", TILEGX_OPC_ST, 0x12, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 14, 33 } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0xc200000004000000ULL
+ },
+ {
+ -1ULL,
+ 0x2862000000000000ULL,
+ -1ULL,
+ -1ULL,
+ 0xc200000004000000ULL
+ }
+#endif
+ },
+ { "st1", TILEGX_OPC_ST1, 0x12, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 14, 33 } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0xc200000004000000ULL
+ },
+ {
+ -1ULL,
+ 0x2854000000000000ULL,
+ -1ULL,
+ -1ULL,
+ 0xc000000000000000ULL
+ }
+#endif
+ },
+ { "st1_add", TILEGX_OPC_ST1_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x18c8000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "st2", TILEGX_OPC_ST2, 0x12, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 14, 33 } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0xc200000004000000ULL
+ },
+ {
+ -1ULL,
+ 0x2856000000000000ULL,
+ -1ULL,
+ -1ULL,
+ 0xc000000004000000ULL
+ }
+#endif
+ },
+ { "st2_add", TILEGX_OPC_ST2_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x18d0000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "st4", TILEGX_OPC_ST4, 0x12, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 14, 33 } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0xc200000004000000ULL
+ },
+ {
+ -1ULL,
+ 0x2858000000000000ULL,
+ -1ULL,
+ -1ULL,
+ 0xc200000000000000ULL
+ }
+#endif
+ },
+ { "st4_add", TILEGX_OPC_ST4_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x18d8000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "st_add", TILEGX_OPC_ST_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x1900000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "stnt", TILEGX_OPC_STNT, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x2860000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "stnt1", TILEGX_OPC_STNT1, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x285a000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "stnt1_add", TILEGX_OPC_STNT1_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x18e0000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "stnt2", TILEGX_OPC_STNT2, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x285c000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "stnt2_add", TILEGX_OPC_STNT2_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x18e8000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "stnt4", TILEGX_OPC_STNT4, 0x2, 2, TREG_ZERO, 1,
+ { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x285e000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "stnt4_add", TILEGX_OPC_STNT4_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x18f0000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "stnt_add", TILEGX_OPC_STNT_ADD, 0x2, 3, TREG_ZERO, 1,
+ { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x18f8000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "sub", TILEGX_OPC_SUB, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051440000ULL,
+ 0x2868000000000000ULL,
+ 0x00000000280c0000ULL,
+ 0x1806000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "subx", TILEGX_OPC_SUBX, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051400000ULL,
+ 0x2866000000000000ULL,
+ 0x0000000028080000ULL,
+ 0x1804000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "subxsc", TILEGX_OPC_SUBXSC, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000513c0000ULL,
+ 0x2864000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "swint0", TILEGX_OPC_SWINT0, 0x2, 0, TREG_ZERO, 0,
+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286b100000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "swint1", TILEGX_OPC_SWINT1, 0x2, 0, TREG_ZERO, 0,
+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286b180000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "swint2", TILEGX_OPC_SWINT2, 0x2, 0, TREG_ZERO, 0,
+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286b200000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "swint3", TILEGX_OPC_SWINT3, 0x2, 0, TREG_ZERO, 0,
+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286b280000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "tblidxb0", TILEGX_OPC_TBLIDXB0, 0x5, 2, TREG_ZERO, 1,
+ { { 23, 9 }, { 0, }, { 24, 11 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffff000ULL,
+ 0ULL,
+ 0x00000000780ff000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051489000ULL,
+ -1ULL,
+ 0x00000000300c9000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "tblidxb1", TILEGX_OPC_TBLIDXB1, 0x5, 2, TREG_ZERO, 1,
+ { { 23, 9 }, { 0, }, { 24, 11 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffff000ULL,
+ 0ULL,
+ 0x00000000780ff000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x000000005148a000ULL,
+ -1ULL,
+ 0x00000000300ca000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "tblidxb2", TILEGX_OPC_TBLIDXB2, 0x5, 2, TREG_ZERO, 1,
+ { { 23, 9 }, { 0, }, { 24, 11 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffff000ULL,
+ 0ULL,
+ 0x00000000780ff000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x000000005148b000ULL,
+ -1ULL,
+ 0x00000000300cb000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "tblidxb3", TILEGX_OPC_TBLIDXB3, 0x5, 2, TREG_ZERO, 1,
+ { { 23, 9 }, { 0, }, { 24, 11 }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffff000ULL,
+ 0ULL,
+ 0x00000000780ff000ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x000000005148c000ULL,
+ -1ULL,
+ 0x00000000300cc000ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1add", TILEGX_OPC_V1ADD, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051500000ULL,
+ 0x286e000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1addi", TILEGX_OPC_V1ADDI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00000ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000040800000ULL,
+ 0x1908000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1adduc", TILEGX_OPC_V1ADDUC, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000514c0000ULL,
+ 0x286c000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1adiffu", TILEGX_OPC_V1ADIFFU, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051540000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1avgu", TILEGX_OPC_V1AVGU, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051580000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1cmpeq", TILEGX_OPC_V1CMPEQ, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000515c0000ULL,
+ 0x2870000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1cmpeqi", TILEGX_OPC_V1CMPEQI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00000ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000040900000ULL,
+ 0x1910000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1cmples", TILEGX_OPC_V1CMPLES, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051600000ULL,
+ 0x2872000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1cmpleu", TILEGX_OPC_V1CMPLEU, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051640000ULL,
+ 0x2874000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1cmplts", TILEGX_OPC_V1CMPLTS, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051680000ULL,
+ 0x2876000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1cmpltsi", TILEGX_OPC_V1CMPLTSI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00000ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000040a00000ULL,
+ 0x1918000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1cmpltu", TILEGX_OPC_V1CMPLTU, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000516c0000ULL,
+ 0x2878000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1cmpltui", TILEGX_OPC_V1CMPLTUI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00000ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000040b00000ULL,
+ 0x1920000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1cmpne", TILEGX_OPC_V1CMPNE, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051700000ULL,
+ 0x287a000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1ddotpu", TILEGX_OPC_V1DDOTPU, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052880000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1ddotpua", TILEGX_OPC_V1DDOTPUA, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052840000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1ddotpus", TILEGX_OPC_V1DDOTPUS, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051780000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1ddotpusa", TILEGX_OPC_V1DDOTPUSA, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051740000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1dotp", TILEGX_OPC_V1DOTP, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051880000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1dotpa", TILEGX_OPC_V1DOTPA, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000517c0000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1dotpu", TILEGX_OPC_V1DOTPU, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052900000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1dotpua", TILEGX_OPC_V1DOTPUA, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000528c0000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1dotpus", TILEGX_OPC_V1DOTPUS, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051840000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1dotpusa", TILEGX_OPC_V1DOTPUSA, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051800000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1int_h", TILEGX_OPC_V1INT_H, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000518c0000ULL,
+ 0x287c000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1int_l", TILEGX_OPC_V1INT_L, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051900000ULL,
+ 0x287e000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1maxu", TILEGX_OPC_V1MAXU, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051940000ULL,
+ 0x2880000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1maxui", TILEGX_OPC_V1MAXUI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00000ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000040c00000ULL,
+ 0x1928000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1minu", TILEGX_OPC_V1MINU, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051980000ULL,
+ 0x2882000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1minui", TILEGX_OPC_V1MINUI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00000ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000040d00000ULL,
+ 0x1930000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1mnz", TILEGX_OPC_V1MNZ, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000519c0000ULL,
+ 0x2884000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1multu", TILEGX_OPC_V1MULTU, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051a00000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1mulu", TILEGX_OPC_V1MULU, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051a80000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1mulus", TILEGX_OPC_V1MULUS, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051a40000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1mz", TILEGX_OPC_V1MZ, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051ac0000ULL,
+ 0x2886000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1sadau", TILEGX_OPC_V1SADAU, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051b00000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1sadu", TILEGX_OPC_V1SADU, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051b40000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1shl", TILEGX_OPC_V1SHL, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051b80000ULL,
+ 0x2888000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1shli", TILEGX_OPC_V1SHLI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000601c0000ULL,
+ 0x300e000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1shrs", TILEGX_OPC_V1SHRS, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051bc0000ULL,
+ 0x288a000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1shrsi", TILEGX_OPC_V1SHRSI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000060200000ULL,
+ 0x3010000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1shru", TILEGX_OPC_V1SHRU, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051c00000ULL,
+ 0x288c000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1shrui", TILEGX_OPC_V1SHRUI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000060240000ULL,
+ 0x3012000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1sub", TILEGX_OPC_V1SUB, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051c80000ULL,
+ 0x2890000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v1subuc", TILEGX_OPC_V1SUBUC, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051c40000ULL,
+ 0x288e000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2add", TILEGX_OPC_V2ADD, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051d00000ULL,
+ 0x2894000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2addi", TILEGX_OPC_V2ADDI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00000ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000040e00000ULL,
+ 0x1938000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2addsc", TILEGX_OPC_V2ADDSC, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051cc0000ULL,
+ 0x2892000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2adiffs", TILEGX_OPC_V2ADIFFS, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051d40000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2avgs", TILEGX_OPC_V2AVGS, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051d80000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2cmpeq", TILEGX_OPC_V2CMPEQ, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051dc0000ULL,
+ 0x2896000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2cmpeqi", TILEGX_OPC_V2CMPEQI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00000ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000040f00000ULL,
+ 0x1940000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2cmples", TILEGX_OPC_V2CMPLES, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051e00000ULL,
+ 0x2898000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2cmpleu", TILEGX_OPC_V2CMPLEU, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051e40000ULL,
+ 0x289a000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2cmplts", TILEGX_OPC_V2CMPLTS, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051e80000ULL,
+ 0x289c000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2cmpltsi", TILEGX_OPC_V2CMPLTSI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00000ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000041000000ULL,
+ 0x1948000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2cmpltu", TILEGX_OPC_V2CMPLTU, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051ec0000ULL,
+ 0x289e000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2cmpltui", TILEGX_OPC_V2CMPLTUI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00000ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000041100000ULL,
+ 0x1950000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2cmpne", TILEGX_OPC_V2CMPNE, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051f00000ULL,
+ 0x28a0000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2dotp", TILEGX_OPC_V2DOTP, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051f80000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2dotpa", TILEGX_OPC_V2DOTPA, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051f40000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2int_h", TILEGX_OPC_V2INT_H, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000051fc0000ULL,
+ 0x28a2000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2int_l", TILEGX_OPC_V2INT_L, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052000000ULL,
+ 0x28a4000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2maxs", TILEGX_OPC_V2MAXS, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052040000ULL,
+ 0x28a6000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2maxsi", TILEGX_OPC_V2MAXSI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00000ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000041200000ULL,
+ 0x1958000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2mins", TILEGX_OPC_V2MINS, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052080000ULL,
+ 0x28a8000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2minsi", TILEGX_OPC_V2MINSI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00000ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000041300000ULL,
+ 0x1960000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2mnz", TILEGX_OPC_V2MNZ, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000520c0000ULL,
+ 0x28aa000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2mulfsc", TILEGX_OPC_V2MULFSC, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052100000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2muls", TILEGX_OPC_V2MULS, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052140000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2mults", TILEGX_OPC_V2MULTS, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052180000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2mz", TILEGX_OPC_V2MZ, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000521c0000ULL,
+ 0x28ac000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2packh", TILEGX_OPC_V2PACKH, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052200000ULL,
+ 0x28ae000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2packl", TILEGX_OPC_V2PACKL, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052240000ULL,
+ 0x28b0000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2packuc", TILEGX_OPC_V2PACKUC, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052280000ULL,
+ 0x28b2000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2sadas", TILEGX_OPC_V2SADAS, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000522c0000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2sadau", TILEGX_OPC_V2SADAU, 0x1, 3, TREG_ZERO, 1,
+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052300000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2sads", TILEGX_OPC_V2SADS, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052340000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2sadu", TILEGX_OPC_V2SADU, 0x1, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052380000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2shl", TILEGX_OPC_V2SHL, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052400000ULL,
+ 0x28b6000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2shli", TILEGX_OPC_V2SHLI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000060280000ULL,
+ 0x3014000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2shlsc", TILEGX_OPC_V2SHLSC, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000523c0000ULL,
+ 0x28b4000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2shrs", TILEGX_OPC_V2SHRS, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052440000ULL,
+ 0x28b8000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2shrsi", TILEGX_OPC_V2SHRSI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000602c0000ULL,
+ 0x3016000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2shru", TILEGX_OPC_V2SHRU, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052480000ULL,
+ 0x28ba000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2shrui", TILEGX_OPC_V2SHRUI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000060300000ULL,
+ 0x3018000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2sub", TILEGX_OPC_V2SUB, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052500000ULL,
+ 0x28be000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v2subsc", TILEGX_OPC_V2SUBSC, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000524c0000ULL,
+ 0x28bc000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v4add", TILEGX_OPC_V4ADD, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052580000ULL,
+ 0x28c2000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v4addsc", TILEGX_OPC_V4ADDSC, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052540000ULL,
+ 0x28c0000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v4int_h", TILEGX_OPC_V4INT_H, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000525c0000ULL,
+ 0x28c4000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v4int_l", TILEGX_OPC_V4INT_L, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052600000ULL,
+ 0x28c6000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v4packsc", TILEGX_OPC_V4PACKSC, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052640000ULL,
+ 0x28c8000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v4shl", TILEGX_OPC_V4SHL, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000526c0000ULL,
+ 0x28cc000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v4shlsc", TILEGX_OPC_V4SHLSC, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052680000ULL,
+ 0x28ca000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v4shrs", TILEGX_OPC_V4SHRS, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052700000ULL,
+ 0x28ce000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v4shru", TILEGX_OPC_V4SHRU, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052740000ULL,
+ 0x28d0000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v4sub", TILEGX_OPC_V4SUB, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x00000000527c0000ULL,
+ 0x28d4000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "v4subsc", TILEGX_OPC_V4SUBSC, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052780000ULL,
+ 0x28d2000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "wh64", TILEGX_OPC_WH64, 0x2, 1, TREG_ZERO, 1,
+ { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0ULL,
+ 0xfffff80000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ -1ULL,
+ 0x286b300000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "xor", TILEGX_OPC_XOR, 0xf, 3, TREG_ZERO, 1,
+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ffc0000ULL,
+ 0xfffe000000000000ULL,
+ 0x00000000780c0000ULL,
+ 0x3c06000000000000ULL,
+ 0ULL
+ },
+ {
+ 0x0000000052800000ULL,
+ 0x28d6000000000000ULL,
+ 0x00000000500c0000ULL,
+ 0x2c06000000000000ULL,
+ -1ULL
+ }
+#endif
+ },
+ { "xori", TILEGX_OPC_XORI, 0x3, 3, TREG_ZERO, 1,
+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },
+#ifndef DISASM_ONLY
+ {
+ 0xc00000007ff00000ULL,
+ 0xfff8000000000000ULL,
+ 0ULL,
+ 0ULL,
+ 0ULL
+ },
+ {
+ 0x0000000041400000ULL,
+ 0x1968000000000000ULL,
+ -1ULL,
+ -1ULL,
+ -1ULL
+ }
+#endif
+ },
+ { NULL, TILEGX_OPC_NONE, 0, 0, TREG_ZERO, 0, { { 0, } },
+#ifndef DISASM_ONLY
+ { 0, }, { 0, }
+#endif
+ }
+};
+
+#define BITFIELD(start, size) ((start) | (((1 << (size)) - 1) << 6))
+#define CHILD(array_index) (TILEGX_OPC_NONE + (array_index))
+
+static const unsigned short decode_X0_fsm[936] =
+{
+ BITFIELD(22, 9) /* index 0 */,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_BFEXTS,
+ TILEGX_OPC_BFEXTS, TILEGX_OPC_BFEXTS, TILEGX_OPC_BFEXTS, TILEGX_OPC_BFEXTU,
+ TILEGX_OPC_BFEXTU, TILEGX_OPC_BFEXTU, TILEGX_OPC_BFEXTU, TILEGX_OPC_BFINS,
+ TILEGX_OPC_BFINS, TILEGX_OPC_BFINS, TILEGX_OPC_BFINS, TILEGX_OPC_MM,
+ TILEGX_OPC_MM, TILEGX_OPC_MM, TILEGX_OPC_MM, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(528), CHILD(578),
+ CHILD(583), CHILD(588), CHILD(593), CHILD(598), TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, CHILD(603), CHILD(620), CHILD(637), CHILD(654), CHILD(671),
+ CHILD(703), CHILD(797), CHILD(814), CHILD(831), CHILD(848), CHILD(865),
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, CHILD(889), TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),
+ CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),
+ CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),
+ CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),
+ CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),
+ CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),
+ CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),
+ CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),
+ CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),
+ CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),
+ CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),
+ BITFIELD(6, 2) /* index 513 */,
+ TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(518),
+ BITFIELD(8, 2) /* index 518 */,
+ TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(523),
+ BITFIELD(10, 2) /* index 523 */,
+ TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_MOVELI,
+ BITFIELD(20, 2) /* index 528 */,
+ TILEGX_OPC_NONE, CHILD(533), TILEGX_OPC_ADDXI, CHILD(548),
+ BITFIELD(6, 2) /* index 533 */,
+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(538),
+ BITFIELD(8, 2) /* index 538 */,
+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(543),
+ BITFIELD(10, 2) /* index 543 */,
+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI,
+ BITFIELD(0, 2) /* index 548 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(553),
+ BITFIELD(2, 2) /* index 553 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(558),
+ BITFIELD(4, 2) /* index 558 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(563),
+ BITFIELD(6, 2) /* index 563 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(568),
+ BITFIELD(8, 2) /* index 568 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(573),
+ BITFIELD(10, 2) /* index 573 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO,
+ BITFIELD(20, 2) /* index 578 */,
+ TILEGX_OPC_CMPEQI, TILEGX_OPC_CMPLTSI, TILEGX_OPC_CMPLTUI, TILEGX_OPC_ORI,
+ BITFIELD(20, 2) /* index 583 */,
+ TILEGX_OPC_V1ADDI, TILEGX_OPC_V1CMPEQI, TILEGX_OPC_V1CMPLTSI,
+ TILEGX_OPC_V1CMPLTUI,
+ BITFIELD(20, 2) /* index 588 */,
+ TILEGX_OPC_V1MAXUI, TILEGX_OPC_V1MINUI, TILEGX_OPC_V2ADDI,
+ TILEGX_OPC_V2CMPEQI,
+ BITFIELD(20, 2) /* index 593 */,
+ TILEGX_OPC_V2CMPLTSI, TILEGX_OPC_V2CMPLTUI, TILEGX_OPC_V2MAXSI,
+ TILEGX_OPC_V2MINSI,
+ BITFIELD(20, 2) /* index 598 */,
+ TILEGX_OPC_XORI, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ BITFIELD(18, 4) /* index 603 */,
+ TILEGX_OPC_NONE, TILEGX_OPC_ADDXSC, TILEGX_OPC_ADDX, TILEGX_OPC_ADD,
+ TILEGX_OPC_AND, TILEGX_OPC_CMOVEQZ, TILEGX_OPC_CMOVNEZ, TILEGX_OPC_CMPEQ,
+ TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU,
+ TILEGX_OPC_CMPNE, TILEGX_OPC_CMULAF, TILEGX_OPC_CMULA, TILEGX_OPC_CMULFR,
+ BITFIELD(18, 4) /* index 620 */,
+ TILEGX_OPC_CMULF, TILEGX_OPC_CMULHR, TILEGX_OPC_CMULH, TILEGX_OPC_CMUL,
+ TILEGX_OPC_CRC32_32, TILEGX_OPC_CRC32_8, TILEGX_OPC_DBLALIGN2,
+ TILEGX_OPC_DBLALIGN4, TILEGX_OPC_DBLALIGN6, TILEGX_OPC_DBLALIGN,
+ TILEGX_OPC_FDOUBLE_ADDSUB, TILEGX_OPC_FDOUBLE_ADD_FLAGS,
+ TILEGX_OPC_FDOUBLE_MUL_FLAGS, TILEGX_OPC_FDOUBLE_PACK1,
+ TILEGX_OPC_FDOUBLE_PACK2, TILEGX_OPC_FDOUBLE_SUB_FLAGS,
+ BITFIELD(18, 4) /* index 637 */,
+ TILEGX_OPC_FDOUBLE_UNPACK_MAX, TILEGX_OPC_FDOUBLE_UNPACK_MIN,
+ TILEGX_OPC_FSINGLE_ADD1, TILEGX_OPC_FSINGLE_ADDSUB2,
+ TILEGX_OPC_FSINGLE_MUL1, TILEGX_OPC_FSINGLE_MUL2, TILEGX_OPC_FSINGLE_PACK2,
+ TILEGX_OPC_FSINGLE_SUB1, TILEGX_OPC_MNZ, TILEGX_OPC_MULAX,
+ TILEGX_OPC_MULA_HS_HS, TILEGX_OPC_MULA_HS_HU, TILEGX_OPC_MULA_HS_LS,
+ TILEGX_OPC_MULA_HS_LU, TILEGX_OPC_MULA_HU_HU, TILEGX_OPC_MULA_HU_LS,
+ BITFIELD(18, 4) /* index 654 */,
+ TILEGX_OPC_MULA_HU_LU, TILEGX_OPC_MULA_LS_LS, TILEGX_OPC_MULA_LS_LU,
+ TILEGX_OPC_MULA_LU_LU, TILEGX_OPC_MULX, TILEGX_OPC_MUL_HS_HS,
+ TILEGX_OPC_MUL_HS_HU, TILEGX_OPC_MUL_HS_LS, TILEGX_OPC_MUL_HS_LU,
+ TILEGX_OPC_MUL_HU_HU, TILEGX_OPC_MUL_HU_LS, TILEGX_OPC_MUL_HU_LU,
+ TILEGX_OPC_MUL_LS_LS, TILEGX_OPC_MUL_LS_LU, TILEGX_OPC_MUL_LU_LU,
+ TILEGX_OPC_MZ,
+ BITFIELD(18, 4) /* index 671 */,
+ TILEGX_OPC_NOR, CHILD(688), TILEGX_OPC_ROTL, TILEGX_OPC_SHL1ADDX,
+ TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADDX, TILEGX_OPC_SHL2ADD,
+ TILEGX_OPC_SHL3ADDX, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHLX, TILEGX_OPC_SHL,
+ TILEGX_OPC_SHRS, TILEGX_OPC_SHRUX, TILEGX_OPC_SHRU, TILEGX_OPC_SHUFFLEBYTES,
+ TILEGX_OPC_SUBXSC,
+ BITFIELD(12, 2) /* index 688 */,
+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(693),
+ BITFIELD(14, 2) /* index 693 */,
+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(698),
+ BITFIELD(16, 2) /* index 698 */,
+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE,
+ BITFIELD(18, 4) /* index 703 */,
+ TILEGX_OPC_SUBX, TILEGX_OPC_SUB, CHILD(720), TILEGX_OPC_V1ADDUC,
+ TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADIFFU, TILEGX_OPC_V1AVGU,
+ TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLEU,
+ TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPNE,
+ TILEGX_OPC_V1DDOTPUSA, TILEGX_OPC_V1DDOTPUS, TILEGX_OPC_V1DOTPA,
+ BITFIELD(12, 4) /* index 720 */,
+ TILEGX_OPC_NONE, CHILD(737), CHILD(742), CHILD(747), CHILD(752), CHILD(757),
+ CHILD(762), CHILD(767), CHILD(772), CHILD(777), CHILD(782), CHILD(787),
+ CHILD(792), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ BITFIELD(16, 2) /* index 737 */,
+ TILEGX_OPC_CLZ, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ BITFIELD(16, 2) /* index 742 */,
+ TILEGX_OPC_CTZ, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ BITFIELD(16, 2) /* index 747 */,
+ TILEGX_OPC_FNOP, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ BITFIELD(16, 2) /* index 752 */,
+ TILEGX_OPC_FSINGLE_PACK1, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ BITFIELD(16, 2) /* index 757 */,
+ TILEGX_OPC_NOP, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ BITFIELD(16, 2) /* index 762 */,
+ TILEGX_OPC_PCNT, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ BITFIELD(16, 2) /* index 767 */,
+ TILEGX_OPC_REVBITS, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ BITFIELD(16, 2) /* index 772 */,
+ TILEGX_OPC_REVBYTES, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ BITFIELD(16, 2) /* index 777 */,
+ TILEGX_OPC_TBLIDXB0, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ BITFIELD(16, 2) /* index 782 */,
+ TILEGX_OPC_TBLIDXB1, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ BITFIELD(16, 2) /* index 787 */,
+ TILEGX_OPC_TBLIDXB2, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ BITFIELD(16, 2) /* index 792 */,
+ TILEGX_OPC_TBLIDXB3, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ BITFIELD(18, 4) /* index 797 */,
+ TILEGX_OPC_V1DOTPUSA, TILEGX_OPC_V1DOTPUS, TILEGX_OPC_V1DOTP,
+ TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1MAXU,
+ TILEGX_OPC_V1MINU, TILEGX_OPC_V1MNZ, TILEGX_OPC_V1MULTU, TILEGX_OPC_V1MULUS,
+ TILEGX_OPC_V1MULU, TILEGX_OPC_V1MZ, TILEGX_OPC_V1SADAU, TILEGX_OPC_V1SADU,
+ TILEGX_OPC_V1SHL, TILEGX_OPC_V1SHRS,
+ BITFIELD(18, 4) /* index 814 */,
+ TILEGX_OPC_V1SHRU, TILEGX_OPC_V1SUBUC, TILEGX_OPC_V1SUB, TILEGX_OPC_V2ADDSC,
+ TILEGX_OPC_V2ADD, TILEGX_OPC_V2ADIFFS, TILEGX_OPC_V2AVGS,
+ TILEGX_OPC_V2CMPEQ, TILEGX_OPC_V2CMPLES, TILEGX_OPC_V2CMPLEU,
+ TILEGX_OPC_V2CMPLTS, TILEGX_OPC_V2CMPLTU, TILEGX_OPC_V2CMPNE,
+ TILEGX_OPC_V2DOTPA, TILEGX_OPC_V2DOTP, TILEGX_OPC_V2INT_H,
+ BITFIELD(18, 4) /* index 831 */,
+ TILEGX_OPC_V2INT_L, TILEGX_OPC_V2MAXS, TILEGX_OPC_V2MINS, TILEGX_OPC_V2MNZ,
+ TILEGX_OPC_V2MULFSC, TILEGX_OPC_V2MULS, TILEGX_OPC_V2MULTS, TILEGX_OPC_V2MZ,
+ TILEGX_OPC_V2PACKH, TILEGX_OPC_V2PACKL, TILEGX_OPC_V2PACKUC,
+ TILEGX_OPC_V2SADAS, TILEGX_OPC_V2SADAU, TILEGX_OPC_V2SADS,
+ TILEGX_OPC_V2SADU, TILEGX_OPC_V2SHLSC,
+ BITFIELD(18, 4) /* index 848 */,
+ TILEGX_OPC_V2SHL, TILEGX_OPC_V2SHRS, TILEGX_OPC_V2SHRU, TILEGX_OPC_V2SUBSC,
+ TILEGX_OPC_V2SUB, TILEGX_OPC_V4ADDSC, TILEGX_OPC_V4ADD, TILEGX_OPC_V4INT_H,
+ TILEGX_OPC_V4INT_L, TILEGX_OPC_V4PACKSC, TILEGX_OPC_V4SHLSC,
+ TILEGX_OPC_V4SHL, TILEGX_OPC_V4SHRS, TILEGX_OPC_V4SHRU, TILEGX_OPC_V4SUBSC,
+ TILEGX_OPC_V4SUB,
+ BITFIELD(18, 3) /* index 865 */,
+ CHILD(874), CHILD(877), CHILD(880), CHILD(883), CHILD(886), TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ BITFIELD(21, 1) /* index 874 */,
+ TILEGX_OPC_XOR, TILEGX_OPC_NONE,
+ BITFIELD(21, 1) /* index 877 */,
+ TILEGX_OPC_V1DDOTPUA, TILEGX_OPC_NONE,
+ BITFIELD(21, 1) /* index 880 */,
+ TILEGX_OPC_V1DDOTPU, TILEGX_OPC_NONE,
+ BITFIELD(21, 1) /* index 883 */,
+ TILEGX_OPC_V1DOTPUA, TILEGX_OPC_NONE,
+ BITFIELD(21, 1) /* index 886 */,
+ TILEGX_OPC_V1DOTPU, TILEGX_OPC_NONE,
+ BITFIELD(18, 4) /* index 889 */,
+ TILEGX_OPC_NONE, TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHLXI,
+ TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI, TILEGX_OPC_SHRUXI, TILEGX_OPC_V1SHLI,
+ TILEGX_OPC_V1SHRSI, TILEGX_OPC_V1SHRUI, TILEGX_OPC_V2SHLI,
+ TILEGX_OPC_V2SHRSI, TILEGX_OPC_V2SHRUI, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE,
+ BITFIELD(0, 2) /* index 906 */,
+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,
+ CHILD(911),
+ BITFIELD(2, 2) /* index 911 */,
+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,
+ CHILD(916),
+ BITFIELD(4, 2) /* index 916 */,
+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,
+ CHILD(921),
+ BITFIELD(6, 2) /* index 921 */,
+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,
+ CHILD(926),
+ BITFIELD(8, 2) /* index 926 */,
+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,
+ CHILD(931),
+ BITFIELD(10, 2) /* index 931 */,
+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,
+ TILEGX_OPC_INFOL,
+};
+
+static const unsigned short decode_X1_fsm[1266] =
+{
+ BITFIELD(53, 9) /* index 0 */,
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),
+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,
+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_BEQZT,
+ TILEGX_OPC_BEQZT, TILEGX_OPC_BEQZ, TILEGX_OPC_BEQZ, TILEGX_OPC_BGEZT,
+ TILEGX_OPC_BGEZT, TILEGX_OPC_BGEZ, TILEGX_OPC_BGEZ, TILEGX_OPC_BGTZT,
+ TILEGX_OPC_BGTZT, TILEGX_OPC_BGTZ, TILEGX_OPC_BGTZ, TILEGX_OPC_BLBCT,
+ TILEGX_OPC_BLBCT, TILEGX_OPC_BLBC, TILEGX_OPC_BLBC, TILEGX_OPC_BLBST,
+ TILEGX_OPC_BLBST, TILEGX_OPC_BLBS, TILEGX_OPC_BLBS, TILEGX_OPC_BLEZT,
+ TILEGX_OPC_BLEZT, TILEGX_OPC_BLEZ, TILEGX_OPC_BLEZ, TILEGX_OPC_BLTZT,
+ TILEGX_OPC_BLTZT, TILEGX_OPC_BLTZ, TILEGX_OPC_BLTZ, TILEGX_OPC_BNEZT,
+ TILEGX_OPC_BNEZT, TILEGX_OPC_BNEZ, TILEGX_OPC_BNEZ, CHILD(528), CHILD(578),
+ CHILD(598), CHILD(703), CHILD(723), CHILD(728), CHILD(753), CHILD(758),
+ CHILD(763), CHILD(768), CHILD(773), CHILD(778), TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_JAL,
+ TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL,
+ TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL,
+ TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL,
+ TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL,
+ TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL,
+ TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL,
+ TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL,
+ TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_J, TILEGX_OPC_J,
+ TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J,
+ TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J,
+ TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J,
+ TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J,
+ TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J,
+ TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J,
+ CHILD(783), CHILD(800), CHILD(832), CHILD(849), CHILD(1168), CHILD(1185),
+ CHILD(1202), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(1219), TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(1236), CHILD(1236), CHILD(1236),
+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),
+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),
+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),
+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),
+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),
+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),
+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),
+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),
+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),
+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),
+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),
+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),
+ CHILD(1236),
+ BITFIELD(37, 2) /* index 513 */,
+ TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(518),
+ BITFIELD(39, 2) /* index 518 */,
+ TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(523),
+ BITFIELD(41, 2) /* index 523 */,
+ TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_MOVELI,
+ BITFIELD(51, 2) /* index 528 */,
+ TILEGX_OPC_NONE, CHILD(533), TILEGX_OPC_ADDXI, CHILD(548),
+ BITFIELD(37, 2) /* index 533 */,
+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(538),
+ BITFIELD(39, 2) /* index 538 */,
+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(543),
+ BITFIELD(41, 2) /* index 543 */,
+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI,
+ BITFIELD(31, 2) /* index 548 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(553),
+ BITFIELD(33, 2) /* index 553 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(558),
+ BITFIELD(35, 2) /* index 558 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(563),
+ BITFIELD(37, 2) /* index 563 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(568),
+ BITFIELD(39, 2) /* index 568 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(573),
+ BITFIELD(41, 2) /* index 573 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO,
+ BITFIELD(51, 2) /* index 578 */,
+ TILEGX_OPC_CMPEQI, TILEGX_OPC_CMPLTSI, TILEGX_OPC_CMPLTUI, CHILD(583),
+ BITFIELD(31, 2) /* index 583 */,
+ TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, CHILD(588),
+ BITFIELD(33, 2) /* index 588 */,
+ TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, CHILD(593),
+ BITFIELD(35, 2) /* index 593 */,
+ TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD,
+ TILEGX_OPC_PREFETCH_ADD_L1_FAULT,
+ BITFIELD(51, 2) /* index 598 */,
+ CHILD(603), CHILD(618), CHILD(633), CHILD(648),
+ BITFIELD(31, 2) /* index 603 */,
+ TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, CHILD(608),
+ BITFIELD(33, 2) /* index 608 */,
+ TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, CHILD(613),
+ BITFIELD(35, 2) /* index 613 */,
+ TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD,
+ TILEGX_OPC_PREFETCH_ADD_L1,
+ BITFIELD(31, 2) /* index 618 */,
+ TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, CHILD(623),
+ BITFIELD(33, 2) /* index 623 */,
+ TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, CHILD(628),
+ BITFIELD(35, 2) /* index 628 */,
+ TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD,
+ TILEGX_OPC_PREFETCH_ADD_L2_FAULT,
+ BITFIELD(31, 2) /* index 633 */,
+ TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, CHILD(638),
+ BITFIELD(33, 2) /* index 638 */,
+ TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, CHILD(643),
+ BITFIELD(35, 2) /* index 643 */,
+ TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD,
+ TILEGX_OPC_PREFETCH_ADD_L2,
+ BITFIELD(31, 2) /* index 648 */,
+ CHILD(653), CHILD(653), CHILD(653), CHILD(673),
+ BITFIELD(43, 2) /* index 653 */,
+ CHILD(658), TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD,
+ BITFIELD(45, 2) /* index 658 */,
+ CHILD(663), TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD,
+ BITFIELD(47, 2) /* index 663 */,
+ CHILD(668), TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD,
+ BITFIELD(49, 2) /* index 668 */,
+ TILEGX_OPC_LD4S_TLS, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD,
+ TILEGX_OPC_LD4S_ADD,
+ BITFIELD(33, 2) /* index 673 */,
+ CHILD(653), CHILD(653), CHILD(653), CHILD(678),
+ BITFIELD(35, 2) /* index 678 */,
+ CHILD(653), CHILD(653), CHILD(653), CHILD(683),
+ BITFIELD(43, 2) /* index 683 */,
+ CHILD(688), TILEGX_OPC_PREFETCH_ADD_L3_FAULT,
+ TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_ADD_L3_FAULT,
+ BITFIELD(45, 2) /* index 688 */,
+ CHILD(693), TILEGX_OPC_PREFETCH_ADD_L3_FAULT,
+ TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_ADD_L3_FAULT,
+ BITFIELD(47, 2) /* index 693 */,
+ CHILD(698), TILEGX_OPC_PREFETCH_ADD_L3_FAULT,
+ TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_ADD_L3_FAULT,
+ BITFIELD(49, 2) /* index 698 */,
+ TILEGX_OPC_LD4S_TLS, TILEGX_OPC_PREFETCH_ADD_L3_FAULT,
+ TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_ADD_L3_FAULT,
+ BITFIELD(51, 2) /* index 703 */,
+ CHILD(708), TILEGX_OPC_LDNT1S_ADD, TILEGX_OPC_LDNT1U_ADD,
+ TILEGX_OPC_LDNT2S_ADD,
+ BITFIELD(31, 2) /* index 708 */,
+ TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, CHILD(713),
+ BITFIELD(33, 2) /* index 713 */,
+ TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, CHILD(718),
+ BITFIELD(35, 2) /* index 718 */,
+ TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD,
+ TILEGX_OPC_PREFETCH_ADD_L3,
+ BITFIELD(51, 2) /* index 723 */,
+ TILEGX_OPC_LDNT2U_ADD, TILEGX_OPC_LDNT4S_ADD, TILEGX_OPC_LDNT4U_ADD,
+ TILEGX_OPC_LDNT_ADD,
+ BITFIELD(51, 2) /* index 728 */,
+ CHILD(733), TILEGX_OPC_LDNA_ADD, TILEGX_OPC_MFSPR, TILEGX_OPC_MTSPR,
+ BITFIELD(43, 2) /* index 733 */,
+ CHILD(738), TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD,
+ BITFIELD(45, 2) /* index 738 */,
+ CHILD(743), TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD,
+ BITFIELD(47, 2) /* index 743 */,
+ CHILD(748), TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD,
+ BITFIELD(49, 2) /* index 748 */,
+ TILEGX_OPC_LD_TLS, TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD,
+ BITFIELD(51, 2) /* index 753 */,
+ TILEGX_OPC_ORI, TILEGX_OPC_ST1_ADD, TILEGX_OPC_ST2_ADD, TILEGX_OPC_ST4_ADD,
+ BITFIELD(51, 2) /* index 758 */,
+ TILEGX_OPC_STNT1_ADD, TILEGX_OPC_STNT2_ADD, TILEGX_OPC_STNT4_ADD,
+ TILEGX_OPC_STNT_ADD,
+ BITFIELD(51, 2) /* index 763 */,
+ TILEGX_OPC_ST_ADD, TILEGX_OPC_V1ADDI, TILEGX_OPC_V1CMPEQI,
+ TILEGX_OPC_V1CMPLTSI,
+ BITFIELD(51, 2) /* index 768 */,
+ TILEGX_OPC_V1CMPLTUI, TILEGX_OPC_V1MAXUI, TILEGX_OPC_V1MINUI,
+ TILEGX_OPC_V2ADDI,
+ BITFIELD(51, 2) /* index 773 */,
+ TILEGX_OPC_V2CMPEQI, TILEGX_OPC_V2CMPLTSI, TILEGX_OPC_V2CMPLTUI,
+ TILEGX_OPC_V2MAXSI,
+ BITFIELD(51, 2) /* index 778 */,
+ TILEGX_OPC_V2MINSI, TILEGX_OPC_XORI, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ BITFIELD(49, 4) /* index 783 */,
+ TILEGX_OPC_NONE, TILEGX_OPC_ADDXSC, TILEGX_OPC_ADDX, TILEGX_OPC_ADD,
+ TILEGX_OPC_AND, TILEGX_OPC_CMPEQ, TILEGX_OPC_CMPEXCH4, TILEGX_OPC_CMPEXCH,
+ TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU,
+ TILEGX_OPC_CMPNE, TILEGX_OPC_DBLALIGN2, TILEGX_OPC_DBLALIGN4,
+ TILEGX_OPC_DBLALIGN6,
+ BITFIELD(49, 4) /* index 800 */,
+ TILEGX_OPC_EXCH4, TILEGX_OPC_EXCH, TILEGX_OPC_FETCHADD4,
+ TILEGX_OPC_FETCHADDGEZ4, TILEGX_OPC_FETCHADDGEZ, TILEGX_OPC_FETCHADD,
+ TILEGX_OPC_FETCHAND4, TILEGX_OPC_FETCHAND, TILEGX_OPC_FETCHOR4,
+ TILEGX_OPC_FETCHOR, TILEGX_OPC_MNZ, TILEGX_OPC_MZ, TILEGX_OPC_NOR,
+ CHILD(817), TILEGX_OPC_ROTL, TILEGX_OPC_SHL1ADDX,
+ BITFIELD(43, 2) /* index 817 */,
+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(822),
+ BITFIELD(45, 2) /* index 822 */,
+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(827),
+ BITFIELD(47, 2) /* index 827 */,
+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE,
+ BITFIELD(49, 4) /* index 832 */,
+ TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADDX, TILEGX_OPC_SHL2ADD,
+ TILEGX_OPC_SHL3ADDX, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHLX, TILEGX_OPC_SHL,
+ TILEGX_OPC_SHRS, TILEGX_OPC_SHRUX, TILEGX_OPC_SHRU, TILEGX_OPC_ST1,
+ TILEGX_OPC_ST2, TILEGX_OPC_ST4, TILEGX_OPC_STNT1, TILEGX_OPC_STNT2,
+ TILEGX_OPC_STNT4,
+ BITFIELD(46, 7) /* index 849 */,
+ TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT,
+ TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT,
+ TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST,
+ TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_SUBXSC,
+ TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC,
+ TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBX,
+ TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX,
+ TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUB,
+ TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB,
+ TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB, CHILD(978), CHILD(987),
+ CHILD(1066), CHILD(1150), CHILD(1159), TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC,
+ TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC,
+ TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD,
+ TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD,
+ TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ,
+ TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ,
+ TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ,
+ TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES,
+ TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES,
+ TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLEU,
+ TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU,
+ TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU,
+ TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS,
+ TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS,
+ TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS,
+ TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU,
+ TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU,
+ TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPNE,
+ TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE,
+ TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE,
+ TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H,
+ TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H,
+ TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H,
+ TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L,
+ TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L,
+ TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L,
+ BITFIELD(43, 3) /* index 978 */,
+ TILEGX_OPC_NONE, TILEGX_OPC_DRAIN, TILEGX_OPC_DTLBPR, TILEGX_OPC_FINV,
+ TILEGX_OPC_FLUSHWB, TILEGX_OPC_FLUSH, TILEGX_OPC_FNOP, TILEGX_OPC_ICOH,
+ BITFIELD(43, 3) /* index 987 */,
+ CHILD(996), TILEGX_OPC_INV, TILEGX_OPC_IRET, TILEGX_OPC_JALRP,
+ TILEGX_OPC_JALR, TILEGX_OPC_JRP, TILEGX_OPC_JR, CHILD(1051),
+ BITFIELD(31, 2) /* index 996 */,
+ CHILD(1001), CHILD(1026), TILEGX_OPC_ILL, TILEGX_OPC_ILL,
+ BITFIELD(33, 2) /* index 1001 */,
+ TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_ILL, CHILD(1006),
+ BITFIELD(35, 2) /* index 1006 */,
+ TILEGX_OPC_ILL, CHILD(1011), TILEGX_OPC_ILL, TILEGX_OPC_ILL,
+ BITFIELD(37, 2) /* index 1011 */,
+ TILEGX_OPC_ILL, CHILD(1016), TILEGX_OPC_ILL, TILEGX_OPC_ILL,
+ BITFIELD(39, 2) /* index 1016 */,
+ TILEGX_OPC_ILL, CHILD(1021), TILEGX_OPC_ILL, TILEGX_OPC_ILL,
+ BITFIELD(41, 2) /* index 1021 */,
+ TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_BPT, TILEGX_OPC_ILL,
+ BITFIELD(33, 2) /* index 1026 */,
+ TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_ILL, CHILD(1031),
+ BITFIELD(35, 2) /* index 1031 */,
+ TILEGX_OPC_ILL, CHILD(1036), TILEGX_OPC_ILL, TILEGX_OPC_ILL,
+ BITFIELD(37, 2) /* index 1036 */,
+ TILEGX_OPC_ILL, CHILD(1041), TILEGX_OPC_ILL, TILEGX_OPC_ILL,
+ BITFIELD(39, 2) /* index 1041 */,
+ TILEGX_OPC_ILL, CHILD(1046), TILEGX_OPC_ILL, TILEGX_OPC_ILL,
+ BITFIELD(41, 2) /* index 1046 */,
+ TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_RAISE, TILEGX_OPC_ILL,
+ BITFIELD(31, 2) /* index 1051 */,
+ TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, CHILD(1056),
+ BITFIELD(33, 2) /* index 1056 */,
+ TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, CHILD(1061),
+ BITFIELD(35, 2) /* index 1061 */,
+ TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S,
+ TILEGX_OPC_PREFETCH_L1_FAULT,
+ BITFIELD(43, 3) /* index 1066 */,
+ CHILD(1075), CHILD(1090), CHILD(1105), CHILD(1120), CHILD(1135),
+ TILEGX_OPC_LDNA, TILEGX_OPC_LDNT1S, TILEGX_OPC_LDNT1U,
+ BITFIELD(31, 2) /* index 1075 */,
+ TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, CHILD(1080),
+ BITFIELD(33, 2) /* index 1080 */,
+ TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, CHILD(1085),
+ BITFIELD(35, 2) /* index 1085 */,
+ TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_PREFETCH,
+ BITFIELD(31, 2) /* index 1090 */,
+ TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, CHILD(1095),
+ BITFIELD(33, 2) /* index 1095 */,
+ TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, CHILD(1100),
+ BITFIELD(35, 2) /* index 1100 */,
+ TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S,
+ TILEGX_OPC_PREFETCH_L2_FAULT,
+ BITFIELD(31, 2) /* index 1105 */,
+ TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, CHILD(1110),
+ BITFIELD(33, 2) /* index 1110 */,
+ TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, CHILD(1115),
+ BITFIELD(35, 2) /* index 1115 */,
+ TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_PREFETCH_L2,
+ BITFIELD(31, 2) /* index 1120 */,
+ TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(1125),
+ BITFIELD(33, 2) /* index 1125 */,
+ TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(1130),
+ BITFIELD(35, 2) /* index 1130 */,
+ TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S,
+ TILEGX_OPC_PREFETCH_L3_FAULT,
+ BITFIELD(31, 2) /* index 1135 */,
+ TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(1140),
+ BITFIELD(33, 2) /* index 1140 */,
+ TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(1145),
+ BITFIELD(35, 2) /* index 1145 */,
+ TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_PREFETCH_L3,
+ BITFIELD(43, 3) /* index 1150 */,
+ TILEGX_OPC_LDNT2S, TILEGX_OPC_LDNT2U, TILEGX_OPC_LDNT4S, TILEGX_OPC_LDNT4U,
+ TILEGX_OPC_LDNT, TILEGX_OPC_LD, TILEGX_OPC_LNK, TILEGX_OPC_MF,
+ BITFIELD(43, 3) /* index 1159 */,
+ TILEGX_OPC_NAP, TILEGX_OPC_NOP, TILEGX_OPC_SWINT0, TILEGX_OPC_SWINT1,
+ TILEGX_OPC_SWINT2, TILEGX_OPC_SWINT3, TILEGX_OPC_WH64, TILEGX_OPC_NONE,
+ BITFIELD(49, 4) /* index 1168 */,
+ TILEGX_OPC_V1MAXU, TILEGX_OPC_V1MINU, TILEGX_OPC_V1MNZ, TILEGX_OPC_V1MZ,
+ TILEGX_OPC_V1SHL, TILEGX_OPC_V1SHRS, TILEGX_OPC_V1SHRU, TILEGX_OPC_V1SUBUC,
+ TILEGX_OPC_V1SUB, TILEGX_OPC_V2ADDSC, TILEGX_OPC_V2ADD, TILEGX_OPC_V2CMPEQ,
+ TILEGX_OPC_V2CMPLES, TILEGX_OPC_V2CMPLEU, TILEGX_OPC_V2CMPLTS,
+ TILEGX_OPC_V2CMPLTU,
+ BITFIELD(49, 4) /* index 1185 */,
+ TILEGX_OPC_V2CMPNE, TILEGX_OPC_V2INT_H, TILEGX_OPC_V2INT_L,
+ TILEGX_OPC_V2MAXS, TILEGX_OPC_V2MINS, TILEGX_OPC_V2MNZ, TILEGX_OPC_V2MZ,
+ TILEGX_OPC_V2PACKH, TILEGX_OPC_V2PACKL, TILEGX_OPC_V2PACKUC,
+ TILEGX_OPC_V2SHLSC, TILEGX_OPC_V2SHL, TILEGX_OPC_V2SHRS, TILEGX_OPC_V2SHRU,
+ TILEGX_OPC_V2SUBSC, TILEGX_OPC_V2SUB,
+ BITFIELD(49, 4) /* index 1202 */,
+ TILEGX_OPC_V4ADDSC, TILEGX_OPC_V4ADD, TILEGX_OPC_V4INT_H,
+ TILEGX_OPC_V4INT_L, TILEGX_OPC_V4PACKSC, TILEGX_OPC_V4SHLSC,
+ TILEGX_OPC_V4SHL, TILEGX_OPC_V4SHRS, TILEGX_OPC_V4SHRU, TILEGX_OPC_V4SUBSC,
+ TILEGX_OPC_V4SUB, TILEGX_OPC_XOR, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ BITFIELD(49, 4) /* index 1219 */,
+ TILEGX_OPC_NONE, TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHLXI,
+ TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI, TILEGX_OPC_SHRUXI, TILEGX_OPC_V1SHLI,
+ TILEGX_OPC_V1SHRSI, TILEGX_OPC_V1SHRUI, TILEGX_OPC_V2SHLI,
+ TILEGX_OPC_V2SHRSI, TILEGX_OPC_V2SHRUI, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE,
+ BITFIELD(31, 2) /* index 1236 */,
+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,
+ CHILD(1241),
+ BITFIELD(33, 2) /* index 1241 */,
+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,
+ CHILD(1246),
+ BITFIELD(35, 2) /* index 1246 */,
+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,
+ CHILD(1251),
+ BITFIELD(37, 2) /* index 1251 */,
+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,
+ CHILD(1256),
+ BITFIELD(39, 2) /* index 1256 */,
+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,
+ CHILD(1261),
+ BITFIELD(41, 2) /* index 1261 */,
+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,
+ TILEGX_OPC_INFOL,
+};
+
+static const unsigned short decode_Y0_fsm[178] =
+{
+ BITFIELD(27, 4) /* index 0 */,
+ CHILD(17), TILEGX_OPC_ADDXI, CHILD(32), TILEGX_OPC_CMPEQI,
+ TILEGX_OPC_CMPLTSI, CHILD(62), CHILD(67), CHILD(118), CHILD(123),
+ CHILD(128), CHILD(133), CHILD(153), CHILD(158), CHILD(163), CHILD(168),
+ CHILD(173),
+ BITFIELD(6, 2) /* index 17 */,
+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(22),
+ BITFIELD(8, 2) /* index 22 */,
+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(27),
+ BITFIELD(10, 2) /* index 27 */,
+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI,
+ BITFIELD(0, 2) /* index 32 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(37),
+ BITFIELD(2, 2) /* index 37 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(42),
+ BITFIELD(4, 2) /* index 42 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(47),
+ BITFIELD(6, 2) /* index 47 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(52),
+ BITFIELD(8, 2) /* index 52 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(57),
+ BITFIELD(10, 2) /* index 57 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO,
+ BITFIELD(18, 2) /* index 62 */,
+ TILEGX_OPC_ADDX, TILEGX_OPC_ADD, TILEGX_OPC_SUBX, TILEGX_OPC_SUB,
+ BITFIELD(15, 5) /* index 67 */,
+ TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD,
+ TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD,
+ TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADD,
+ TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD,
+ TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD,
+ TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD,
+ TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD,
+ TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, CHILD(100),
+ CHILD(109), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ BITFIELD(12, 3) /* index 100 */,
+ TILEGX_OPC_NONE, TILEGX_OPC_CLZ, TILEGX_OPC_CTZ, TILEGX_OPC_FNOP,
+ TILEGX_OPC_FSINGLE_PACK1, TILEGX_OPC_NOP, TILEGX_OPC_PCNT,
+ TILEGX_OPC_REVBITS,
+ BITFIELD(12, 3) /* index 109 */,
+ TILEGX_OPC_REVBYTES, TILEGX_OPC_TBLIDXB0, TILEGX_OPC_TBLIDXB1,
+ TILEGX_OPC_TBLIDXB2, TILEGX_OPC_TBLIDXB3, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ TILEGX_OPC_NONE,
+ BITFIELD(18, 2) /* index 118 */,
+ TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU,
+ BITFIELD(18, 2) /* index 123 */,
+ TILEGX_OPC_CMPEQ, TILEGX_OPC_CMPNE, TILEGX_OPC_MULAX, TILEGX_OPC_MULX,
+ BITFIELD(18, 2) /* index 128 */,
+ TILEGX_OPC_CMOVEQZ, TILEGX_OPC_CMOVNEZ, TILEGX_OPC_MNZ, TILEGX_OPC_MZ,
+ BITFIELD(18, 2) /* index 133 */,
+ TILEGX_OPC_AND, TILEGX_OPC_NOR, CHILD(138), TILEGX_OPC_XOR,
+ BITFIELD(12, 2) /* index 138 */,
+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(143),
+ BITFIELD(14, 2) /* index 143 */,
+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(148),
+ BITFIELD(16, 2) /* index 148 */,
+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE,
+ BITFIELD(18, 2) /* index 153 */,
+ TILEGX_OPC_ROTL, TILEGX_OPC_SHL, TILEGX_OPC_SHRS, TILEGX_OPC_SHRU,
+ BITFIELD(18, 2) /* index 158 */,
+ TILEGX_OPC_NONE, TILEGX_OPC_SHL1ADDX, TILEGX_OPC_SHL2ADDX,
+ TILEGX_OPC_SHL3ADDX,
+ BITFIELD(18, 2) /* index 163 */,
+ TILEGX_OPC_MUL_HS_HS, TILEGX_OPC_MUL_HU_HU, TILEGX_OPC_MUL_LS_LS,
+ TILEGX_OPC_MUL_LU_LU,
+ BITFIELD(18, 2) /* index 168 */,
+ TILEGX_OPC_MULA_HS_HS, TILEGX_OPC_MULA_HU_HU, TILEGX_OPC_MULA_LS_LS,
+ TILEGX_OPC_MULA_LU_LU,
+ BITFIELD(18, 2) /* index 173 */,
+ TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI,
+};
+
+static const unsigned short decode_Y1_fsm[167] =
+{
+ BITFIELD(58, 4) /* index 0 */,
+ TILEGX_OPC_NONE, CHILD(17), TILEGX_OPC_ADDXI, CHILD(32), TILEGX_OPC_CMPEQI,
+ TILEGX_OPC_CMPLTSI, CHILD(62), CHILD(67), CHILD(117), CHILD(122),
+ CHILD(127), CHILD(132), CHILD(152), CHILD(157), CHILD(162), TILEGX_OPC_NONE,
+ BITFIELD(37, 2) /* index 17 */,
+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(22),
+ BITFIELD(39, 2) /* index 22 */,
+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(27),
+ BITFIELD(41, 2) /* index 27 */,
+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI,
+ BITFIELD(31, 2) /* index 32 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(37),
+ BITFIELD(33, 2) /* index 37 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(42),
+ BITFIELD(35, 2) /* index 42 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(47),
+ BITFIELD(37, 2) /* index 47 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(52),
+ BITFIELD(39, 2) /* index 52 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(57),
+ BITFIELD(41, 2) /* index 57 */,
+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO,
+ BITFIELD(49, 2) /* index 62 */,
+ TILEGX_OPC_ADDX, TILEGX_OPC_ADD, TILEGX_OPC_SUBX, TILEGX_OPC_SUB,
+ BITFIELD(47, 4) /* index 67 */,
+ TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD,
+ TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD,
+ TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL3ADD,
+ TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, CHILD(84),
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,
+ BITFIELD(43, 3) /* index 84 */,
+ CHILD(93), CHILD(96), CHILD(99), CHILD(102), CHILD(105), CHILD(108),
+ CHILD(111), CHILD(114),
+ BITFIELD(46, 1) /* index 93 */,
+ TILEGX_OPC_NONE, TILEGX_OPC_FNOP,
+ BITFIELD(46, 1) /* index 96 */,
+ TILEGX_OPC_NONE, TILEGX_OPC_ILL,
+ BITFIELD(46, 1) /* index 99 */,
+ TILEGX_OPC_NONE, TILEGX_OPC_JALRP,
+ BITFIELD(46, 1) /* index 102 */,
+ TILEGX_OPC_NONE, TILEGX_OPC_JALR,
+ BITFIELD(46, 1) /* index 105 */,
+ TILEGX_OPC_NONE, TILEGX_OPC_JRP,
+ BITFIELD(46, 1) /* index 108 */,
+ TILEGX_OPC_NONE, TILEGX_OPC_JR,
+ BITFIELD(46, 1) /* index 111 */,
+ TILEGX_OPC_NONE, TILEGX_OPC_LNK,
+ BITFIELD(46, 1) /* index 114 */,
+ TILEGX_OPC_NONE, TILEGX_OPC_NOP,
+ BITFIELD(49, 2) /* index 117 */,
+ TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU,
+ BITFIELD(49, 2) /* index 122 */,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_CMPEQ, TILEGX_OPC_CMPNE,
+ BITFIELD(49, 2) /* index 127 */,
+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_MNZ, TILEGX_OPC_MZ,
+ BITFIELD(49, 2) /* index 132 */,
+ TILEGX_OPC_AND, TILEGX_OPC_NOR, CHILD(137), TILEGX_OPC_XOR,
+ BITFIELD(43, 2) /* index 137 */,
+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(142),
+ BITFIELD(45, 2) /* index 142 */,
+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(147),
+ BITFIELD(47, 2) /* index 147 */,
+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE,
+ BITFIELD(49, 2) /* index 152 */,
+ TILEGX_OPC_ROTL, TILEGX_OPC_SHL, TILEGX_OPC_SHRS, TILEGX_OPC_SHRU,
+ BITFIELD(49, 2) /* index 157 */,
+ TILEGX_OPC_NONE, TILEGX_OPC_SHL1ADDX, TILEGX_OPC_SHL2ADDX,
+ TILEGX_OPC_SHL3ADDX,
+ BITFIELD(49, 2) /* index 162 */,
+ TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI,
+};
+
+static const unsigned short decode_Y2_fsm[118] =
+{
+ BITFIELD(62, 2) /* index 0 */,
+ TILEGX_OPC_NONE, CHILD(5), CHILD(66), CHILD(109),
+ BITFIELD(55, 3) /* index 5 */,
+ CHILD(14), CHILD(14), CHILD(14), CHILD(17), CHILD(40), CHILD(40), CHILD(40),
+ CHILD(43),
+ BITFIELD(26, 1) /* index 14 */,
+ TILEGX_OPC_LD1S, TILEGX_OPC_LD1U,
+ BITFIELD(26, 1) /* index 17 */,
+ CHILD(20), CHILD(30),
+ BITFIELD(51, 2) /* index 20 */,
+ TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, CHILD(25),
+ BITFIELD(53, 2) /* index 25 */,
+ TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S,
+ TILEGX_OPC_PREFETCH_L1_FAULT,
+ BITFIELD(51, 2) /* index 30 */,
+ TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, CHILD(35),
+ BITFIELD(53, 2) /* index 35 */,
+ TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_PREFETCH,
+ BITFIELD(26, 1) /* index 40 */,
+ TILEGX_OPC_LD2S, TILEGX_OPC_LD2U,
+ BITFIELD(26, 1) /* index 43 */,
+ CHILD(46), CHILD(56),
+ BITFIELD(51, 2) /* index 46 */,
+ TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, CHILD(51),
+ BITFIELD(53, 2) /* index 51 */,
+ TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S,
+ TILEGX_OPC_PREFETCH_L2_FAULT,
+ BITFIELD(51, 2) /* index 56 */,
+ TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, CHILD(61),
+ BITFIELD(53, 2) /* index 61 */,
+ TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_PREFETCH_L2,
+ BITFIELD(56, 2) /* index 66 */,
+ CHILD(71), CHILD(74), CHILD(90), CHILD(93),
+ BITFIELD(26, 1) /* index 71 */,
+ TILEGX_OPC_NONE, TILEGX_OPC_LD4S,
+ BITFIELD(26, 1) /* index 74 */,
+ TILEGX_OPC_NONE, CHILD(77),
+ BITFIELD(51, 2) /* index 77 */,
+ TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(82),
+ BITFIELD(53, 2) /* index 82 */,
+ TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(87),
+ BITFIELD(55, 1) /* index 87 */,
+ TILEGX_OPC_LD4S, TILEGX_OPC_PREFETCH_L3_FAULT,
+ BITFIELD(26, 1) /* index 90 */,
+ TILEGX_OPC_LD4U, TILEGX_OPC_LD,
+ BITFIELD(26, 1) /* index 93 */,
+ CHILD(96), TILEGX_OPC_LD,
+ BITFIELD(51, 2) /* index 96 */,
+ TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(101),
+ BITFIELD(53, 2) /* index 101 */,
+ TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(106),
+ BITFIELD(55, 1) /* index 106 */,
+ TILEGX_OPC_LD4U, TILEGX_OPC_PREFETCH_L3,
+ BITFIELD(26, 1) /* index 109 */,
+ CHILD(112), CHILD(115),
+ BITFIELD(57, 1) /* index 112 */,
+ TILEGX_OPC_ST1, TILEGX_OPC_ST4,
+ BITFIELD(57, 1) /* index 115 */,
+ TILEGX_OPC_ST2, TILEGX_OPC_ST,
+};
+
+#undef BITFIELD
+#undef CHILD
+
+const unsigned short * const
+tilegx_bundle_decoder_fsms[TILEGX_NUM_PIPELINE_ENCODINGS] =
+{
+ decode_X0_fsm,
+ decode_X1_fsm,
+ decode_Y0_fsm,
+ decode_Y1_fsm,
+ decode_Y2_fsm
+};
+
+const struct tilegx_operand tilegx_operands[35] =
+{
+ {
+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_X0),
+ 8, 1, 0, 0, 0, 0,
+ create_Imm8_X0, get_Imm8_X0
+ },
+ {
+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_X1),
+ 8, 1, 0, 0, 0, 0,
+ create_Imm8_X1, get_Imm8_X1
+ },
+ {
+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_Y0),
+ 8, 1, 0, 0, 0, 0,
+ create_Imm8_Y0, get_Imm8_Y0
+ },
+ {
+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_Y1),
+ 8, 1, 0, 0, 0, 0,
+ create_Imm8_Y1, get_Imm8_Y1
+ },
+ {
+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM16_X0_HW0_LAST),
+ 16, 1, 0, 0, 0, 0,
+ create_Imm16_X0, get_Imm16_X0
+ },
+ {
+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM16_X1_HW0_LAST),
+ 16, 1, 0, 0, 0, 0,
+ create_Imm16_X1, get_Imm16_X1
+ },
+ {
+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+ 6, 0, 0, 1, 0, 0,
+ create_Dest_X1, get_Dest_X1
+ },
+ {
+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+ 6, 0, 1, 0, 0, 0,
+ create_SrcA_X1, get_SrcA_X1
+ },
+ {
+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+ 6, 0, 0, 1, 0, 0,
+ create_Dest_X0, get_Dest_X0
+ },
+ {
+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+ 6, 0, 1, 0, 0, 0,
+ create_SrcA_X0, get_SrcA_X0
+ },
+ {
+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+ 6, 0, 0, 1, 0, 0,
+ create_Dest_Y0, get_Dest_Y0
+ },
+ {
+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+ 6, 0, 1, 0, 0, 0,
+ create_SrcA_Y0, get_SrcA_Y0
+ },
+ {
+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+ 6, 0, 0, 1, 0, 0,
+ create_Dest_Y1, get_Dest_Y1
+ },
+ {
+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+ 6, 0, 1, 0, 0, 0,
+ create_SrcA_Y1, get_SrcA_Y1
+ },
+ {
+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+ 6, 0, 1, 0, 0, 0,
+ create_SrcA_Y2, get_SrcA_Y2
+ },
+ {
+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+ 6, 0, 1, 1, 0, 0,
+ create_SrcA_X1, get_SrcA_X1
+ },
+ {
+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+ 6, 0, 1, 0, 0, 0,
+ create_SrcB_X0, get_SrcB_X0
+ },
+ {
+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+ 6, 0, 1, 0, 0, 0,
+ create_SrcB_X1, get_SrcB_X1
+ },
+ {
+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+ 6, 0, 1, 0, 0, 0,
+ create_SrcB_Y0, get_SrcB_Y0
+ },
+ {
+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+ 6, 0, 1, 0, 0, 0,
+ create_SrcB_Y1, get_SrcB_Y1
+ },
+ {
+ TILEGX_OP_TYPE_ADDRESS, BFD_RELOC(TILEGX_BROFF_X1),
+ 17, 1, 0, 0, 1, TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,
+ create_BrOff_X1, get_BrOff_X1
+ },
+ {
+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_MMSTART_X0),
+ 6, 0, 0, 0, 0, 0,
+ create_BFStart_X0, get_BFStart_X0
+ },
+ {
+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_MMEND_X0),
+ 6, 0, 0, 0, 0, 0,
+ create_BFEnd_X0, get_BFEnd_X0
+ },
+ {
+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+ 6, 0, 1, 1, 0, 0,
+ create_Dest_X0, get_Dest_X0
+ },
+ {
+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+ 6, 0, 1, 1, 0, 0,
+ create_Dest_Y0, get_Dest_Y0
+ },
+ {
+ TILEGX_OP_TYPE_ADDRESS, BFD_RELOC(TILEGX_JUMPOFF_X1),
+ 27, 1, 0, 0, 1, TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,
+ create_JumpOff_X1, get_JumpOff_X1
+ },
+ {
+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+ 6, 0, 0, 1, 0, 0,
+ create_SrcBDest_Y2, get_SrcBDest_Y2
+ },
+ {
+ TILEGX_OP_TYPE_SPR, BFD_RELOC(TILEGX_MF_IMM14_X1),
+ 14, 0, 0, 0, 0, 0,
+ create_MF_Imm14_X1, get_MF_Imm14_X1
+ },
+ {
+ TILEGX_OP_TYPE_SPR, BFD_RELOC(TILEGX_MT_IMM14_X1),
+ 14, 0, 0, 0, 0, 0,
+ create_MT_Imm14_X1, get_MT_Imm14_X1
+ },
+ {
+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_X0),
+ 6, 0, 0, 0, 0, 0,
+ create_ShAmt_X0, get_ShAmt_X0
+ },
+ {
+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_X1),
+ 6, 0, 0, 0, 0, 0,
+ create_ShAmt_X1, get_ShAmt_X1
+ },
+ {
+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_Y0),
+ 6, 0, 0, 0, 0, 0,
+ create_ShAmt_Y0, get_ShAmt_Y0
+ },
+ {
+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_Y1),
+ 6, 0, 0, 0, 0, 0,
+ create_ShAmt_Y1, get_ShAmt_Y1
+ },
+ {
+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+ 6, 0, 1, 0, 0, 0,
+ create_SrcBDest_Y2, get_SrcBDest_Y2
+ },
+ {
+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_DEST_IMM8_X1),
+ 8, 1, 0, 0, 0, 0,
+ create_Dest_Imm8_X1, get_Dest_Imm8_X1
+ }
+};
+
+/* Given a set of bundle bits and a specific pipe, returns which
+ * instruction the bundle contains in that pipe.
+ */
+const struct tilegx_opcode *
+find_opcode(tilegx_bundle_bits bits, tilegx_pipeline pipe)
+{
+ const unsigned short *table = tilegx_bundle_decoder_fsms[pipe];
+ int index = 0;
+
+ while (1)
+ {
+ unsigned short bitspec = table[index];
+ unsigned int bitfield =
+ ((unsigned int)(bits >> (bitspec & 63))) & (bitspec >> 6);
+
+ unsigned short next = table[index + 1 + bitfield];
+ if (next <= TILEGX_OPC_NONE)
+ return &tilegx_opcodes[next];
+
+ index = next - TILEGX_OPC_NONE;
+ }
+}
+
+int
+parse_insn_tilegx(tilegx_bundle_bits bits,
+ unsigned long long pc,
+ struct tilegx_decoded_instruction
+ decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE])
+{
+ int num_instructions = 0;
+ int pipe;
+
+ int min_pipe, max_pipe;
+ if ((bits & TILEGX_BUNDLE_MODE_MASK) == 0)
+ {
+ min_pipe = TILEGX_PIPELINE_X0;
+ max_pipe = TILEGX_PIPELINE_X1;
+ }
+ else
+ {
+ min_pipe = TILEGX_PIPELINE_Y0;
+ max_pipe = TILEGX_PIPELINE_Y2;
+ }
+
+ /* For each pipe, find an instruction that fits. */
+ for (pipe = min_pipe; pipe <= max_pipe; pipe++)
+ {
+ const struct tilegx_opcode *opc;
+ struct tilegx_decoded_instruction *d;
+ int i;
+
+ d = &decoded[num_instructions++];
+ opc = find_opcode (bits, (tilegx_pipeline)pipe);
+ d->opcode = opc;
+
+ /* Decode each operand, sign extending, etc. as appropriate. */
+ for (i = 0; i < opc->num_operands; i++)
+ {
+ const struct tilegx_operand *op =
+ &tilegx_operands[opc->operands[pipe][i]];
+ int raw_opval = op->extract (bits);
+ long long opval;
+
+ if (op->is_signed)
+ {
+ /* Sign-extend the operand. */
+ int shift = (int)((sizeof(int) * 8) - op->num_bits);
+ raw_opval = (raw_opval << shift) >> shift;
+ }
+
+ /* Adjust PC-relative scaled branch offsets. */
+ if (op->type == TILEGX_OP_TYPE_ADDRESS)
+ opval = (raw_opval * TILEGX_BUNDLE_SIZE_IN_BYTES) + pc;
+ else
+ opval = raw_opval;
+
+ /* Record the final value. */
+ d->operands[i] = op;
+ d->operand_values[i] = opval;
+ }
+ }
+
+ return num_instructions;
+}
+
+struct tilegx_spr
+{
+ /* The number */
+ int number;
+
+ /* The name */
+ const char *name;
+};
+
+static int
+tilegx_spr_compare (const void *a_ptr, const void *b_ptr)
+{
+ const struct tilegx_spr *a = (const struct tilegx_spr *) a_ptr;
+ const struct tilegx_spr *b = (const struct tilegx_spr *) b_ptr;
+ return (a->number - b->number);
+}
+
+const struct tilegx_spr tilegx_sprs[] = {
+ { 0, "MPL_MEM_ERROR_SET_0" },
+ { 1, "MPL_MEM_ERROR_SET_1" },
+ { 2, "MPL_MEM_ERROR_SET_2" },
+ { 3, "MPL_MEM_ERROR_SET_3" },
+ { 4, "MPL_MEM_ERROR" },
+ { 5, "MEM_ERROR_CBOX_ADDR" },
+ { 6, "MEM_ERROR_CBOX_STATUS" },
+ { 7, "MEM_ERROR_ENABLE" },
+ { 8, "MEM_ERROR_MBOX_ADDR" },
+ { 9, "MEM_ERROR_MBOX_STATUS" },
+ { 10, "SBOX_ERROR" },
+ { 11, "XDN_DEMUX_ERROR" },
+ { 256, "MPL_SINGLE_STEP_3_SET_0" },
+ { 257, "MPL_SINGLE_STEP_3_SET_1" },
+ { 258, "MPL_SINGLE_STEP_3_SET_2" },
+ { 259, "MPL_SINGLE_STEP_3_SET_3" },
+ { 260, "MPL_SINGLE_STEP_3" },
+ { 261, "SINGLE_STEP_CONTROL_3" },
+ { 512, "MPL_SINGLE_STEP_2_SET_0" },
+ { 513, "MPL_SINGLE_STEP_2_SET_1" },
+ { 514, "MPL_SINGLE_STEP_2_SET_2" },
+ { 515, "MPL_SINGLE_STEP_2_SET_3" },
+ { 516, "MPL_SINGLE_STEP_2" },
+ { 517, "SINGLE_STEP_CONTROL_2" },
+ { 768, "MPL_SINGLE_STEP_1_SET_0" },
+ { 769, "MPL_SINGLE_STEP_1_SET_1" },
+ { 770, "MPL_SINGLE_STEP_1_SET_2" },
+ { 771, "MPL_SINGLE_STEP_1_SET_3" },
+ { 772, "MPL_SINGLE_STEP_1" },
+ { 773, "SINGLE_STEP_CONTROL_1" },
+ { 1024, "MPL_SINGLE_STEP_0_SET_0" },
+ { 1025, "MPL_SINGLE_STEP_0_SET_1" },
+ { 1026, "MPL_SINGLE_STEP_0_SET_2" },
+ { 1027, "MPL_SINGLE_STEP_0_SET_3" },
+ { 1028, "MPL_SINGLE_STEP_0" },
+ { 1029, "SINGLE_STEP_CONTROL_0" },
+ { 1280, "MPL_IDN_COMPLETE_SET_0" },
+ { 1281, "MPL_IDN_COMPLETE_SET_1" },
+ { 1282, "MPL_IDN_COMPLETE_SET_2" },
+ { 1283, "MPL_IDN_COMPLETE_SET_3" },
+ { 1284, "MPL_IDN_COMPLETE" },
+ { 1285, "IDN_COMPLETE_PENDING" },
+ { 1536, "MPL_UDN_COMPLETE_SET_0" },
+ { 1537, "MPL_UDN_COMPLETE_SET_1" },
+ { 1538, "MPL_UDN_COMPLETE_SET_2" },
+ { 1539, "MPL_UDN_COMPLETE_SET_3" },
+ { 1540, "MPL_UDN_COMPLETE" },
+ { 1541, "UDN_COMPLETE_PENDING" },
+ { 1792, "MPL_ITLB_MISS_SET_0" },
+ { 1793, "MPL_ITLB_MISS_SET_1" },
+ { 1794, "MPL_ITLB_MISS_SET_2" },
+ { 1795, "MPL_ITLB_MISS_SET_3" },
+ { 1796, "MPL_ITLB_MISS" },
+ { 1797, "ITLB_TSB_BASE_ADDR_0" },
+ { 1798, "ITLB_TSB_BASE_ADDR_1" },
+ { 1920, "ITLB_CURRENT_ATTR" },
+ { 1921, "ITLB_CURRENT_PA" },
+ { 1922, "ITLB_CURRENT_VA" },
+ { 1923, "ITLB_INDEX" },
+ { 1924, "ITLB_MATCH_0" },
+ { 1925, "ITLB_PERF" },
+ { 1926, "ITLB_PR" },
+ { 1927, "ITLB_TSB_ADDR_0" },
+ { 1928, "ITLB_TSB_ADDR_1" },
+ { 1929, "ITLB_TSB_FILL_CURRENT_ATTR" },
+ { 1930, "ITLB_TSB_FILL_MATCH" },
+ { 1931, "NUMBER_ITLB" },
+ { 1932, "REPLACEMENT_ITLB" },
+ { 1933, "WIRED_ITLB" },
+ { 2048, "MPL_ILL_SET_0" },
+ { 2049, "MPL_ILL_SET_1" },
+ { 2050, "MPL_ILL_SET_2" },
+ { 2051, "MPL_ILL_SET_3" },
+ { 2052, "MPL_ILL" },
+ { 2304, "MPL_GPV_SET_0" },
+ { 2305, "MPL_GPV_SET_1" },
+ { 2306, "MPL_GPV_SET_2" },
+ { 2307, "MPL_GPV_SET_3" },
+ { 2308, "MPL_GPV" },
+ { 2309, "GPV_REASON" },
+ { 2560, "MPL_IDN_ACCESS_SET_0" },
+ { 2561, "MPL_IDN_ACCESS_SET_1" },
+ { 2562, "MPL_IDN_ACCESS_SET_2" },
+ { 2563, "MPL_IDN_ACCESS_SET_3" },
+ { 2564, "MPL_IDN_ACCESS" },
+ { 2565, "IDN_DEMUX_COUNT_0" },
+ { 2566, "IDN_DEMUX_COUNT_1" },
+ { 2567, "IDN_FLUSH_EGRESS" },
+ { 2568, "IDN_PENDING" },
+ { 2569, "IDN_ROUTE_ORDER" },
+ { 2570, "IDN_SP_FIFO_CNT" },
+ { 2688, "IDN_DATA_AVAIL" },
+ { 2816, "MPL_UDN_ACCESS_SET_0" },
+ { 2817, "MPL_UDN_ACCESS_SET_1" },
+ { 2818, "MPL_UDN_ACCESS_SET_2" },
+ { 2819, "MPL_UDN_ACCESS_SET_3" },
+ { 2820, "MPL_UDN_ACCESS" },
+ { 2821, "UDN_DEMUX_COUNT_0" },
+ { 2822, "UDN_DEMUX_COUNT_1" },
+ { 2823, "UDN_DEMUX_COUNT_2" },
+ { 2824, "UDN_DEMUX_COUNT_3" },
+ { 2825, "UDN_FLUSH_EGRESS" },
+ { 2826, "UDN_PENDING" },
+ { 2827, "UDN_ROUTE_ORDER" },
+ { 2828, "UDN_SP_FIFO_CNT" },
+ { 2944, "UDN_DATA_AVAIL" },
+ { 3072, "MPL_SWINT_3_SET_0" },
+ { 3073, "MPL_SWINT_3_SET_1" },
+ { 3074, "MPL_SWINT_3_SET_2" },
+ { 3075, "MPL_SWINT_3_SET_3" },
+ { 3076, "MPL_SWINT_3" },
+ { 3328, "MPL_SWINT_2_SET_0" },
+ { 3329, "MPL_SWINT_2_SET_1" },
+ { 3330, "MPL_SWINT_2_SET_2" },
+ { 3331, "MPL_SWINT_2_SET_3" },
+ { 3332, "MPL_SWINT_2" },
+ { 3584, "MPL_SWINT_1_SET_0" },
+ { 3585, "MPL_SWINT_1_SET_1" },
+ { 3586, "MPL_SWINT_1_SET_2" },
+ { 3587, "MPL_SWINT_1_SET_3" },
+ { 3588, "MPL_SWINT_1" },
+ { 3840, "MPL_SWINT_0_SET_0" },
+ { 3841, "MPL_SWINT_0_SET_1" },
+ { 3842, "MPL_SWINT_0_SET_2" },
+ { 3843, "MPL_SWINT_0_SET_3" },
+ { 3844, "MPL_SWINT_0" },
+ { 4096, "MPL_ILL_TRANS_SET_0" },
+ { 4097, "MPL_ILL_TRANS_SET_1" },
+ { 4098, "MPL_ILL_TRANS_SET_2" },
+ { 4099, "MPL_ILL_TRANS_SET_3" },
+ { 4100, "MPL_ILL_TRANS" },
+ { 4101, "ILL_TRANS_REASON" },
+ { 4102, "ILL_VA_PC" },
+ { 4352, "MPL_UNALIGN_DATA_SET_0" },
+ { 4353, "MPL_UNALIGN_DATA_SET_1" },
+ { 4354, "MPL_UNALIGN_DATA_SET_2" },
+ { 4355, "MPL_UNALIGN_DATA_SET_3" },
+ { 4356, "MPL_UNALIGN_DATA" },
+ { 4608, "MPL_DTLB_MISS_SET_0" },
+ { 4609, "MPL_DTLB_MISS_SET_1" },
+ { 4610, "MPL_DTLB_MISS_SET_2" },
+ { 4611, "MPL_DTLB_MISS_SET_3" },
+ { 4612, "MPL_DTLB_MISS" },
+ { 4613, "DTLB_TSB_BASE_ADDR_0" },
+ { 4614, "DTLB_TSB_BASE_ADDR_1" },
+ { 4736, "AAR" },
+ { 4737, "CACHE_PINNED_WAYS" },
+ { 4738, "DTLB_BAD_ADDR" },
+ { 4739, "DTLB_BAD_ADDR_REASON" },
+ { 4740, "DTLB_CURRENT_ATTR" },
+ { 4741, "DTLB_CURRENT_PA" },
+ { 4742, "DTLB_CURRENT_VA" },
+ { 4743, "DTLB_INDEX" },
+ { 4744, "DTLB_MATCH_0" },
+ { 4745, "DTLB_PERF" },
+ { 4746, "DTLB_TSB_ADDR_0" },
+ { 4747, "DTLB_TSB_ADDR_1" },
+ { 4748, "DTLB_TSB_FILL_CURRENT_ATTR" },
+ { 4749, "DTLB_TSB_FILL_MATCH" },
+ { 4750, "NUMBER_DTLB" },
+ { 4751, "REPLACEMENT_DTLB" },
+ { 4752, "WIRED_DTLB" },
+ { 4864, "MPL_DTLB_ACCESS_SET_0" },
+ { 4865, "MPL_DTLB_ACCESS_SET_1" },
+ { 4866, "MPL_DTLB_ACCESS_SET_2" },
+ { 4867, "MPL_DTLB_ACCESS_SET_3" },
+ { 4868, "MPL_DTLB_ACCESS" },
+ { 5120, "MPL_IDN_FIREWALL_SET_0" },
+ { 5121, "MPL_IDN_FIREWALL_SET_1" },
+ { 5122, "MPL_IDN_FIREWALL_SET_2" },
+ { 5123, "MPL_IDN_FIREWALL_SET_3" },
+ { 5124, "MPL_IDN_FIREWALL" },
+ { 5125, "IDN_DIRECTION_PROTECT" },
+ { 5376, "MPL_UDN_FIREWALL_SET_0" },
+ { 5377, "MPL_UDN_FIREWALL_SET_1" },
+ { 5378, "MPL_UDN_FIREWALL_SET_2" },
+ { 5379, "MPL_UDN_FIREWALL_SET_3" },
+ { 5380, "MPL_UDN_FIREWALL" },
+ { 5381, "UDN_DIRECTION_PROTECT" },
+ { 5632, "MPL_TILE_TIMER_SET_0" },
+ { 5633, "MPL_TILE_TIMER_SET_1" },
+ { 5634, "MPL_TILE_TIMER_SET_2" },
+ { 5635, "MPL_TILE_TIMER_SET_3" },
+ { 5636, "MPL_TILE_TIMER" },
+ { 5637, "TILE_TIMER_CONTROL" },
+ { 5888, "MPL_AUX_TILE_TIMER_SET_0" },
+ { 5889, "MPL_AUX_TILE_TIMER_SET_1" },
+ { 5890, "MPL_AUX_TILE_TIMER_SET_2" },
+ { 5891, "MPL_AUX_TILE_TIMER_SET_3" },
+ { 5892, "MPL_AUX_TILE_TIMER" },
+ { 5893, "AUX_TILE_TIMER_CONTROL" },
+ { 6144, "MPL_IDN_TIMER_SET_0" },
+ { 6145, "MPL_IDN_TIMER_SET_1" },
+ { 6146, "MPL_IDN_TIMER_SET_2" },
+ { 6147, "MPL_IDN_TIMER_SET_3" },
+ { 6148, "MPL_IDN_TIMER" },
+ { 6149, "IDN_DEADLOCK_COUNT" },
+ { 6150, "IDN_DEADLOCK_TIMEOUT" },
+ { 6400, "MPL_UDN_TIMER_SET_0" },
+ { 6401, "MPL_UDN_TIMER_SET_1" },
+ { 6402, "MPL_UDN_TIMER_SET_2" },
+ { 6403, "MPL_UDN_TIMER_SET_3" },
+ { 6404, "MPL_UDN_TIMER" },
+ { 6405, "UDN_DEADLOCK_COUNT" },
+ { 6406, "UDN_DEADLOCK_TIMEOUT" },
+ { 6656, "MPL_IDN_AVAIL_SET_0" },
+ { 6657, "MPL_IDN_AVAIL_SET_1" },
+ { 6658, "MPL_IDN_AVAIL_SET_2" },
+ { 6659, "MPL_IDN_AVAIL_SET_3" },
+ { 6660, "MPL_IDN_AVAIL" },
+ { 6661, "IDN_AVAIL_EN" },
+ { 6912, "MPL_UDN_AVAIL_SET_0" },
+ { 6913, "MPL_UDN_AVAIL_SET_1" },
+ { 6914, "MPL_UDN_AVAIL_SET_2" },
+ { 6915, "MPL_UDN_AVAIL_SET_3" },
+ { 6916, "MPL_UDN_AVAIL" },
+ { 6917, "UDN_AVAIL_EN" },
+ { 7168, "MPL_IPI_3_SET_0" },
+ { 7169, "MPL_IPI_3_SET_1" },
+ { 7170, "MPL_IPI_3_SET_2" },
+ { 7171, "MPL_IPI_3_SET_3" },
+ { 7172, "MPL_IPI_3" },
+ { 7173, "IPI_EVENT_3" },
+ { 7174, "IPI_EVENT_RESET_3" },
+ { 7175, "IPI_EVENT_SET_3" },
+ { 7176, "IPI_MASK_3" },
+ { 7177, "IPI_MASK_RESET_3" },
+ { 7178, "IPI_MASK_SET_3" },
+ { 7424, "MPL_IPI_2_SET_0" },
+ { 7425, "MPL_IPI_2_SET_1" },
+ { 7426, "MPL_IPI_2_SET_2" },
+ { 7427, "MPL_IPI_2_SET_3" },
+ { 7428, "MPL_IPI_2" },
+ { 7429, "IPI_EVENT_2" },
+ { 7430, "IPI_EVENT_RESET_2" },
+ { 7431, "IPI_EVENT_SET_2" },
+ { 7432, "IPI_MASK_2" },
+ { 7433, "IPI_MASK_RESET_2" },
+ { 7434, "IPI_MASK_SET_2" },
+ { 7680, "MPL_IPI_1_SET_0" },
+ { 7681, "MPL_IPI_1_SET_1" },
+ { 7682, "MPL_IPI_1_SET_2" },
+ { 7683, "MPL_IPI_1_SET_3" },
+ { 7684, "MPL_IPI_1" },
+ { 7685, "IPI_EVENT_1" },
+ { 7686, "IPI_EVENT_RESET_1" },
+ { 7687, "IPI_EVENT_SET_1" },
+ { 7688, "IPI_MASK_1" },
+ { 7689, "IPI_MASK_RESET_1" },
+ { 7690, "IPI_MASK_SET_1" },
+ { 7936, "MPL_IPI_0_SET_0" },
+ { 7937, "MPL_IPI_0_SET_1" },
+ { 7938, "MPL_IPI_0_SET_2" },
+ { 7939, "MPL_IPI_0_SET_3" },
+ { 7940, "MPL_IPI_0" },
+ { 7941, "IPI_EVENT_0" },
+ { 7942, "IPI_EVENT_RESET_0" },
+ { 7943, "IPI_EVENT_SET_0" },
+ { 7944, "IPI_MASK_0" },
+ { 7945, "IPI_MASK_RESET_0" },
+ { 7946, "IPI_MASK_SET_0" },
+ { 8192, "MPL_PERF_COUNT_SET_0" },
+ { 8193, "MPL_PERF_COUNT_SET_1" },
+ { 8194, "MPL_PERF_COUNT_SET_2" },
+ { 8195, "MPL_PERF_COUNT_SET_3" },
+ { 8196, "MPL_PERF_COUNT" },
+ { 8197, "PERF_COUNT_0" },
+ { 8198, "PERF_COUNT_1" },
+ { 8199, "PERF_COUNT_CTL" },
+ { 8200, "PERF_COUNT_DN_CTL" },
+ { 8201, "PERF_COUNT_STS" },
+ { 8202, "WATCH_MASK" },
+ { 8203, "WATCH_VAL" },
+ { 8448, "MPL_AUX_PERF_COUNT_SET_0" },
+ { 8449, "MPL_AUX_PERF_COUNT_SET_1" },
+ { 8450, "MPL_AUX_PERF_COUNT_SET_2" },
+ { 8451, "MPL_AUX_PERF_COUNT_SET_3" },
+ { 8452, "MPL_AUX_PERF_COUNT" },
+ { 8453, "AUX_PERF_COUNT_0" },
+ { 8454, "AUX_PERF_COUNT_1" },
+ { 8455, "AUX_PERF_COUNT_CTL" },
+ { 8456, "AUX_PERF_COUNT_STS" },
+ { 8704, "MPL_INTCTRL_3_SET_0" },
+ { 8705, "MPL_INTCTRL_3_SET_1" },
+ { 8706, "MPL_INTCTRL_3_SET_2" },
+ { 8707, "MPL_INTCTRL_3_SET_3" },
+ { 8708, "MPL_INTCTRL_3" },
+ { 8709, "INTCTRL_3_STATUS" },
+ { 8710, "INTERRUPT_MASK_3" },
+ { 8711, "INTERRUPT_MASK_RESET_3" },
+ { 8712, "INTERRUPT_MASK_SET_3" },
+ { 8713, "INTERRUPT_VECTOR_BASE_3" },
+ { 8714, "SINGLE_STEP_EN_0_3" },
+ { 8715, "SINGLE_STEP_EN_1_3" },
+ { 8716, "SINGLE_STEP_EN_2_3" },
+ { 8717, "SINGLE_STEP_EN_3_3" },
+ { 8832, "EX_CONTEXT_3_0" },
+ { 8833, "EX_CONTEXT_3_1" },
+ { 8834, "SYSTEM_SAVE_3_0" },
+ { 8835, "SYSTEM_SAVE_3_1" },
+ { 8836, "SYSTEM_SAVE_3_2" },
+ { 8837, "SYSTEM_SAVE_3_3" },
+ { 8960, "MPL_INTCTRL_2_SET_0" },
+ { 8961, "MPL_INTCTRL_2_SET_1" },
+ { 8962, "MPL_INTCTRL_2_SET_2" },
+ { 8963, "MPL_INTCTRL_2_SET_3" },
+ { 8964, "MPL_INTCTRL_2" },
+ { 8965, "INTCTRL_2_STATUS" },
+ { 8966, "INTERRUPT_MASK_2" },
+ { 8967, "INTERRUPT_MASK_RESET_2" },
+ { 8968, "INTERRUPT_MASK_SET_2" },
+ { 8969, "INTERRUPT_VECTOR_BASE_2" },
+ { 8970, "SINGLE_STEP_EN_0_2" },
+ { 8971, "SINGLE_STEP_EN_1_2" },
+ { 8972, "SINGLE_STEP_EN_2_2" },
+ { 8973, "SINGLE_STEP_EN_3_2" },
+ { 9088, "EX_CONTEXT_2_0" },
+ { 9089, "EX_CONTEXT_2_1" },
+ { 9090, "SYSTEM_SAVE_2_0" },
+ { 9091, "SYSTEM_SAVE_2_1" },
+ { 9092, "SYSTEM_SAVE_2_2" },
+ { 9093, "SYSTEM_SAVE_2_3" },
+ { 9216, "MPL_INTCTRL_1_SET_0" },
+ { 9217, "MPL_INTCTRL_1_SET_1" },
+ { 9218, "MPL_INTCTRL_1_SET_2" },
+ { 9219, "MPL_INTCTRL_1_SET_3" },
+ { 9220, "MPL_INTCTRL_1" },
+ { 9221, "INTCTRL_1_STATUS" },
+ { 9222, "INTERRUPT_MASK_1" },
+ { 9223, "INTERRUPT_MASK_RESET_1" },
+ { 9224, "INTERRUPT_MASK_SET_1" },
+ { 9225, "INTERRUPT_VECTOR_BASE_1" },
+ { 9226, "SINGLE_STEP_EN_0_1" },
+ { 9227, "SINGLE_STEP_EN_1_1" },
+ { 9228, "SINGLE_STEP_EN_2_1" },
+ { 9229, "SINGLE_STEP_EN_3_1" },
+ { 9344, "EX_CONTEXT_1_0" },
+ { 9345, "EX_CONTEXT_1_1" },
+ { 9346, "SYSTEM_SAVE_1_0" },
+ { 9347, "SYSTEM_SAVE_1_1" },
+ { 9348, "SYSTEM_SAVE_1_2" },
+ { 9349, "SYSTEM_SAVE_1_3" },
+ { 9472, "MPL_INTCTRL_0_SET_0" },
+ { 9473, "MPL_INTCTRL_0_SET_1" },
+ { 9474, "MPL_INTCTRL_0_SET_2" },
+ { 9475, "MPL_INTCTRL_0_SET_3" },
+ { 9476, "MPL_INTCTRL_0" },
+ { 9477, "INTCTRL_0_STATUS" },
+ { 9478, "INTERRUPT_MASK_0" },
+ { 9479, "INTERRUPT_MASK_RESET_0" },
+ { 9480, "INTERRUPT_MASK_SET_0" },
+ { 9481, "INTERRUPT_VECTOR_BASE_0" },
+ { 9482, "SINGLE_STEP_EN_0_0" },
+ { 9483, "SINGLE_STEP_EN_1_0" },
+ { 9484, "SINGLE_STEP_EN_2_0" },
+ { 9485, "SINGLE_STEP_EN_3_0" },
+ { 9600, "EX_CONTEXT_0_0" },
+ { 9601, "EX_CONTEXT_0_1" },
+ { 9602, "SYSTEM_SAVE_0_0" },
+ { 9603, "SYSTEM_SAVE_0_1" },
+ { 9604, "SYSTEM_SAVE_0_2" },
+ { 9605, "SYSTEM_SAVE_0_3" },
+ { 9728, "MPL_BOOT_ACCESS_SET_0" },
+ { 9729, "MPL_BOOT_ACCESS_SET_1" },
+ { 9730, "MPL_BOOT_ACCESS_SET_2" },
+ { 9731, "MPL_BOOT_ACCESS_SET_3" },
+ { 9732, "MPL_BOOT_ACCESS" },
+ { 9733, "BIG_ENDIAN_CONFIG" },
+ { 9734, "CACHE_INVALIDATION_COMPRESSION_MODE" },
+ { 9735, "CACHE_INVALIDATION_MASK_0" },
+ { 9736, "CACHE_INVALIDATION_MASK_1" },
+ { 9737, "CACHE_INVALIDATION_MASK_2" },
+ { 9738, "CBOX_CACHEASRAM_CONFIG" },
+ { 9739, "CBOX_CACHE_CONFIG" },
+ { 9740, "CBOX_HOME_MAP_ADDR" },
+ { 9741, "CBOX_HOME_MAP_DATA" },
+ { 9742, "CBOX_MMAP_0" },
+ { 9743, "CBOX_MMAP_1" },
+ { 9744, "CBOX_MMAP_2" },
+ { 9745, "CBOX_MMAP_3" },
+ { 9746, "CBOX_MSR" },
+ { 9747, "DIAG_BCST_CTL" },
+ { 9748, "DIAG_BCST_MASK" },
+ { 9749, "DIAG_BCST_TRIGGER" },
+ { 9750, "DIAG_MUX_CTL" },
+ { 9751, "DIAG_TRACE_CTL" },
+ { 9752, "DIAG_TRACE_DATA" },
+ { 9753, "DIAG_TRACE_STS" },
+ { 9754, "IDN_DEMUX_BUF_THRESH" },
+ { 9755, "L1_I_PIN_WAY_0" },
+ { 9756, "MEM_ROUTE_ORDER" },
+ { 9757, "MEM_STRIPE_CONFIG" },
+ { 9758, "PERF_COUNT_PLS" },
+ { 9759, "PSEUDO_RANDOM_NUMBER_MODIFY" },
+ { 9760, "QUIESCE_CTL" },
+ { 9761, "RSHIM_COORD" },
+ { 9762, "SBOX_CONFIG" },
+ { 9763, "UDN_DEMUX_BUF_THRESH" },
+ { 9764, "XDN_CORE_STARVATION_COUNT" },
+ { 9765, "XDN_ROUND_ROBIN_ARB_CTL" },
+ { 9856, "CYCLE_MODIFY" },
+ { 9857, "I_AAR" },
+ { 9984, "MPL_WORLD_ACCESS_SET_0" },
+ { 9985, "MPL_WORLD_ACCESS_SET_1" },
+ { 9986, "MPL_WORLD_ACCESS_SET_2" },
+ { 9987, "MPL_WORLD_ACCESS_SET_3" },
+ { 9988, "MPL_WORLD_ACCESS" },
+ { 9989, "DONE" },
+ { 9990, "DSTREAM_PF" },
+ { 9991, "FAIL" },
+ { 9992, "INTERRUPT_CRITICAL_SECTION" },
+ { 9993, "PASS" },
+ { 9994, "PSEUDO_RANDOM_NUMBER" },
+ { 9995, "TILE_COORD" },
+ { 9996, "TILE_RTF_HWM" },
+ { 10112, "CMPEXCH_VALUE" },
+ { 10113, "CYCLE" },
+ { 10114, "EVENT_BEGIN" },
+ { 10115, "EVENT_END" },
+ { 10116, "PROC_STATUS" },
+ { 10117, "SIM_CONTROL" },
+ { 10118, "SIM_SOCKET" },
+ { 10119, "STATUS_SATURATE" },
+ { 10240, "MPL_I_ASID_SET_0" },
+ { 10241, "MPL_I_ASID_SET_1" },
+ { 10242, "MPL_I_ASID_SET_2" },
+ { 10243, "MPL_I_ASID_SET_3" },
+ { 10244, "MPL_I_ASID" },
+ { 10245, "I_ASID" },
+ { 10496, "MPL_D_ASID_SET_0" },
+ { 10497, "MPL_D_ASID_SET_1" },
+ { 10498, "MPL_D_ASID_SET_2" },
+ { 10499, "MPL_D_ASID_SET_3" },
+ { 10500, "MPL_D_ASID" },
+ { 10501, "D_ASID" },
+ { 10752, "MPL_DOUBLE_FAULT_SET_0" },
+ { 10753, "MPL_DOUBLE_FAULT_SET_1" },
+ { 10754, "MPL_DOUBLE_FAULT_SET_2" },
+ { 10755, "MPL_DOUBLE_FAULT_SET_3" },
+ { 10756, "MPL_DOUBLE_FAULT" },
+ { 10757, "LAST_INTERRUPT_REASON" },
+};
+
+const int tilegx_num_sprs = 441;
+
+const char *
+get_tilegx_spr_name (int num)
+{
+ void *result;
+ struct tilegx_spr key;
+
+ key.number = num;
+ result = bsearch((const void *) &key, (const void *) tilegx_sprs,
+ tilegx_num_sprs, sizeof (struct tilegx_spr),
+ tilegx_spr_compare);
+
+ if (result == NULL)
+ {
+ return (NULL);
+ }
+ else
+ {
+ struct tilegx_spr *result_ptr = (struct tilegx_spr *) result;
+ return (result_ptr->name);
+ }
+}
+
+int
+print_insn_tilegx (unsigned char * memaddr)
+{
+ struct tilegx_decoded_instruction
+ decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE];
+ unsigned char opbuf[TILEGX_BUNDLE_SIZE_IN_BYTES];
+ int i, num_instructions, num_printed;
+ tilegx_mnemonic padding_mnemonic;
+
+ memcpy((void *)opbuf, (void *)memaddr, TILEGX_BUNDLE_SIZE_IN_BYTES);
+
+ /* Parse the instructions in the bundle. */
+ num_instructions =
+ parse_insn_tilegx (*(unsigned long long *)opbuf, (unsigned long long)memaddr, decoded);
+
+ /* Print the instructions in the bundle. */
+ printf("{ ");
+ num_printed = 0;
+
+ /* Determine which nop opcode is used for padding and should be skipped. */
+ padding_mnemonic = TILEGX_OPC_FNOP;
+ for (i = 0; i < num_instructions; i++)
+ {
+ if (!decoded[i].opcode->can_bundle)
+ {
+ /* Instructions that cannot be bundled are padded out with nops,
+ rather than fnops. Displaying them is always clutter. */
+ padding_mnemonic = TILEGX_OPC_NOP;
+ break;
+ }
+ }
+
+ for (i = 0; i < num_instructions; i++)
+ {
+ const struct tilegx_opcode *opcode = decoded[i].opcode;
+ const char *name;
+ int j;
+
+ /* Do not print out fnops, unless everything is an fnop, in
+ which case we will print out just the last one. */
+ if (opcode->mnemonic == padding_mnemonic
+ && (num_printed > 0 || i + 1 < num_instructions))
+ continue;
+
+ if (num_printed > 0)
+ printf(" ; ");
+ ++num_printed;
+
+ name = opcode->name;
+ if (name == NULL)
+ name = "<invalid>";
+ printf("%s", name);
+
+ for (j = 0; j < opcode->num_operands; j++)
+ {
+ unsigned long long num;
+ const struct tilegx_operand *op;
+ const char *spr_name;
+
+ if (j > 0)
+ printf (",");
+ printf (" ");
+
+ num = decoded[i].operand_values[j];
+
+ op = decoded[i].operands[j];
+ switch (op->type)
+ {
+ case TILEGX_OP_TYPE_REGISTER:
+ printf ("%s", tilegx_register_names[(int)num]);
+ break;
+ case TILEGX_OP_TYPE_SPR:
+ spr_name = get_tilegx_spr_name(num);
+ if (spr_name != NULL)
+ printf ("%s", spr_name);
+ else
+ printf ("%d", (int)num);
+ break;
+ case TILEGX_OP_TYPE_IMMEDIATE:
+ printf ("%d", (int)num);
+ break;
+ case TILEGX_OP_TYPE_ADDRESS:
+ printf ("0x%016llx", num);
+ break;
+ default:
+ abort ();
+ }
+ }
+ }
+ printf (" }\n");
+
+ return TILEGX_BUNDLE_SIZE_IN_BYTES;
+}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c b/src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c
new file mode 100644
index 0000000000..d0b392e7a4
--- /dev/null
+++ b/src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c
@@ -0,0 +1,2580 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright 2013-2013 Tilera Corporation(jiwang@tilera.com). All rights reserved.
+ * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.
+ */
+
+/* TileGX architecture. */
+/* Contributed by Tilera Corporation. */
+#include "sljitNativeTILEGX-encoder.c"
+
+#define SIMM_8BIT_MAX (0x7f)
+#define SIMM_8BIT_MIN (-0x80)
+#define SIMM_16BIT_MAX (0x7fff)
+#define SIMM_16BIT_MIN (-0x8000)
+#define SIMM_17BIT_MAX (0xffff)
+#define SIMM_17BIT_MIN (-0x10000)
+#define SIMM_32BIT_MIN (-0x80000000)
+#define SIMM_32BIT_MAX (0x7fffffff)
+#define SIMM_48BIT_MIN (0x800000000000L)
+#define SIMM_48BIT_MAX (0x7fffffff0000L)
+#define IMM16(imm) ((imm) & 0xffff)
+
+#define UIMM_16BIT_MAX (0xffff)
+
+#define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
+#define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
+#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
+#define ADDR_TMP (SLJIT_NO_REGISTERS + 4)
+#define PIC_ADDR_REG TMP_REG2
+
+static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
+ 63, 0, 1, 2, 3, 4, 30, 31, 32, 33, 34, 54, 5, 16, 6, 7
+};
+
+#define SLJIT_LOCALS_REG_mapped 54
+#define TMP_REG1_mapped 5
+#define TMP_REG2_mapped 16
+#define TMP_REG3_mapped 6
+#define ADDR_TMP_mapped 7
+#define SLJIT_SAVED_REG1_mapped 30
+#define SLJIT_SAVED_REG2_mapped 31
+#define SLJIT_SAVED_REG3_mapped 32
+#define SLJIT_SAVED_EREG1_mapped 33
+#define SLJIT_SAVED_EREG2_mapped 34
+
+/* Flags are keept in volatile registers. */
+#define EQUAL_FLAG 8
+/* And carry flag as well. */
+#define ULESS_FLAG 9
+#define UGREATER_FLAG 10
+#define LESS_FLAG 11
+#define GREATER_FLAG 12
+#define OVERFLOW_FLAG 13
+
+#define ZERO 63
+#define RA 55
+#define TMP_EREG1 14
+#define TMP_EREG2 15
+
+#define LOAD_DATA 0x01
+#define WORD_DATA 0x00
+#define BYTE_DATA 0x02
+#define HALF_DATA 0x04
+#define INT_DATA 0x06
+#define SIGNED_DATA 0x08
+#define DOUBLE_DATA 0x10
+
+/* Separates integer and floating point registers */
+#define GPR_REG 0xf
+
+#define MEM_MASK 0x1f
+
+#define WRITE_BACK 0x00020
+#define ARG_TEST 0x00040
+#define ALT_KEEP_CACHE 0x00080
+#define CUMULATIVE_OP 0x00100
+#define LOGICAL_OP 0x00200
+#define IMM_OP 0x00400
+#define SRC2_IMM 0x00800
+
+#define UNUSED_DEST 0x01000
+#define REG_DEST 0x02000
+#define REG1_SOURCE 0x04000
+#define REG2_SOURCE 0x08000
+#define SLOW_SRC1 0x10000
+#define SLOW_SRC2 0x20000
+#define SLOW_DEST 0x40000
+
+/* Only these flags are set. UNUSED_DEST is not set when no flags should be set.
+ */
+#define CHECK_FLAGS(list) (!(flags & UNUSED_DEST) || (op & GET_FLAGS(~(list))))
+
+SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char *sljit_get_platform_name(void)
+{
+ return "TileGX" SLJIT_CPUINFO;
+}
+
+/* Length of an instruction word */
+typedef sljit_uw sljit_ins;
+
+struct jit_instr {
+ const struct tilegx_opcode* opcode;
+ tilegx_pipeline pipe;
+ unsigned long input_registers;
+ unsigned long output_registers;
+ int operand_value[4];
+ int line;
+};
+
+/* Opcode Helper Macros */
+#define TILEGX_X_MODE 0
+
+#define X_MODE create_Mode(TILEGX_X_MODE)
+
+#define FNOP_X0 \
+ create_Opcode_X0(RRR_0_OPCODE_X0) | \
+ create_RRROpcodeExtension_X0(UNARY_RRR_0_OPCODE_X0) | \
+ create_UnaryOpcodeExtension_X0(FNOP_UNARY_OPCODE_X0)
+
+#define FNOP_X1 \
+ create_Opcode_X1(RRR_0_OPCODE_X1) | \
+ create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | \
+ create_UnaryOpcodeExtension_X1(FNOP_UNARY_OPCODE_X1)
+
+#define NOP \
+ create_Mode(TILEGX_X_MODE) | FNOP_X0 | FNOP_X1
+
+#define ANOP_X0 \
+ create_Opcode_X0(RRR_0_OPCODE_X0) | \
+ create_RRROpcodeExtension_X0(UNARY_RRR_0_OPCODE_X0) | \
+ create_UnaryOpcodeExtension_X0(NOP_UNARY_OPCODE_X0)
+
+#define BPT create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \
+ create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | \
+ create_UnaryOpcodeExtension_X1(ILL_UNARY_OPCODE_X1) | \
+ create_Dest_X1(0x1C) | create_SrcA_X1(0x25) | ANOP_X0
+
+#define ADD_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \
+ create_RRROpcodeExtension_X1(ADD_RRR_0_OPCODE_X1) | FNOP_X0
+
+#define ADDI_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(IMM8_OPCODE_X1) | \
+ create_Imm8OpcodeExtension_X1(ADDI_IMM8_OPCODE_X1) | FNOP_X0
+
+#define SUB_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \
+ create_RRROpcodeExtension_X1(SUB_RRR_0_OPCODE_X1) | FNOP_X0
+
+#define NOR_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \
+ create_RRROpcodeExtension_X1(NOR_RRR_0_OPCODE_X1) | FNOP_X0
+
+#define OR_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \
+ create_RRROpcodeExtension_X1(OR_RRR_0_OPCODE_X1) | FNOP_X0
+
+#define AND_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \
+ create_RRROpcodeExtension_X1(AND_RRR_0_OPCODE_X1) | FNOP_X0
+
+#define XOR_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \
+ create_RRROpcodeExtension_X1(XOR_RRR_0_OPCODE_X1) | FNOP_X0
+
+#define CMOVNEZ_X0 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X0(RRR_0_OPCODE_X0) | \
+ create_RRROpcodeExtension_X0(CMOVNEZ_RRR_0_OPCODE_X0) | FNOP_X1
+
+#define CMOVEQZ_X0 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X0(RRR_0_OPCODE_X0) | \
+ create_RRROpcodeExtension_X0(CMOVEQZ_RRR_0_OPCODE_X0) | FNOP_X1
+
+#define ADDLI_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(ADDLI_OPCODE_X1) | FNOP_X0
+
+#define V4INT_L_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \
+ create_RRROpcodeExtension_X1(V4INT_L_RRR_0_OPCODE_X1) | FNOP_X0
+
+#define BFEXTU_X0 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X0(BF_OPCODE_X0) | \
+ create_BFOpcodeExtension_X0(BFEXTU_BF_OPCODE_X0) | FNOP_X1
+
+#define BFEXTS_X0 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X0(BF_OPCODE_X0) | \
+ create_BFOpcodeExtension_X0(BFEXTS_BF_OPCODE_X0) | FNOP_X1
+
+#define SHL16INSLI_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(SHL16INSLI_OPCODE_X1) | FNOP_X0
+
+#define ST_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \
+ create_RRROpcodeExtension_X1(ST_RRR_0_OPCODE_X1) | create_Dest_X1(0x0) | FNOP_X0
+
+#define LD_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \
+ create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | \
+ create_UnaryOpcodeExtension_X1(LD_UNARY_OPCODE_X1) | FNOP_X0
+
+#define JR_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \
+ create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | \
+ create_UnaryOpcodeExtension_X1(JR_UNARY_OPCODE_X1) | FNOP_X0
+
+#define JALR_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \
+ create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | \
+ create_UnaryOpcodeExtension_X1(JALR_UNARY_OPCODE_X1) | FNOP_X0
+
+#define CLZ_X0 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X0(RRR_0_OPCODE_X0) | \
+ create_RRROpcodeExtension_X0(UNARY_RRR_0_OPCODE_X0) | \
+ create_UnaryOpcodeExtension_X0(CNTLZ_UNARY_OPCODE_X0) | FNOP_X1
+
+#define CMPLTUI_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(IMM8_OPCODE_X1) | \
+ create_Imm8OpcodeExtension_X1(CMPLTUI_IMM8_OPCODE_X1) | FNOP_X0
+
+#define CMPLTU_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \
+ create_RRROpcodeExtension_X1(CMPLTU_RRR_0_OPCODE_X1) | FNOP_X0
+
+#define CMPLTS_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \
+ create_RRROpcodeExtension_X1(CMPLTS_RRR_0_OPCODE_X1) | FNOP_X0
+
+#define XORI_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(IMM8_OPCODE_X1) | \
+ create_Imm8OpcodeExtension_X1(XORI_IMM8_OPCODE_X1) | FNOP_X0
+
+#define ORI_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(IMM8_OPCODE_X1) | \
+ create_Imm8OpcodeExtension_X1(ORI_IMM8_OPCODE_X1) | FNOP_X0
+
+#define ANDI_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(IMM8_OPCODE_X1) | \
+ create_Imm8OpcodeExtension_X1(ANDI_IMM8_OPCODE_X1) | FNOP_X0
+
+#define SHLI_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(SHIFT_OPCODE_X1) | \
+ create_ShiftOpcodeExtension_X1(SHLI_SHIFT_OPCODE_X1) | FNOP_X0
+
+#define SHL_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \
+ create_RRROpcodeExtension_X1(SHL_RRR_0_OPCODE_X1) | FNOP_X0
+
+#define SHRSI_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(SHIFT_OPCODE_X1) | \
+ create_ShiftOpcodeExtension_X1(SHRSI_SHIFT_OPCODE_X1) | FNOP_X0
+
+#define SHRS_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \
+ create_RRROpcodeExtension_X1(SHRS_RRR_0_OPCODE_X1) | FNOP_X0
+
+#define SHRUI_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(SHIFT_OPCODE_X1) | \
+ create_ShiftOpcodeExtension_X1(SHRUI_SHIFT_OPCODE_X1) | FNOP_X0
+
+#define SHRU_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \
+ create_RRROpcodeExtension_X1(SHRU_RRR_0_OPCODE_X1) | FNOP_X0
+
+#define BEQZ_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(BRANCH_OPCODE_X1) | \
+ create_BrType_X1(BEQZ_BRANCH_OPCODE_X1) | FNOP_X0
+
+#define BNEZ_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(BRANCH_OPCODE_X1) | \
+ create_BrType_X1(BNEZ_BRANCH_OPCODE_X1) | FNOP_X0
+
+#define J_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(JUMP_OPCODE_X1) | \
+ create_JumpOpcodeExtension_X1(J_JUMP_OPCODE_X1) | FNOP_X0
+
+#define JAL_X1 \
+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(JUMP_OPCODE_X1) | \
+ create_JumpOpcodeExtension_X1(JAL_JUMP_OPCODE_X1) | FNOP_X0
+
+#define DEST_X0(x) create_Dest_X0(x)
+#define SRCA_X0(x) create_SrcA_X0(x)
+#define SRCB_X0(x) create_SrcB_X0(x)
+#define DEST_X1(x) create_Dest_X1(x)
+#define SRCA_X1(x) create_SrcA_X1(x)
+#define SRCB_X1(x) create_SrcB_X1(x)
+#define IMM16_X1(x) create_Imm16_X1(x)
+#define IMM8_X1(x) create_Imm8_X1(x)
+#define BFSTART_X0(x) create_BFStart_X0(x)
+#define BFEND_X0(x) create_BFEnd_X0(x)
+#define SHIFTIMM_X1(x) create_ShAmt_X1(x)
+#define JOFF_X1(x) create_JumpOff_X1(x)
+#define BOFF_X1(x) create_BrOff_X1(x)
+
+static SLJIT_CONST tilegx_mnemonic data_transfer_insts[16] = {
+ /* u w s */ TILEGX_OPC_ST /* st */,
+ /* u w l */ TILEGX_OPC_LD /* ld */,
+ /* u b s */ TILEGX_OPC_ST1 /* st1 */,
+ /* u b l */ TILEGX_OPC_LD1U /* ld1u */,
+ /* u h s */ TILEGX_OPC_ST2 /* st2 */,
+ /* u h l */ TILEGX_OPC_LD2U /* ld2u */,
+ /* u i s */ TILEGX_OPC_ST4 /* st4 */,
+ /* u i l */ TILEGX_OPC_LD4U /* ld4u */,
+ /* s w s */ TILEGX_OPC_ST /* st */,
+ /* s w l */ TILEGX_OPC_LD /* ld */,
+ /* s b s */ TILEGX_OPC_ST1 /* st1 */,
+ /* s b l */ TILEGX_OPC_LD1S /* ld1s */,
+ /* s h s */ TILEGX_OPC_ST2 /* st2 */,
+ /* s h l */ TILEGX_OPC_LD2S /* ld2s */,
+ /* s i s */ TILEGX_OPC_ST4 /* st4 */,
+ /* s i l */ TILEGX_OPC_LD4S /* ld4s */,
+};
+
+#ifdef TILEGX_JIT_DEBUG
+static sljit_si push_inst_debug(struct sljit_compiler *compiler, sljit_ins ins, int line)
+{
+ sljit_ins *ptr = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ptr);
+ *ptr = ins;
+ compiler->size++;
+ printf("|%04d|S0|:\t\t", line);
+ print_insn_tilegx(ptr);
+ return SLJIT_SUCCESS;
+}
+
+static sljit_si push_inst_nodebug(struct sljit_compiler *compiler, sljit_ins ins)
+{
+ sljit_ins *ptr = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ptr);
+ *ptr = ins;
+ compiler->size++;
+ return SLJIT_SUCCESS;
+}
+
+#define push_inst(a, b) push_inst_debug(a, b, __LINE__)
+#else
+static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins)
+{
+ sljit_ins *ptr = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ptr);
+ *ptr = ins;
+ compiler->size++;
+ return SLJIT_SUCCESS;
+}
+#endif
+
+#define BUNDLE_FORMAT_MASK(p0, p1, p2) \
+ ((p0) | ((p1) << 8) | ((p2) << 16))
+
+#define BUNDLE_FORMAT(p0, p1, p2) \
+ { \
+ { \
+ (tilegx_pipeline)(p0), \
+ (tilegx_pipeline)(p1), \
+ (tilegx_pipeline)(p2) \
+ }, \
+ BUNDLE_FORMAT_MASK(1 << (p0), 1 << (p1), (1 << (p2))) \
+ }
+
+#define NO_PIPELINE TILEGX_NUM_PIPELINE_ENCODINGS
+
+#define tilegx_is_x_pipeline(p) ((int)(p) <= (int)TILEGX_PIPELINE_X1)
+
+#define PI(encoding) \
+ push_inst(compiler, encoding)
+
+#define PB3(opcode, dst, srca, srcb) \
+ push_3_buffer(compiler, opcode, dst, srca, srcb, __LINE__)
+
+#define PB2(opcode, dst, src) \
+ push_2_buffer(compiler, opcode, dst, src, __LINE__)
+
+#define JR(reg) \
+ push_jr_buffer(compiler, TILEGX_OPC_JR, reg, __LINE__)
+
+#define ADD(dst, srca, srcb) \
+ push_3_buffer(compiler, TILEGX_OPC_ADD, dst, srca, srcb, __LINE__)
+
+#define SUB(dst, srca, srcb) \
+ push_3_buffer(compiler, TILEGX_OPC_SUB, dst, srca, srcb, __LINE__)
+
+#define NOR(dst, srca, srcb) \
+ push_3_buffer(compiler, TILEGX_OPC_NOR, dst, srca, srcb, __LINE__)
+
+#define OR(dst, srca, srcb) \
+ push_3_buffer(compiler, TILEGX_OPC_OR, dst, srca, srcb, __LINE__)
+
+#define XOR(dst, srca, srcb) \
+ push_3_buffer(compiler, TILEGX_OPC_XOR, dst, srca, srcb, __LINE__)
+
+#define AND(dst, srca, srcb) \
+ push_3_buffer(compiler, TILEGX_OPC_AND, dst, srca, srcb, __LINE__)
+
+#define CLZ(dst, src) \
+ push_2_buffer(compiler, TILEGX_OPC_CLZ, dst, src, __LINE__)
+
+#define SHLI(dst, srca, srcb) \
+ push_3_buffer(compiler, TILEGX_OPC_SHLI, dst, srca, srcb, __LINE__)
+
+#define SHRUI(dst, srca, imm) \
+ push_3_buffer(compiler, TILEGX_OPC_SHRUI, dst, srca, imm, __LINE__)
+
+#define XORI(dst, srca, imm) \
+ push_3_buffer(compiler, TILEGX_OPC_XORI, dst, srca, imm, __LINE__)
+
+#define ORI(dst, srca, imm) \
+ push_3_buffer(compiler, TILEGX_OPC_ORI, dst, srca, imm, __LINE__)
+
+#define CMPLTU(dst, srca, srcb) \
+ push_3_buffer(compiler, TILEGX_OPC_CMPLTU, dst, srca, srcb, __LINE__)
+
+#define CMPLTS(dst, srca, srcb) \
+ push_3_buffer(compiler, TILEGX_OPC_CMPLTS, dst, srca, srcb, __LINE__)
+
+#define CMPLTUI(dst, srca, imm) \
+ push_3_buffer(compiler, TILEGX_OPC_CMPLTUI, dst, srca, imm, __LINE__)
+
+#define CMOVNEZ(dst, srca, srcb) \
+ push_3_buffer(compiler, TILEGX_OPC_CMOVNEZ, dst, srca, srcb, __LINE__)
+
+#define CMOVEQZ(dst, srca, srcb) \
+ push_3_buffer(compiler, TILEGX_OPC_CMOVEQZ, dst, srca, srcb, __LINE__)
+
+#define ADDLI(dst, srca, srcb) \
+ push_3_buffer(compiler, TILEGX_OPC_ADDLI, dst, srca, srcb, __LINE__)
+
+#define SHL16INSLI(dst, srca, srcb) \
+ push_3_buffer(compiler, TILEGX_OPC_SHL16INSLI, dst, srca, srcb, __LINE__)
+
+#define LD_ADD(dst, addr, adjust) \
+ push_3_buffer(compiler, TILEGX_OPC_LD_ADD, dst, addr, adjust, __LINE__)
+
+#define ST_ADD(src, addr, adjust) \
+ push_3_buffer(compiler, TILEGX_OPC_ST_ADD, src, addr, adjust, __LINE__)
+
+#define LD(dst, addr) \
+ push_2_buffer(compiler, TILEGX_OPC_LD, dst, addr, __LINE__)
+
+#define BFEXTU(dst, src, start, end) \
+ push_4_buffer(compiler, TILEGX_OPC_BFEXTU, dst, src, start, end, __LINE__)
+
+#define BFEXTS(dst, src, start, end) \
+ push_4_buffer(compiler, TILEGX_OPC_BFEXTS, dst, src, start, end, __LINE__)
+
+#define ADD_SOLO(dest, srca, srcb) \
+ push_inst(compiler, ADD_X1 | DEST_X1(dest) | SRCA_X1(srca) | SRCB_X1(srcb))
+
+#define ADDI_SOLO(dest, srca, imm) \
+ push_inst(compiler, ADDI_X1 | DEST_X1(dest) | SRCA_X1(srca) | IMM8_X1(imm))
+
+#define ADDLI_SOLO(dest, srca, imm) \
+ push_inst(compiler, ADDLI_X1 | DEST_X1(dest) | SRCA_X1(srca) | IMM16_X1(imm))
+
+#define SHL16INSLI_SOLO(dest, srca, imm) \
+ push_inst(compiler, SHL16INSLI_X1 | DEST_X1(dest) | SRCA_X1(srca) | IMM16_X1(imm))
+
+#define JALR_SOLO(reg) \
+ push_inst(compiler, JALR_X1 | SRCA_X1(reg))
+
+#define JR_SOLO(reg) \
+ push_inst(compiler, JR_X1 | SRCA_X1(reg))
+
+struct Format {
+ /* Mapping of bundle issue slot to assigned pipe. */
+ tilegx_pipeline pipe[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE];
+
+ /* Mask of pipes used by this bundle. */
+ unsigned int pipe_mask;
+};
+
+const struct Format formats[] =
+{
+ /* In Y format we must always have something in Y2, since it has
+ * no fnop, so this conveys that Y2 must always be used. */
+ BUNDLE_FORMAT(TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y2, NO_PIPELINE),
+ BUNDLE_FORMAT(TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y2, NO_PIPELINE),
+ BUNDLE_FORMAT(TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y0, NO_PIPELINE),
+ BUNDLE_FORMAT(TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y1, NO_PIPELINE),
+
+ /* Y format has three instructions. */
+ BUNDLE_FORMAT(TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y2),
+ BUNDLE_FORMAT(TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y1),
+ BUNDLE_FORMAT(TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y2),
+ BUNDLE_FORMAT(TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y0),
+ BUNDLE_FORMAT(TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y1),
+ BUNDLE_FORMAT(TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y0),
+
+ /* X format has only two instructions. */
+ BUNDLE_FORMAT(TILEGX_PIPELINE_X0, TILEGX_PIPELINE_X1, NO_PIPELINE),
+ BUNDLE_FORMAT(TILEGX_PIPELINE_X1, TILEGX_PIPELINE_X0, NO_PIPELINE)
+};
+
+
+struct jit_instr inst_buf[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE];
+unsigned long inst_buf_index;
+
+tilegx_pipeline get_any_valid_pipe(const struct tilegx_opcode* opcode)
+{
+ /* FIXME: tile: we could pregenerate this. */
+ int pipe;
+ for (pipe = 0; ((opcode->pipes & (1 << pipe)) == 0 && pipe < TILEGX_NUM_PIPELINE_ENCODINGS); pipe++)
+ ;
+ return (tilegx_pipeline)(pipe);
+}
+
+void insert_nop(tilegx_mnemonic opc, int line)
+{
+ const struct tilegx_opcode* opcode = NULL;
+
+ memmove(&inst_buf[1], &inst_buf[0], inst_buf_index * sizeof inst_buf[0]);
+
+ opcode = &tilegx_opcodes[opc];
+ inst_buf[0].opcode = opcode;
+ inst_buf[0].pipe = get_any_valid_pipe(opcode);
+ inst_buf[0].input_registers = 0;
+ inst_buf[0].output_registers = 0;
+ inst_buf[0].line = line;
+ ++inst_buf_index;
+}
+
+const struct Format* compute_format()
+{
+ unsigned int compatible_pipes = BUNDLE_FORMAT_MASK(
+ inst_buf[0].opcode->pipes,
+ inst_buf[1].opcode->pipes,
+ (inst_buf_index == 3 ? inst_buf[2].opcode->pipes : (1 << NO_PIPELINE)));
+
+ const struct Format* match = NULL;
+ const struct Format *b = NULL;
+ unsigned int i = 0;
+ for (i; i < sizeof formats / sizeof formats[0]; i++) {
+ b = &formats[i];
+ if ((b->pipe_mask & compatible_pipes) == b->pipe_mask) {
+ match = b;
+ break;
+ }
+ }
+
+ return match;
+}
+
+sljit_si assign_pipes()
+{
+ unsigned long output_registers = 0;
+ unsigned int i = 0;
+
+ if (inst_buf_index == 1) {
+ tilegx_mnemonic opc = inst_buf[0].opcode->can_bundle
+ ? TILEGX_OPC_FNOP : TILEGX_OPC_NOP;
+ insert_nop(opc, __LINE__);
+ }
+
+ const struct Format* match = compute_format();
+
+ if (match == NULL)
+ return -1;
+
+ for (i = 0; i < inst_buf_index; i++) {
+
+ if ((i > 0) && ((inst_buf[i].input_registers & output_registers) != 0))
+ return -1;
+
+ if ((i > 0) && ((inst_buf[i].output_registers & output_registers) != 0))
+ return -1;
+
+ /* Don't include Rzero in the match set, to avoid triggering
+ needlessly on 'prefetch' instrs. */
+
+ output_registers |= inst_buf[i].output_registers & 0xFFFFFFFFFFFFFFL;
+
+ inst_buf[i].pipe = match->pipe[i];
+ }
+
+ /* If only 2 instrs, and in Y-mode, insert a nop. */
+ if (inst_buf_index == 2 && !tilegx_is_x_pipeline(match->pipe[0])) {
+ insert_nop(TILEGX_OPC_FNOP, __LINE__);
+
+ /* Select the yet unassigned pipe. */
+ tilegx_pipeline pipe = (tilegx_pipeline)(((TILEGX_PIPELINE_Y0
+ + TILEGX_PIPELINE_Y1 + TILEGX_PIPELINE_Y2)
+ - (inst_buf[1].pipe + inst_buf[2].pipe)));
+
+ inst_buf[0].pipe = pipe;
+ }
+
+ return 0;
+}
+
+tilegx_bundle_bits get_bundle_bit(struct jit_instr *inst)
+{
+ int i, val;
+ const struct tilegx_opcode* opcode = inst->opcode;
+ tilegx_bundle_bits bits = opcode->fixed_bit_values[inst->pipe];
+
+ const struct tilegx_operand* operand = NULL;
+ for (i = 0; i < opcode->num_operands; i++) {
+ operand = &tilegx_operands[opcode->operands[inst->pipe][i]];
+ val = inst->operand_value[i];
+
+ bits |= operand->insert(val);
+ }
+
+ return bits;
+}
+
+static sljit_si update_buffer(struct sljit_compiler *compiler)
+{
+ int count;
+ int i;
+ int orig_index = inst_buf_index;
+ struct jit_instr inst0 = inst_buf[0];
+ struct jit_instr inst1 = inst_buf[1];
+ struct jit_instr inst2 = inst_buf[2];
+ tilegx_bundle_bits bits = 0;
+
+ /* If the bundle is valid as is, perform the encoding and return 1. */
+ if (assign_pipes() == 0) {
+ for (i = 0; i < inst_buf_index; i++) {
+ bits |= get_bundle_bit(inst_buf + i);
+#ifdef TILEGX_JIT_DEBUG
+ printf("|%04d", inst_buf[i].line);
+#endif
+ }
+#ifdef TILEGX_JIT_DEBUG
+ if (inst_buf_index == 3)
+ printf("|M0|:\t");
+ else
+ printf("|M0|:\t\t");
+ print_insn_tilegx(&bits);
+#endif
+
+ inst_buf_index = 0;
+
+#ifdef TILEGX_JIT_DEBUG
+ return push_inst_nodebug(compiler, bits);
+#else
+ return push_inst(compiler, bits);
+#endif
+ }
+
+ /* If the bundle is invalid, split it in two. First encode the first two
+ (or possibly 1) instructions, and then the last, separately. Note that
+ assign_pipes may have re-ordered the instrs (by inserting no-ops in
+ lower slots) so we need to reset them. */
+
+ inst_buf_index = orig_index - 1;
+ inst_buf[0] = inst0;
+ inst_buf[1] = inst1;
+ inst_buf[2] = inst2;
+ if (assign_pipes() == 0) {
+ for (i = 0; i < inst_buf_index; i++) {
+ bits |= get_bundle_bit(inst_buf + i);
+#ifdef TILEGX_JIT_DEBUG
+ printf("|%04d", inst_buf[i].line);
+#endif
+ }
+
+#ifdef TILEGX_JIT_DEBUG
+ if (inst_buf_index == 3)
+ printf("|M1|:\t");
+ else
+ printf("|M1|:\t\t");
+ print_insn_tilegx(&bits);
+#endif
+
+ if ((orig_index - 1) == 2) {
+ inst_buf[0] = inst2;
+ inst_buf_index = 1;
+ } else if ((orig_index - 1) == 1) {
+ inst_buf[0] = inst1;
+ inst_buf_index = 1;
+ } else
+ SLJIT_ASSERT_STOP();
+
+#ifdef TILEGX_JIT_DEBUG
+ return push_inst_nodebug(compiler, bits);
+#else
+ return push_inst(compiler, bits);
+#endif
+ } else {
+ /* We had 3 instrs of which the first 2 can't live in the same bundle.
+ Split those two. Note that we don't try to then combine the second
+ and third instr into a single bundle. First instruction: */
+ inst_buf_index = 1;
+ inst_buf[0] = inst0;
+ inst_buf[1] = inst1;
+ inst_buf[2] = inst2;
+ if (assign_pipes() == 0) {
+ for (i = 0; i < inst_buf_index; i++) {
+ bits |= get_bundle_bit(inst_buf + i);
+#ifdef TILEGX_JIT_DEBUG
+ printf("|%04d", inst_buf[i].line);
+#endif
+ }
+
+#ifdef TILEGX_JIT_DEBUG
+ if (inst_buf_index == 3)
+ printf("|M2|:\t");
+ else
+ printf("|M2|:\t\t");
+ print_insn_tilegx(&bits);
+#endif
+
+ inst_buf[0] = inst1;
+ inst_buf[1] = inst2;
+ inst_buf_index = orig_index - 1;
+#ifdef TILEGX_JIT_DEBUG
+ return push_inst_nodebug(compiler, bits);
+#else
+ return push_inst(compiler, bits);
+#endif
+ } else
+ SLJIT_ASSERT_STOP();
+ }
+
+ SLJIT_ASSERT_STOP();
+}
+
+static sljit_si flush_buffer(struct sljit_compiler *compiler)
+{
+ while (inst_buf_index != 0)
+ update_buffer(compiler);
+}
+
+static sljit_si push_4_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int op3, int line)
+{
+ if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE)
+ FAIL_IF(update_buffer(compiler));
+
+ const struct tilegx_opcode* opcode = &tilegx_opcodes[opc];
+ inst_buf[inst_buf_index].opcode = opcode;
+ inst_buf[inst_buf_index].pipe = get_any_valid_pipe(opcode);
+ inst_buf[inst_buf_index].operand_value[0] = op0;
+ inst_buf[inst_buf_index].operand_value[1] = op1;
+ inst_buf[inst_buf_index].operand_value[2] = op2;
+ inst_buf[inst_buf_index].operand_value[3] = op3;
+ inst_buf[inst_buf_index].input_registers = 1L << op1;
+ inst_buf[inst_buf_index].output_registers = 1L << op0;
+ inst_buf[inst_buf_index].line = line;
+ inst_buf_index++;
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_si push_3_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int line)
+{
+ if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE)
+ FAIL_IF(update_buffer(compiler));
+
+ const struct tilegx_opcode* opcode = &tilegx_opcodes[opc];
+ inst_buf[inst_buf_index].opcode = opcode;
+ inst_buf[inst_buf_index].pipe = get_any_valid_pipe(opcode);
+ inst_buf[inst_buf_index].operand_value[0] = op0;
+ inst_buf[inst_buf_index].operand_value[1] = op1;
+ inst_buf[inst_buf_index].operand_value[2] = op2;
+ inst_buf[inst_buf_index].line = line;
+
+ switch (opc) {
+ case TILEGX_OPC_ST_ADD:
+ inst_buf[inst_buf_index].input_registers = (1L << op0) | (1L << op1);
+ inst_buf[inst_buf_index].output_registers = 1L << op0;
+ break;
+ case TILEGX_OPC_LD_ADD:
+ inst_buf[inst_buf_index].input_registers = 1L << op1;
+ inst_buf[inst_buf_index].output_registers = (1L << op0) | (1L << op1);
+ break;
+ case TILEGX_OPC_ADD:
+ case TILEGX_OPC_AND:
+ case TILEGX_OPC_SUB:
+ case TILEGX_OPC_OR:
+ case TILEGX_OPC_XOR:
+ case TILEGX_OPC_NOR:
+ case TILEGX_OPC_SHL:
+ case TILEGX_OPC_SHRU:
+ case TILEGX_OPC_SHRS:
+ case TILEGX_OPC_CMPLTU:
+ case TILEGX_OPC_CMPLTS:
+ case TILEGX_OPC_CMOVEQZ:
+ case TILEGX_OPC_CMOVNEZ:
+ inst_buf[inst_buf_index].input_registers = (1L << op1) | (1L << op2);
+ inst_buf[inst_buf_index].output_registers = 1L << op0;
+ break;
+ case TILEGX_OPC_ADDLI:
+ case TILEGX_OPC_XORI:
+ case TILEGX_OPC_ORI:
+ case TILEGX_OPC_SHLI:
+ case TILEGX_OPC_SHRUI:
+ case TILEGX_OPC_SHRSI:
+ case TILEGX_OPC_SHL16INSLI:
+ case TILEGX_OPC_CMPLTUI:
+ case TILEGX_OPC_CMPLTSI:
+ inst_buf[inst_buf_index].input_registers = 1L << op1;
+ inst_buf[inst_buf_index].output_registers = 1L << op0;
+ break;
+ default:
+ printf("unrecoginzed opc: %s\n", opcode->name);
+ SLJIT_ASSERT_STOP();
+ }
+
+ inst_buf_index++;
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_si push_2_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int line)
+{
+ if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE)
+ FAIL_IF(update_buffer(compiler));
+
+ const struct tilegx_opcode* opcode = &tilegx_opcodes[opc];
+ inst_buf[inst_buf_index].opcode = opcode;
+ inst_buf[inst_buf_index].pipe = get_any_valid_pipe(opcode);
+ inst_buf[inst_buf_index].operand_value[0] = op0;
+ inst_buf[inst_buf_index].operand_value[1] = op1;
+ inst_buf[inst_buf_index].line = line;
+
+ switch (opc) {
+ case TILEGX_OPC_BEQZ:
+ case TILEGX_OPC_BNEZ:
+ inst_buf[inst_buf_index].input_registers = 1L << op0;
+ break;
+ case TILEGX_OPC_ST:
+ case TILEGX_OPC_ST1:
+ case TILEGX_OPC_ST2:
+ case TILEGX_OPC_ST4:
+ inst_buf[inst_buf_index].input_registers = (1L << op0) | (1L << op1);
+ inst_buf[inst_buf_index].output_registers = 0;
+ break;
+ case TILEGX_OPC_CLZ:
+ case TILEGX_OPC_LD:
+ case TILEGX_OPC_LD1U:
+ case TILEGX_OPC_LD1S:
+ case TILEGX_OPC_LD2U:
+ case TILEGX_OPC_LD2S:
+ case TILEGX_OPC_LD4U:
+ case TILEGX_OPC_LD4S:
+ inst_buf[inst_buf_index].input_registers = 1L << op1;
+ inst_buf[inst_buf_index].output_registers = 1L << op0;
+ break;
+ default:
+ printf("unrecoginzed opc: %s\n", opcode->name);
+ SLJIT_ASSERT_STOP();
+ }
+
+ inst_buf_index++;
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_si push_0_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int line)
+{
+ if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE)
+ FAIL_IF(update_buffer(compiler));
+
+ const struct tilegx_opcode* opcode = &tilegx_opcodes[opc];
+ inst_buf[inst_buf_index].opcode = opcode;
+ inst_buf[inst_buf_index].pipe = get_any_valid_pipe(opcode);
+ inst_buf[inst_buf_index].input_registers = 0;
+ inst_buf[inst_buf_index].output_registers = 0;
+ inst_buf[inst_buf_index].line = line;
+ inst_buf_index++;
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_si push_jr_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int line)
+{
+ if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE)
+ FAIL_IF(update_buffer(compiler));
+
+ const struct tilegx_opcode* opcode = &tilegx_opcodes[opc];
+ inst_buf[inst_buf_index].opcode = opcode;
+ inst_buf[inst_buf_index].pipe = get_any_valid_pipe(opcode);
+ inst_buf[inst_buf_index].operand_value[0] = op0;
+ inst_buf[inst_buf_index].input_registers = 1L << op0;
+ inst_buf[inst_buf_index].output_registers = 0;
+ inst_buf[inst_buf_index].line = line;
+ inst_buf_index++;
+
+ return flush_buffer(compiler);
+}
+
+static SLJIT_INLINE sljit_ins * detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
+{
+ sljit_sw diff;
+ sljit_uw target_addr;
+ sljit_ins *inst;
+ sljit_ins saved_inst;
+
+ if (jump->flags & SLJIT_REWRITABLE_JUMP)
+ return code_ptr;
+
+ if (jump->flags & JUMP_ADDR)
+ target_addr = jump->u.target;
+ else {
+ SLJIT_ASSERT(jump->flags & JUMP_LABEL);
+ target_addr = (sljit_uw)(code + jump->u.label->size);
+ }
+
+ inst = (sljit_ins *)jump->addr;
+ if (jump->flags & IS_COND)
+ inst--;
+
+ diff = ((sljit_sw) target_addr - (sljit_sw) inst) >> 3;
+ if (diff <= SIMM_17BIT_MAX && diff >= SIMM_17BIT_MIN) {
+ jump->flags |= PATCH_B;
+
+ if (!(jump->flags & IS_COND)) {
+ if (jump->flags & IS_JAL) {
+ jump->flags &= ~(PATCH_B);
+ jump->flags |= PATCH_J;
+ inst[0] = JAL_X1;
+
+#ifdef TILEGX_JIT_DEBUG
+ printf("[runtime relocate]%04d:\t", __LINE__);
+ print_insn_tilegx(inst);
+#endif
+ } else {
+ inst[0] = BEQZ_X1 | SRCA_X1(ZERO);
+
+#ifdef TILEGX_JIT_DEBUG
+ printf("[runtime relocate]%04d:\t", __LINE__);
+ print_insn_tilegx(inst);
+#endif
+ }
+
+ return inst;
+ }
+
+ inst[0] = inst[0] ^ (0x7L << 55);
+
+#ifdef TILEGX_JIT_DEBUG
+ printf("[runtime relocate]%04d:\t", __LINE__);
+ print_insn_tilegx(inst);
+#endif
+ jump->addr -= sizeof(sljit_ins);
+ return inst;
+ }
+
+ if (jump->flags & IS_COND) {
+ if ((target_addr & ~0x3FFFFFFFL) == ((jump->addr + sizeof(sljit_ins)) & ~0x3FFFFFFFL)) {
+ jump->flags |= PATCH_J;
+ inst[0] = (inst[0] & ~(BOFF_X1(-1))) | BOFF_X1(2);
+ inst[1] = J_X1;
+ return inst + 1;
+ }
+
+ return code_ptr;
+ }
+
+ if ((target_addr & ~0x3FFFFFFFL) == ((jump->addr + sizeof(sljit_ins)) & ~0x3FFFFFFFL)) {
+ jump->flags |= PATCH_J;
+
+ if (jump->flags & IS_JAL) {
+ inst[0] = JAL_X1;
+
+#ifdef TILEGX_JIT_DEBUG
+ printf("[runtime relocate]%04d:\t", __LINE__);
+ print_insn_tilegx(inst);
+#endif
+
+ } else {
+ inst[0] = J_X1;
+
+#ifdef TILEGX_JIT_DEBUG
+ printf("[runtime relocate]%04d:\t", __LINE__);
+ print_insn_tilegx(inst);
+#endif
+ }
+
+ return inst;
+ }
+
+ return code_ptr;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void * sljit_generate_code(struct sljit_compiler *compiler)
+{
+ struct sljit_memory_fragment *buf;
+ sljit_ins *code;
+ sljit_ins *code_ptr;
+ sljit_ins *buf_ptr;
+ sljit_ins *buf_end;
+ sljit_uw word_count;
+ sljit_uw addr;
+
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ struct sljit_const *const_;
+
+ CHECK_ERROR_PTR();
+ check_sljit_generate_code(compiler);
+ reverse_buf(compiler);
+
+ code = (sljit_ins *)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins));
+ PTR_FAIL_WITH_EXEC_IF(code);
+ buf = compiler->buf;
+
+ code_ptr = code;
+ word_count = 0;
+ label = compiler->labels;
+ jump = compiler->jumps;
+ const_ = compiler->consts;
+ do {
+ buf_ptr = (sljit_ins *)buf->memory;
+ buf_end = buf_ptr + (buf->used_size >> 3);
+ do {
+ *code_ptr = *buf_ptr++;
+ SLJIT_ASSERT(!label || label->size >= word_count);
+ SLJIT_ASSERT(!jump || jump->addr >= word_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+ /* These structures are ordered by their address. */
+ if (label && label->size == word_count) {
+ /* Just recording the address. */
+ label->addr = (sljit_uw) code_ptr;
+ label->size = code_ptr - code;
+ label = label->next;
+ }
+
+ if (jump && jump->addr == word_count) {
+ if (jump->flags & IS_JAL)
+ jump->addr = (sljit_uw)(code_ptr - 4);
+ else
+ jump->addr = (sljit_uw)(code_ptr - 3);
+
+ code_ptr = detect_jump_type(jump, code_ptr, code);
+ jump = jump->next;
+ }
+
+ if (const_ && const_->addr == word_count) {
+ /* Just recording the address. */
+ const_->addr = (sljit_uw) code_ptr;
+ const_ = const_->next;
+ }
+
+ code_ptr++;
+ word_count++;
+ } while (buf_ptr < buf_end);
+
+ buf = buf->next;
+ } while (buf);
+
+ if (label && label->size == word_count) {
+ label->addr = (sljit_uw) code_ptr;
+ label->size = code_ptr - code;
+ label = label->next;
+ }
+
+ SLJIT_ASSERT(!label);
+ SLJIT_ASSERT(!jump);
+ SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
+
+ jump = compiler->jumps;
+ while (jump) {
+ do {
+ addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
+ buf_ptr = (sljit_ins *)jump->addr;
+
+ if (jump->flags & PATCH_B) {
+ addr = (sljit_sw)(addr - (jump->addr)) >> 3;
+ SLJIT_ASSERT((sljit_sw) addr <= SIMM_17BIT_MAX && (sljit_sw) addr >= SIMM_17BIT_MIN);
+ buf_ptr[0] = (buf_ptr[0] & ~(BOFF_X1(-1))) | BOFF_X1(addr);
+
+#ifdef TILEGX_JIT_DEBUG
+ printf("[runtime relocate]%04d:\t", __LINE__);
+ print_insn_tilegx(buf_ptr);
+#endif
+ break;
+ }
+
+ if (jump->flags & PATCH_J) {
+ SLJIT_ASSERT((addr & ~0x3FFFFFFFL) == ((jump->addr + sizeof(sljit_ins)) & ~0x3FFFFFFFL));
+ addr = (sljit_sw)(addr - (jump->addr)) >> 3;
+ buf_ptr[0] = (buf_ptr[0] & ~(JOFF_X1(-1))) | JOFF_X1(addr);
+
+#ifdef TILEGX_JIT_DEBUG
+ printf("[runtime relocate]%04d:\t", __LINE__);
+ print_insn_tilegx(buf_ptr);
+#endif
+ break;
+ }
+
+ SLJIT_ASSERT(!(jump->flags & IS_JAL));
+
+ /* Set the fields of immediate loads. */
+ buf_ptr[0] = (buf_ptr[0] & ~(0xFFFFL << 43)) | (((addr >> 32) & 0xFFFFL) << 43);
+ buf_ptr[1] = (buf_ptr[1] & ~(0xFFFFL << 43)) | (((addr >> 16) & 0xFFFFL) << 43);
+ buf_ptr[2] = (buf_ptr[2] & ~(0xFFFFL << 43)) | ((addr & 0xFFFFL) << 43);
+ } while (0);
+
+ jump = jump->next;
+ }
+
+ compiler->error = SLJIT_ERR_COMPILED;
+ compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
+ SLJIT_CACHE_FLUSH(code, code_ptr);
+ return code;
+}
+
+static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm)
+{
+
+ if (imm <= SIMM_16BIT_MAX && imm >= SIMM_16BIT_MIN)
+ return ADDLI(dst_ar, ZERO, imm);
+
+ if (imm <= SIMM_32BIT_MAX && imm >= SIMM_32BIT_MIN) {
+ FAIL_IF(ADDLI(dst_ar, ZERO, imm >> 16));
+ return SHL16INSLI(dst_ar, dst_ar, imm);
+ }
+
+ if (imm <= SIMM_48BIT_MAX && imm >= SIMM_48BIT_MIN) {
+ FAIL_IF(ADDLI(dst_ar, ZERO, imm >> 32));
+ FAIL_IF(SHL16INSLI(dst_ar, dst_ar, imm >> 16));
+ return SHL16INSLI(dst_ar, dst_ar, imm);
+ }
+
+ FAIL_IF(ADDLI(dst_ar, ZERO, imm >> 48));
+ FAIL_IF(SHL16INSLI(dst_ar, dst_ar, imm >> 32));
+ FAIL_IF(SHL16INSLI(dst_ar, dst_ar, imm >> 16));
+ return SHL16INSLI(dst_ar, dst_ar, imm);
+}
+
+static sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm, int flush)
+{
+ /* Should *not* be optimized as load_immediate, as pcre relocation
+ mechanism will match this fixed 4-instruction pattern. */
+ if (flush) {
+ FAIL_IF(ADDLI_SOLO(dst_ar, ZERO, imm >> 32));
+ FAIL_IF(SHL16INSLI_SOLO(dst_ar, dst_ar, imm >> 16));
+ return SHL16INSLI_SOLO(dst_ar, dst_ar, imm);
+ }
+
+ FAIL_IF(ADDLI(dst_ar, ZERO, imm >> 32));
+ FAIL_IF(SHL16INSLI(dst_ar, dst_ar, imm >> 16));
+ return SHL16INSLI(dst_ar, dst_ar, imm);
+}
+
+static sljit_si emit_const_64(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm, int flush)
+{
+ /* Should *not* be optimized as load_immediate, as pcre relocation
+ mechanism will match this fixed 4-instruction pattern. */
+ if (flush) {
+ FAIL_IF(ADDLI_SOLO(reg_map[dst_ar], ZERO, imm >> 48));
+ FAIL_IF(SHL16INSLI_SOLO(reg_map[dst_ar], reg_map[dst_ar], imm >> 32));
+ FAIL_IF(SHL16INSLI_SOLO(reg_map[dst_ar], reg_map[dst_ar], imm >> 16));
+ return SHL16INSLI_SOLO(reg_map[dst_ar], reg_map[dst_ar], imm);
+ }
+
+ FAIL_IF(ADDLI(reg_map[dst_ar], ZERO, imm >> 48));
+ FAIL_IF(SHL16INSLI(reg_map[dst_ar], reg_map[dst_ar], imm >> 32));
+ FAIL_IF(SHL16INSLI(reg_map[dst_ar], reg_map[dst_ar], imm >> 16));
+ return SHL16INSLI(reg_map[dst_ar], reg_map[dst_ar], imm);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
+{
+ sljit_ins base;
+ sljit_ins bundle = 0;
+
+ CHECK_ERROR();
+ check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
+
+ compiler->scratches = scratches;
+ compiler->saveds = saveds;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->logical_local_size = local_size;
+#endif
+
+ local_size += (saveds + 1) * sizeof(sljit_sw);
+ local_size = (local_size + 7) & ~7;
+ compiler->local_size = local_size;
+
+ if (local_size <= SIMM_16BIT_MAX) {
+ /* Frequent case. */
+ FAIL_IF(ADDLI(SLJIT_LOCALS_REG_mapped, SLJIT_LOCALS_REG_mapped, -local_size));
+ base = SLJIT_LOCALS_REG_mapped;
+ } else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1_mapped, local_size));
+ FAIL_IF(ADD(TMP_REG2_mapped, SLJIT_LOCALS_REG_mapped, ZERO));
+ FAIL_IF(SUB(SLJIT_LOCALS_REG_mapped, SLJIT_LOCALS_REG_mapped, TMP_REG1_mapped));
+ base = TMP_REG2_mapped;
+ local_size = 0;
+ }
+
+ FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 8));
+ FAIL_IF(ST_ADD(ADDR_TMP_mapped, RA, -8));
+
+ if (saveds >= 1)
+ FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_REG1_mapped, -8));
+
+ if (saveds >= 2)
+ FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_REG2_mapped, -8));
+
+ if (saveds >= 3)
+ FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_REG3_mapped, -8));
+
+ if (saveds >= 4)
+ FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_EREG1_mapped, -8));
+
+ if (saveds >= 5)
+ FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_EREG2_mapped, -8));
+
+ if (args >= 1)
+ FAIL_IF(ADD(SLJIT_SAVED_REG1_mapped, 0, ZERO));
+
+ if (args >= 2)
+ FAIL_IF(ADD(SLJIT_SAVED_REG2_mapped, 1, ZERO));
+
+ if (args >= 3)
+ FAIL_IF(ADD(SLJIT_SAVED_REG3_mapped, 2, ZERO));
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
+{
+ CHECK_ERROR_VOID();
+ check_sljit_set_context(compiler, args, scratches, saveds, local_size);
+
+ compiler->scratches = scratches;
+ compiler->saveds = saveds;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->logical_local_size = local_size;
+#endif
+
+ local_size += (saveds + 1) * sizeof(sljit_sw);
+ compiler->local_size = (local_size + 7) & ~7;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
+{
+ sljit_si local_size;
+ sljit_ins base;
+ int addr_initialized = 0;
+
+ CHECK_ERROR();
+ check_sljit_emit_return(compiler, op, src, srcw);
+
+ FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
+
+ local_size = compiler->local_size;
+ if (local_size <= SIMM_16BIT_MAX)
+ base = SLJIT_LOCALS_REG_mapped;
+ else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1_mapped, local_size));
+ FAIL_IF(ADD(TMP_REG1_mapped, SLJIT_LOCALS_REG_mapped, TMP_REG1_mapped));
+ base = TMP_REG1_mapped;
+ local_size = 0;
+ }
+
+ FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 8));
+ FAIL_IF(LD(RA, ADDR_TMP_mapped));
+
+ if (compiler->saveds >= 5) {
+ FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 48));
+ addr_initialized = 1;
+
+ FAIL_IF(LD_ADD(SLJIT_SAVED_EREG2_mapped, ADDR_TMP_mapped, 8));
+ }
+
+ if (compiler->saveds >= 4) {
+ if (addr_initialized == 0) {
+ FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 40));
+ addr_initialized = 1;
+ }
+
+ FAIL_IF(LD_ADD(SLJIT_SAVED_EREG1_mapped, ADDR_TMP_mapped, 8));
+ }
+
+ if (compiler->saveds >= 3) {
+ if (addr_initialized == 0) {
+ FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 32));
+ addr_initialized = 1;
+ }
+
+ FAIL_IF(LD_ADD(SLJIT_SAVED_REG3_mapped, ADDR_TMP_mapped, 8));
+ }
+
+ if (compiler->saveds >= 2) {
+ if (addr_initialized == 0) {
+ FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 24));
+ addr_initialized = 1;
+ }
+
+ FAIL_IF(LD_ADD(SLJIT_SAVED_REG2_mapped, ADDR_TMP_mapped, 8));
+ }
+
+ if (compiler->saveds >= 1) {
+ if (addr_initialized == 0) {
+ FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 16));
+ /* addr_initialized = 1; no need to initialize as it's the last one. */
+ }
+
+ FAIL_IF(LD_ADD(SLJIT_SAVED_REG1_mapped, ADDR_TMP_mapped, 8));
+ }
+
+ if (compiler->local_size <= SIMM_16BIT_MAX)
+ FAIL_IF(ADDLI(SLJIT_LOCALS_REG_mapped, SLJIT_LOCALS_REG_mapped, compiler->local_size));
+ else
+ FAIL_IF(ADD(SLJIT_LOCALS_REG_mapped, TMP_REG1_mapped, ZERO));
+
+ return JR(RA);
+}
+
+/* reg_ar is an absoulute register! */
+
+/* Can perform an operation using at most 1 instruction. */
+static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg_ar, sljit_si arg, sljit_sw argw)
+{
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+
+ if ((!(flags & WRITE_BACK) || !(arg & REG_MASK))
+ && !(arg & OFFS_REG_MASK) && argw <= SIMM_16BIT_MAX && argw >= SIMM_16BIT_MIN) {
+ /* Works for both absoulte and relative addresses. */
+ if (SLJIT_UNLIKELY(flags & ARG_TEST))
+ return 1;
+
+ FAIL_IF(ADDLI(ADDR_TMP_mapped, reg_map[arg & REG_MASK], argw));
+
+ if (flags & LOAD_DATA)
+ FAIL_IF(PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, ADDR_TMP_mapped));
+ else
+ FAIL_IF(PB2(data_transfer_insts[flags & MEM_MASK], ADDR_TMP_mapped, reg_ar));
+
+ return -1;
+ }
+
+ return 0;
+}
+
+/* See getput_arg below.
+ Note: can_cache is called only for binary operators. Those
+ operators always uses word arguments without write back. */
+static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
+{
+ SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
+
+ /* Simple operation except for updates. */
+ if (arg & OFFS_REG_MASK) {
+ argw &= 0x3;
+ next_argw &= 0x3;
+ if (argw && argw == next_argw
+ && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))
+ return 1;
+ return 0;
+ }
+
+ if (arg == next_arg) {
+ if (((next_argw - argw) <= SIMM_16BIT_MAX
+ && (next_argw - argw) >= SIMM_16BIT_MIN))
+ return 1;
+
+ return 0;
+ }
+
+ return 0;
+}
+
+/* Emit the necessary instructions. See can_cache above. */
+static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg_ar, sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
+{
+ sljit_si tmp_ar, base;
+
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+ if (!(next_arg & SLJIT_MEM)) {
+ next_arg = 0;
+ next_argw = 0;
+ }
+
+ if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA))
+ tmp_ar = reg_ar;
+ else
+ tmp_ar = TMP_REG1_mapped;
+
+ base = arg & REG_MASK;
+
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+ argw &= 0x3;
+
+ if ((flags & WRITE_BACK) && reg_ar == reg_map[base]) {
+ SLJIT_ASSERT(!(flags & LOAD_DATA) && reg_map[TMP_REG1] != reg_ar);
+ FAIL_IF(ADD(TMP_REG1_mapped, reg_ar, ZERO));
+ reg_ar = TMP_REG1_mapped;
+ }
+
+ /* Using the cache. */
+ if (argw == compiler->cache_argw) {
+ if (!(flags & WRITE_BACK)) {
+ if (arg == compiler->cache_arg) {
+ if (flags & LOAD_DATA)
+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped);
+ else
+ return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar);
+ }
+
+ if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
+ if (arg == next_arg && argw == (next_argw & 0x3)) {
+ compiler->cache_arg = arg;
+ compiler->cache_argw = argw;
+ FAIL_IF(ADD(TMP_REG3_mapped, reg_map[base], TMP_REG3_mapped));
+ if (flags & LOAD_DATA)
+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped);
+ else
+ return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar);
+ }
+
+ FAIL_IF(ADD(tmp_ar, reg_map[base], TMP_REG3_mapped));
+ if (flags & LOAD_DATA)
+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, tmp_ar);
+ else
+ return PB2(data_transfer_insts[flags & MEM_MASK], tmp_ar, reg_ar);
+ }
+ } else {
+ if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
+ FAIL_IF(ADD(reg_map[base], reg_map[base], TMP_REG3_mapped));
+ if (flags & LOAD_DATA)
+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, reg_map[base]);
+ else
+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_map[base], reg_ar);
+ }
+ }
+ }
+
+ if (SLJIT_UNLIKELY(argw)) {
+ compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);
+ compiler->cache_argw = argw;
+ FAIL_IF(SHLI(TMP_REG3_mapped, reg_map[OFFS_REG(arg)], argw));
+ }
+
+ if (!(flags & WRITE_BACK)) {
+ if (arg == next_arg && argw == (next_argw & 0x3)) {
+ compiler->cache_arg = arg;
+ compiler->cache_argw = argw;
+ FAIL_IF(ADD(TMP_REG3_mapped, reg_map[base], reg_map[!argw ? OFFS_REG(arg) : TMP_REG3]));
+ tmp_ar = TMP_REG3_mapped;
+ } else
+ FAIL_IF(ADD(tmp_ar, reg_map[base], reg_map[!argw ? OFFS_REG(arg) : TMP_REG3]));
+
+ if (flags & LOAD_DATA)
+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, tmp_ar);
+ else
+ return PB2(data_transfer_insts[flags & MEM_MASK], tmp_ar, reg_ar);
+ }
+
+ FAIL_IF(ADD(reg_map[base], reg_map[base], reg_map[!argw ? OFFS_REG(arg) : TMP_REG3]));
+
+ if (flags & LOAD_DATA)
+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, reg_map[base]);
+ else
+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_map[base], reg_ar);
+ }
+
+ if (SLJIT_UNLIKELY(flags & WRITE_BACK) && base) {
+ /* Update only applies if a base register exists. */
+ if (reg_ar == reg_map[base]) {
+ SLJIT_ASSERT(!(flags & LOAD_DATA) && TMP_REG1_mapped != reg_ar);
+ if (argw <= SIMM_16BIT_MAX && argw >= SIMM_16BIT_MIN) {
+ FAIL_IF(ADDLI(ADDR_TMP_mapped, reg_map[base], argw));
+ if (flags & LOAD_DATA)
+ FAIL_IF(PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, ADDR_TMP_mapped));
+ else
+ FAIL_IF(PB2(data_transfer_insts[flags & MEM_MASK], ADDR_TMP_mapped, reg_ar));
+
+ if (argw)
+ return ADDLI(reg_map[base], reg_map[base], argw);
+
+ return SLJIT_SUCCESS;
+ }
+
+ FAIL_IF(ADD(TMP_REG1_mapped, reg_ar, ZERO));
+ reg_ar = TMP_REG1_mapped;
+ }
+
+ if (argw <= SIMM_16BIT_MAX && argw >= SIMM_16BIT_MIN) {
+ if (argw)
+ FAIL_IF(ADDLI(reg_map[base], reg_map[base], argw));
+ } else {
+ if (compiler->cache_arg == SLJIT_MEM
+ && argw - compiler->cache_argw <= SIMM_16BIT_MAX
+ && argw - compiler->cache_argw >= SIMM_16BIT_MIN) {
+ if (argw != compiler->cache_argw) {
+ FAIL_IF(ADD(TMP_REG3_mapped, TMP_REG3_mapped, argw - compiler->cache_argw));
+ compiler->cache_argw = argw;
+ }
+
+ FAIL_IF(ADD(reg_map[base], reg_map[base], TMP_REG3_mapped));
+ } else {
+ compiler->cache_arg = SLJIT_MEM;
+ compiler->cache_argw = argw;
+ FAIL_IF(load_immediate(compiler, TMP_REG3_mapped, argw));
+ FAIL_IF(ADD(reg_map[base], reg_map[base], TMP_REG3_mapped));
+ }
+ }
+
+ if (flags & LOAD_DATA)
+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, reg_map[base]);
+ else
+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_map[base], reg_ar);
+ }
+
+ if (compiler->cache_arg == arg
+ && argw - compiler->cache_argw <= SIMM_16BIT_MAX
+ && argw - compiler->cache_argw >= SIMM_16BIT_MIN) {
+ if (argw != compiler->cache_argw) {
+ FAIL_IF(ADDLI(TMP_REG3_mapped, TMP_REG3_mapped, argw - compiler->cache_argw));
+ compiler->cache_argw = argw;
+ }
+
+ if (flags & LOAD_DATA)
+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped);
+ else
+ return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar);
+ }
+
+ if (compiler->cache_arg == SLJIT_MEM
+ && argw - compiler->cache_argw <= SIMM_16BIT_MAX
+ && argw - compiler->cache_argw >= SIMM_16BIT_MIN) {
+ if (argw != compiler->cache_argw)
+ FAIL_IF(ADDLI(TMP_REG3_mapped, TMP_REG3_mapped, argw - compiler->cache_argw));
+ } else {
+ compiler->cache_arg = SLJIT_MEM;
+ FAIL_IF(load_immediate(compiler, TMP_REG3_mapped, argw));
+ }
+
+ compiler->cache_argw = argw;
+
+ if (!base) {
+ if (flags & LOAD_DATA)
+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped);
+ else
+ return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar);
+ }
+
+ if (arg == next_arg
+ && next_argw - argw <= SIMM_16BIT_MAX
+ && next_argw - argw >= SIMM_16BIT_MIN) {
+ compiler->cache_arg = arg;
+ FAIL_IF(ADD(TMP_REG3_mapped, TMP_REG3_mapped, reg_map[base]));
+ if (flags & LOAD_DATA)
+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped);
+ else
+ return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar);
+ }
+
+ FAIL_IF(ADD(tmp_ar, TMP_REG3_mapped, reg_map[base]));
+
+ if (flags & LOAD_DATA)
+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, tmp_ar);
+ else
+ return PB2(data_transfer_insts[flags & MEM_MASK], tmp_ar, reg_ar);
+}
+
+static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg_ar, sljit_si arg, sljit_sw argw)
+{
+ if (getput_arg_fast(compiler, flags, reg_ar, arg, argw))
+ return compiler->error;
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+ return getput_arg(compiler, flags, reg_ar, arg, argw, 0, 0);
+}
+
+static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg1, sljit_sw arg1w, sljit_si arg2, sljit_sw arg2w)
+{
+ if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
+ return compiler->error;
+ return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
+{
+ CHECK_ERROR();
+ check_sljit_emit_fast_enter(compiler, dst, dstw);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ /* For UNUSED dst. Uncommon, but possible. */
+ if (dst == SLJIT_UNUSED)
+ return SLJIT_SUCCESS;
+
+ if (FAST_IS_REG(dst))
+ return ADD(reg_map[dst], RA, ZERO);
+
+ /* Memory. */
+ return emit_op_mem(compiler, WORD_DATA, RA, dst, dstw);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ check_sljit_emit_fast_return(compiler, src, srcw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (FAST_IS_REG(src))
+ FAIL_IF(ADD(RA, reg_map[src], ZERO));
+
+ else if (src & SLJIT_MEM)
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RA, src, srcw));
+
+ else if (src & SLJIT_IMM)
+ FAIL_IF(load_immediate(compiler, RA, srcw));
+
+ return JR(RA);
+}
+
+static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags, sljit_si dst, sljit_si src1, sljit_sw src2)
+{
+ sljit_si overflow_ra = 0;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if (dst != src2)
+ return ADD(reg_map[dst], reg_map[src2], ZERO);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_UI:
+ case SLJIT_MOV_SI:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ if (op == SLJIT_MOV_SI)
+ return BFEXTS(reg_map[dst], reg_map[src2], 0, 31);
+
+ return BFEXTU(reg_map[dst], reg_map[src2], 0, 31);
+ } else if (dst != src2)
+ SLJIT_ASSERT_STOP();
+
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_UB:
+ case SLJIT_MOV_SB:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ if (op == SLJIT_MOV_SB)
+ return BFEXTS(reg_map[dst], reg_map[src2], 0, 7);
+
+ return BFEXTU(reg_map[dst], reg_map[src2], 0, 7);
+ } else if (dst != src2)
+ SLJIT_ASSERT_STOP();
+
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_UH:
+ case SLJIT_MOV_SH:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ if (op == SLJIT_MOV_SH)
+ return BFEXTS(reg_map[dst], reg_map[src2], 0, 15);
+
+ return BFEXTU(reg_map[dst], reg_map[src2], 0, 15);
+ } else if (dst != src2)
+ SLJIT_ASSERT_STOP();
+
+ return SLJIT_SUCCESS;
+
+ case SLJIT_NOT:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if (op & SLJIT_SET_E)
+ FAIL_IF(NOR(EQUAL_FLAG, reg_map[src2], reg_map[src2]));
+ if (CHECK_FLAGS(SLJIT_SET_E))
+ FAIL_IF(NOR(reg_map[dst], reg_map[src2], reg_map[src2]));
+
+ return SLJIT_SUCCESS;
+
+ case SLJIT_CLZ:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if (op & SLJIT_SET_E)
+ FAIL_IF(CLZ(EQUAL_FLAG, reg_map[src2]));
+ if (CHECK_FLAGS(SLJIT_SET_E))
+ FAIL_IF(CLZ(reg_map[dst], reg_map[src2]));
+
+ return SLJIT_SUCCESS;
+
+ case SLJIT_ADD:
+ if (flags & SRC2_IMM) {
+ if (op & SLJIT_SET_O) {
+ FAIL_IF(SHRUI(TMP_EREG1, reg_map[src1], 63));
+ if (src2 < 0)
+ FAIL_IF(XORI(TMP_EREG1, TMP_EREG1, 1));
+ }
+
+ if (op & SLJIT_SET_E)
+ FAIL_IF(ADDLI(EQUAL_FLAG, reg_map[src1], src2));
+
+ if (op & SLJIT_SET_C) {
+ if (src2 >= 0)
+ FAIL_IF(ORI(ULESS_FLAG ,reg_map[src1], src2));
+ else {
+ FAIL_IF(ADDLI(ULESS_FLAG ,ZERO, src2));
+ FAIL_IF(OR(ULESS_FLAG,reg_map[src1],ULESS_FLAG));
+ }
+ }
+
+ /* dst may be the same as src1 or src2. */
+ if (CHECK_FLAGS(SLJIT_SET_E))
+ FAIL_IF(ADDLI(reg_map[dst], reg_map[src1], src2));
+
+ if (op & SLJIT_SET_O) {
+ FAIL_IF(SHRUI(OVERFLOW_FLAG, reg_map[dst], 63));
+
+ if (src2 < 0)
+ FAIL_IF(XORI(OVERFLOW_FLAG, OVERFLOW_FLAG, 1));
+ }
+ } else {
+ if (op & SLJIT_SET_O) {
+ FAIL_IF(XOR(TMP_EREG1, reg_map[src1], reg_map[src2]));
+ FAIL_IF(SHRUI(TMP_EREG1, TMP_EREG1, 63));
+
+ if (src1 != dst)
+ overflow_ra = reg_map[src1];
+ else if (src2 != dst)
+ overflow_ra = reg_map[src2];
+ else {
+ /* Rare ocasion. */
+ FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO));
+ overflow_ra = TMP_EREG2;
+ }
+ }
+
+ if (op & SLJIT_SET_E)
+ FAIL_IF(ADD(EQUAL_FLAG ,reg_map[src1], reg_map[src2]));
+
+ if (op & SLJIT_SET_C)
+ FAIL_IF(OR(ULESS_FLAG,reg_map[src1], reg_map[src2]));
+
+ /* dst may be the same as src1 or src2. */
+ if (CHECK_FLAGS(SLJIT_SET_E))
+ FAIL_IF(ADD(reg_map[dst],reg_map[src1], reg_map[src2]));
+
+ if (op & SLJIT_SET_O) {
+ FAIL_IF(XOR(OVERFLOW_FLAG,reg_map[dst], overflow_ra));
+ FAIL_IF(SHRUI(OVERFLOW_FLAG, OVERFLOW_FLAG, 63));
+ }
+ }
+
+ /* a + b >= a | b (otherwise, the carry should be set to 1). */
+ if (op & SLJIT_SET_C)
+ FAIL_IF(CMPLTU(ULESS_FLAG ,reg_map[dst] ,ULESS_FLAG));
+
+ if (op & SLJIT_SET_O)
+ return CMOVNEZ(OVERFLOW_FLAG, TMP_EREG1, ZERO);
+
+ return SLJIT_SUCCESS;
+
+ case SLJIT_ADDC:
+ if (flags & SRC2_IMM) {
+ if (op & SLJIT_SET_C) {
+ if (src2 >= 0)
+ FAIL_IF(ORI(TMP_EREG1, reg_map[src1], src2));
+ else {
+ FAIL_IF(ADDLI(TMP_EREG1, ZERO, src2));
+ FAIL_IF(OR(TMP_EREG1, reg_map[src1], TMP_EREG1));
+ }
+ }
+
+ FAIL_IF(ADDLI(reg_map[dst], reg_map[src1], src2));
+
+ } else {
+ if (op & SLJIT_SET_C)
+ FAIL_IF(OR(TMP_EREG1, reg_map[src1], reg_map[src2]));
+
+ /* dst may be the same as src1 or src2. */
+ FAIL_IF(ADD(reg_map[dst], reg_map[src1], reg_map[src2]));
+ }
+
+ if (op & SLJIT_SET_C)
+ FAIL_IF(CMPLTU(TMP_EREG1, reg_map[dst], TMP_EREG1));
+
+ FAIL_IF(ADD(reg_map[dst], reg_map[dst], ULESS_FLAG));
+
+ if (!(op & SLJIT_SET_C))
+ return SLJIT_SUCCESS;
+
+ /* Set TMP_EREG2 (dst == 0) && (ULESS_FLAG == 1). */
+ FAIL_IF(CMPLTUI(TMP_EREG2, reg_map[dst], 1));
+ FAIL_IF(AND(TMP_EREG2, TMP_EREG2, ULESS_FLAG));
+ /* Set carry flag. */
+ return OR(ULESS_FLAG, TMP_EREG2, TMP_EREG1);
+
+ case SLJIT_SUB:
+ if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_16BIT_MIN)) {
+ FAIL_IF(ADDLI(TMP_REG2_mapped, ZERO, src2));
+ src2 = TMP_REG2;
+ flags &= ~SRC2_IMM;
+ }
+
+ if (flags & SRC2_IMM) {
+ if (op & SLJIT_SET_O) {
+ FAIL_IF(SHRUI(TMP_EREG1,reg_map[src1], 63));
+
+ if (src2 < 0)
+ FAIL_IF(XORI(TMP_EREG1, TMP_EREG1, 1));
+
+ if (src1 != dst)
+ overflow_ra = reg_map[src1];
+ else {
+ /* Rare ocasion. */
+ FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO));
+
+ overflow_ra = TMP_EREG2;
+ }
+ }
+
+ if (op & SLJIT_SET_E)
+ FAIL_IF(ADDLI(EQUAL_FLAG, reg_map[src1], -src2));
+
+ if (op & SLJIT_SET_C) {
+ FAIL_IF(load_immediate(compiler, ADDR_TMP_mapped, src2));
+ FAIL_IF(CMPLTU(ULESS_FLAG, reg_map[src1], ADDR_TMP_mapped));
+ }
+
+ /* dst may be the same as src1 or src2. */
+ if (CHECK_FLAGS(SLJIT_SET_E))
+ FAIL_IF(ADDLI(reg_map[dst], reg_map[src1], -src2));
+
+ } else {
+
+ if (op & SLJIT_SET_O) {
+ FAIL_IF(XOR(TMP_EREG1, reg_map[src1], reg_map[src2]));
+ FAIL_IF(SHRUI(TMP_EREG1, TMP_EREG1, 63));
+
+ if (src1 != dst)
+ overflow_ra = reg_map[src1];
+ else {
+ /* Rare ocasion. */
+ FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO));
+ overflow_ra = TMP_EREG2;
+ }
+ }
+
+ if (op & SLJIT_SET_E)
+ FAIL_IF(SUB(EQUAL_FLAG, reg_map[src1], reg_map[src2]));
+
+ if (op & (SLJIT_SET_U | SLJIT_SET_C))
+ FAIL_IF(CMPLTU(ULESS_FLAG, reg_map[src1], reg_map[src2]));
+
+ if (op & SLJIT_SET_U)
+ FAIL_IF(CMPLTU(UGREATER_FLAG, reg_map[src2], reg_map[src1]));
+
+ if (op & SLJIT_SET_S) {
+ FAIL_IF(CMPLTS(LESS_FLAG ,reg_map[src1] ,reg_map[src2]));
+ FAIL_IF(CMPLTS(GREATER_FLAG ,reg_map[src2] ,reg_map[src1]));
+ }
+
+ /* dst may be the same as src1 or src2. */
+ if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))
+ FAIL_IF(SUB(reg_map[dst], reg_map[src1], reg_map[src2]));
+ }
+
+ if (op & SLJIT_SET_O) {
+ FAIL_IF(XOR(OVERFLOW_FLAG, reg_map[dst], overflow_ra));
+ FAIL_IF(SHRUI(OVERFLOW_FLAG, OVERFLOW_FLAG, 63));
+ return CMOVEQZ(OVERFLOW_FLAG, TMP_EREG1, ZERO);
+ }
+
+ return SLJIT_SUCCESS;
+
+ case SLJIT_SUBC:
+ if ((flags & SRC2_IMM) && src2 == SIMM_16BIT_MIN) {
+ FAIL_IF(ADDLI(TMP_REG2_mapped, ZERO, src2));
+ src2 = TMP_REG2;
+ flags &= ~SRC2_IMM;
+ }
+
+ if (flags & SRC2_IMM) {
+ if (op & SLJIT_SET_C) {
+ FAIL_IF(load_immediate(compiler, ADDR_TMP_mapped, -src2));
+ FAIL_IF(CMPLTU(TMP_EREG1, reg_map[src1], ADDR_TMP_mapped));
+ }
+
+ /* dst may be the same as src1 or src2. */
+ FAIL_IF(ADDLI(reg_map[dst], reg_map[src1], -src2));
+
+ } else {
+ if (op & SLJIT_SET_C)
+ FAIL_IF(CMPLTU(TMP_EREG1, reg_map[src1], reg_map[src2]));
+ /* dst may be the same as src1 or src2. */
+ FAIL_IF(SUB(reg_map[dst], reg_map[src1], reg_map[src2]));
+ }
+
+ if (op & SLJIT_SET_C)
+ FAIL_IF(CMOVEQZ(TMP_EREG1, reg_map[dst], ULESS_FLAG));
+
+ FAIL_IF(SUB(reg_map[dst], reg_map[dst], ULESS_FLAG));
+
+ if (op & SLJIT_SET_C)
+ FAIL_IF(ADD(ULESS_FLAG, TMP_EREG1, ZERO));
+
+ return SLJIT_SUCCESS;
+
+#define EMIT_LOGICAL(op_imm, op_norm) \
+ if (flags & SRC2_IMM) { \
+ FAIL_IF(load_immediate(compiler, ADDR_TMP_mapped, src2)); \
+ if (op & SLJIT_SET_E) \
+ FAIL_IF(push_3_buffer( \
+ compiler, op_norm, EQUAL_FLAG, reg_map[src1], \
+ ADDR_TMP_mapped, __LINE__)); \
+ if (CHECK_FLAGS(SLJIT_SET_E)) \
+ FAIL_IF(push_3_buffer( \
+ compiler, op_norm, reg_map[dst], reg_map[src1], \
+ ADDR_TMP_mapped, __LINE__)); \
+ } else { \
+ if (op & SLJIT_SET_E) \
+ FAIL_IF(push_3_buffer( \
+ compiler, op_norm, EQUAL_FLAG, reg_map[src1], \
+ reg_map[src2], __LINE__)); \
+ if (CHECK_FLAGS(SLJIT_SET_E)) \
+ FAIL_IF(push_3_buffer( \
+ compiler, op_norm, reg_map[dst], reg_map[src1], \
+ reg_map[src2], __LINE__)); \
+ }
+
+ case SLJIT_AND:
+ EMIT_LOGICAL(TILEGX_OPC_ANDI, TILEGX_OPC_AND);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_OR:
+ EMIT_LOGICAL(TILEGX_OPC_ORI, TILEGX_OPC_OR);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_XOR:
+ EMIT_LOGICAL(TILEGX_OPC_XORI, TILEGX_OPC_XOR);
+ return SLJIT_SUCCESS;
+
+#define EMIT_SHIFT(op_imm, op_norm) \
+ if (flags & SRC2_IMM) { \
+ if (op & SLJIT_SET_E) \
+ FAIL_IF(push_3_buffer( \
+ compiler, op_imm, EQUAL_FLAG, reg_map[src1], \
+ src2 & 0x3F, __LINE__)); \
+ if (CHECK_FLAGS(SLJIT_SET_E)) \
+ FAIL_IF(push_3_buffer( \
+ compiler, op_imm, reg_map[dst], reg_map[src1], \
+ src2 & 0x3F, __LINE__)); \
+ } else { \
+ if (op & SLJIT_SET_E) \
+ FAIL_IF(push_3_buffer( \
+ compiler, op_imm, reg_map[dst], reg_map[src1], \
+ src2 & 0x3F, __LINE__)); \
+ if (CHECK_FLAGS(SLJIT_SET_E)) \
+ FAIL_IF(push_3_buffer( \
+ compiler, op_norm, reg_map[dst], reg_map[src1], \
+ reg_map[src2], __LINE__)); \
+ }
+
+ case SLJIT_SHL:
+ EMIT_SHIFT(TILEGX_OPC_SHLI, TILEGX_OPC_SHL);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_LSHR:
+ EMIT_SHIFT(TILEGX_OPC_SHRUI, TILEGX_OPC_SHRU);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_ASHR:
+ EMIT_SHIFT(TILEGX_OPC_SHRSI, TILEGX_OPC_SHRS);
+ return SLJIT_SUCCESS;
+ }
+
+ SLJIT_ASSERT_STOP();
+ return SLJIT_SUCCESS;
+}
+
+static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags, sljit_si dst, sljit_sw dstw, sljit_si src1, sljit_sw src1w, sljit_si src2, sljit_sw src2w)
+{
+ /* arg1 goes to TMP_REG1 or src reg.
+ arg2 goes to TMP_REG2, imm or src reg.
+ TMP_REG3 can be used for caching.
+ result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
+ sljit_si dst_r = TMP_REG2;
+ sljit_si src1_r;
+ sljit_sw src2_r = 0;
+ sljit_si sugg_src2_r = TMP_REG2;
+
+ if (!(flags & ALT_KEEP_CACHE)) {
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+ }
+
+ if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
+ if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+ if (GET_FLAGS(op))
+ flags |= UNUSED_DEST;
+ } else if (FAST_IS_REG(dst)) {
+ dst_r = dst;
+ flags |= REG_DEST;
+ if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
+ sugg_src2_r = dst_r;
+ } else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1_mapped, dst, dstw))
+ flags |= SLOW_DEST;
+
+ if (flags & IMM_OP) {
+ if ((src2 & SLJIT_IMM) && src2w) {
+ if ((!(flags & LOGICAL_OP)
+ && (src2w <= SIMM_16BIT_MAX && src2w >= SIMM_16BIT_MIN))
+ || ((flags & LOGICAL_OP) && !(src2w & ~UIMM_16BIT_MAX))) {
+ flags |= SRC2_IMM;
+ src2_r = src2w;
+ }
+ }
+
+ if (!(flags & SRC2_IMM) && (flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w) {
+ if ((!(flags & LOGICAL_OP)
+ && (src1w <= SIMM_16BIT_MAX && src1w >= SIMM_16BIT_MIN))
+ || ((flags & LOGICAL_OP) && !(src1w & ~UIMM_16BIT_MAX))) {
+ flags |= SRC2_IMM;
+ src2_r = src1w;
+
+ /* And swap arguments. */
+ src1 = src2;
+ src1w = src2w;
+ src2 = SLJIT_IMM;
+ /* src2w = src2_r unneeded. */
+ }
+ }
+ }
+
+ /* Source 1. */
+ if (FAST_IS_REG(src1)) {
+ src1_r = src1;
+ flags |= REG1_SOURCE;
+ } else if (src1 & SLJIT_IMM) {
+ if (src1w) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1_mapped, src1w));
+ src1_r = TMP_REG1;
+ } else
+ src1_r = 0;
+ } else {
+ if (getput_arg_fast(compiler, flags | LOAD_DATA, TMP_REG1_mapped, src1, src1w))
+ FAIL_IF(compiler->error);
+ else
+ flags |= SLOW_SRC1;
+ src1_r = TMP_REG1;
+ }
+
+ /* Source 2. */
+ if (FAST_IS_REG(src2)) {
+ src2_r = src2;
+ flags |= REG2_SOURCE;
+ if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
+ dst_r = src2_r;
+ } else if (src2 & SLJIT_IMM) {
+ if (!(flags & SRC2_IMM)) {
+ if (src2w) {
+ FAIL_IF(load_immediate(compiler, reg_map[sugg_src2_r], src2w));
+ src2_r = sugg_src2_r;
+ } else {
+ src2_r = 0;
+ if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_SI) && (dst & SLJIT_MEM))
+ dst_r = 0;
+ }
+ }
+ } else {
+ if (getput_arg_fast(compiler, flags | LOAD_DATA, reg_map[sugg_src2_r], src2, src2w))
+ FAIL_IF(compiler->error);
+ else
+ flags |= SLOW_SRC2;
+ src2_r = sugg_src2_r;
+ }
+
+ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
+ SLJIT_ASSERT(src2_r == TMP_REG2);
+ if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2_mapped, src2, src2w, src1, src1w));
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1_mapped, src1, src1w, dst, dstw));
+ } else {
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1_mapped, src1, src1w, src2, src2w));
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2_mapped, src2, src2w, dst, dstw));
+ }
+ } else if (flags & SLOW_SRC1)
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1_mapped, src1, src1w, dst, dstw));
+ else if (flags & SLOW_SRC2)
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, reg_map[sugg_src2_r], src2, src2w, dst, dstw));
+
+ FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
+
+ if (dst & SLJIT_MEM) {
+ if (!(flags & SLOW_DEST)) {
+ getput_arg_fast(compiler, flags, reg_map[dst_r], dst, dstw);
+ return compiler->error;
+ }
+
+ return getput_arg(compiler, flags, reg_map[dst_r], dst, dstw, 0, 0);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src, sljit_sw srcw, sljit_si type)
+{
+ sljit_si sugg_dst_ar, dst_ar;
+ sljit_si flags = GET_ALL_FLAGS(op);
+
+ CHECK_ERROR();
+ check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ if (dst == SLJIT_UNUSED)
+ return SLJIT_SUCCESS;
+
+ op = GET_OPCODE(op);
+ sugg_dst_ar = reg_map[(op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2];
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+ if (op >= SLJIT_ADD && (src & SLJIT_MEM)) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1_mapped, src, srcw, dst, dstw));
+ src = TMP_REG1;
+ srcw = 0;
+ }
+
+ switch (type) {
+ case SLJIT_C_EQUAL:
+ case SLJIT_C_NOT_EQUAL:
+ FAIL_IF(CMPLTUI(sugg_dst_ar, EQUAL_FLAG, 1));
+ dst_ar = sugg_dst_ar;
+ break;
+ case SLJIT_C_LESS:
+ case SLJIT_C_GREATER_EQUAL:
+ case SLJIT_C_FLOAT_LESS:
+ case SLJIT_C_FLOAT_GREATER_EQUAL:
+ dst_ar = ULESS_FLAG;
+ break;
+ case SLJIT_C_GREATER:
+ case SLJIT_C_LESS_EQUAL:
+ case SLJIT_C_FLOAT_GREATER:
+ case SLJIT_C_FLOAT_LESS_EQUAL:
+ dst_ar = UGREATER_FLAG;
+ break;
+ case SLJIT_C_SIG_LESS:
+ case SLJIT_C_SIG_GREATER_EQUAL:
+ dst_ar = LESS_FLAG;
+ break;
+ case SLJIT_C_SIG_GREATER:
+ case SLJIT_C_SIG_LESS_EQUAL:
+ dst_ar = GREATER_FLAG;
+ break;
+ case SLJIT_C_OVERFLOW:
+ case SLJIT_C_NOT_OVERFLOW:
+ dst_ar = OVERFLOW_FLAG;
+ break;
+ case SLJIT_C_MUL_OVERFLOW:
+ case SLJIT_C_MUL_NOT_OVERFLOW:
+ FAIL_IF(CMPLTUI(sugg_dst_ar, OVERFLOW_FLAG, 1));
+ dst_ar = sugg_dst_ar;
+ type ^= 0x1; /* Flip type bit for the XORI below. */
+ break;
+ case SLJIT_C_FLOAT_EQUAL:
+ case SLJIT_C_FLOAT_NOT_EQUAL:
+ dst_ar = EQUAL_FLAG;
+ break;
+
+ default:
+ SLJIT_ASSERT_STOP();
+ dst_ar = sugg_dst_ar;
+ break;
+ }
+
+ if (type & 0x1) {
+ FAIL_IF(XORI(sugg_dst_ar, dst_ar, 1));
+ dst_ar = sugg_dst_ar;
+ }
+
+ if (op >= SLJIT_ADD) {
+ if (TMP_REG2_mapped != dst_ar)
+ FAIL_IF(ADD(TMP_REG2_mapped, dst_ar, ZERO));
+ return emit_op(compiler, op | flags, CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0);
+ }
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, WORD_DATA, dst_ar, dst, dstw);
+
+ if (sugg_dst_ar != dst_ar)
+ return ADD(sugg_dst_ar, dst_ar, ZERO);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op) {
+ CHECK_ERROR();
+ check_sljit_emit_op0(compiler, op);
+
+ op = GET_OPCODE(op);
+ switch (op) {
+ case SLJIT_NOP:
+ return push_0_buffer(compiler, TILEGX_OPC_FNOP, __LINE__);
+
+ case SLJIT_BREAKPOINT:
+ return PI(BPT);
+
+ case SLJIT_UMUL:
+ case SLJIT_SMUL:
+ case SLJIT_UDIV:
+ case SLJIT_SDIV:
+ SLJIT_ASSERT_STOP();
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+ return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+
+ case SLJIT_MOV_UI:
+ return emit_op(compiler, SLJIT_MOV_UI, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+
+ case SLJIT_MOV_SI:
+ return emit_op(compiler, SLJIT_MOV_SI, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+
+ case SLJIT_MOV_UB:
+ return emit_op(compiler, SLJIT_MOV_UB, BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub) srcw : srcw);
+
+ case SLJIT_MOV_SB:
+ return emit_op(compiler, SLJIT_MOV_SB, BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb) srcw : srcw);
+
+ case SLJIT_MOV_UH:
+ return emit_op(compiler, SLJIT_MOV_UH, HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh) srcw : srcw);
+
+ case SLJIT_MOV_SH:
+ return emit_op(compiler, SLJIT_MOV_SH, HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh) srcw : srcw);
+
+ case SLJIT_MOVU:
+ case SLJIT_MOVU_P:
+ return emit_op(compiler, SLJIT_MOV, WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+
+ case SLJIT_MOVU_UI:
+ return emit_op(compiler, SLJIT_MOV_UI, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+
+ case SLJIT_MOVU_SI:
+ return emit_op(compiler, SLJIT_MOV_SI, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+
+ case SLJIT_MOVU_UB:
+ return emit_op(compiler, SLJIT_MOV_UB, BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub) srcw : srcw);
+
+ case SLJIT_MOVU_SB:
+ return emit_op(compiler, SLJIT_MOV_SB, BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb) srcw : srcw);
+
+ case SLJIT_MOVU_UH:
+ return emit_op(compiler, SLJIT_MOV_UH, HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh) srcw : srcw);
+
+ case SLJIT_MOVU_SH:
+ return emit_op(compiler, SLJIT_MOV_SH, HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh) srcw : srcw);
+
+ case SLJIT_NOT:
+ return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw);
+
+ case SLJIT_NEG:
+ return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw);
+
+ case SLJIT_CLZ:
+ return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src1, sljit_sw src1w, sljit_si src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADD:
+ case SLJIT_ADDC:
+ return emit_op(compiler, op, CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_SUB:
+ case SLJIT_SUBC:
+ return emit_op(compiler, op, IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_MUL:
+ return emit_op(compiler, op, CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_AND:
+ case SLJIT_OR:
+ case SLJIT_XOR:
+ return emit_op(compiler, op, CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_SHL:
+ case SLJIT_LSHR:
+ case SLJIT_ASHR:
+ if (src2 & SLJIT_IMM)
+ src2w &= 0x3f;
+ if (op & SLJIT_INT_OP)
+ src2w &= 0x1f;
+
+ return emit_op(compiler, op, IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label * sljit_emit_label(struct sljit_compiler *compiler)
+{
+ struct sljit_label *label;
+
+ flush_buffer(compiler);
+
+ CHECK_ERROR_PTR();
+ check_sljit_emit_label(compiler);
+
+ if (compiler->last_label && compiler->last_label->size == compiler->size)
+ return compiler->last_label;
+
+ label = (struct sljit_label *)ensure_abuf(compiler, sizeof(struct sljit_label));
+ PTR_FAIL_IF(!label);
+ set_label(label, compiler);
+ return label;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
+{
+ sljit_si src_r = TMP_REG2;
+ struct sljit_jump *jump = NULL;
+
+ flush_buffer(compiler);
+
+ CHECK_ERROR();
+ check_sljit_emit_ijump(compiler, type, src, srcw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (FAST_IS_REG(src)) {
+ if (reg_map[src] != 0)
+ src_r = src;
+ else
+ FAIL_IF(ADD_SOLO(TMP_REG2_mapped, reg_map[src], ZERO));
+ }
+
+ if (type >= SLJIT_CALL0) {
+ SLJIT_ASSERT(reg_map[PIC_ADDR_REG] == 16 && PIC_ADDR_REG == TMP_REG2);
+ if (src & (SLJIT_IMM | SLJIT_MEM)) {
+ if (src & SLJIT_IMM)
+ FAIL_IF(emit_const(compiler, reg_map[PIC_ADDR_REG], srcw, 1));
+ else {
+ SLJIT_ASSERT(src_r == TMP_REG2 && (src & SLJIT_MEM));
+ FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
+ }
+
+ FAIL_IF(ADD_SOLO(0, reg_map[SLJIT_SCRATCH_REG1], ZERO));
+
+ FAIL_IF(ADDI_SOLO(54, 54, -16));
+
+ FAIL_IF(JALR_SOLO(reg_map[PIC_ADDR_REG]));
+
+ return ADDI_SOLO(54, 54, 16);
+ }
+
+ /* Register input. */
+ if (type >= SLJIT_CALL1)
+ FAIL_IF(ADD_SOLO(0, reg_map[SLJIT_SCRATCH_REG1], ZERO));
+
+ FAIL_IF(ADD_SOLO(reg_map[PIC_ADDR_REG], reg_map[src_r], ZERO));
+
+ FAIL_IF(ADDI_SOLO(54, 54, -16));
+
+ FAIL_IF(JALR_SOLO(reg_map[src_r]));
+
+ return ADDI_SOLO(54, 54, 16);
+ }
+
+ if (src & SLJIT_IMM) {
+ jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ FAIL_IF(!jump);
+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0));
+ jump->u.target = srcw;
+ FAIL_IF(emit_const(compiler, TMP_REG2_mapped, 0, 1));
+
+ if (type >= SLJIT_FAST_CALL) {
+ FAIL_IF(ADD_SOLO(ZERO, ZERO, ZERO));
+ jump->addr = compiler->size;
+ FAIL_IF(JR_SOLO(reg_map[src_r]));
+ } else {
+ jump->addr = compiler->size;
+ FAIL_IF(JR_SOLO(reg_map[src_r]));
+ }
+
+ return SLJIT_SUCCESS;
+
+ } else if (src & SLJIT_MEM)
+ FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
+
+ FAIL_IF(JR_SOLO(reg_map[src_r]));
+
+ if (jump)
+ jump->addr = compiler->size;
+
+ return SLJIT_SUCCESS;
+}
+
+#define BR_Z(src) \
+ inst = BEQZ_X1 | SRCA_X1(src); \
+ flags = IS_COND;
+
+#define BR_NZ(src) \
+ inst = BNEZ_X1 | SRCA_X1(src); \
+ flags = IS_COND;
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
+{
+ struct sljit_jump *jump;
+ sljit_ins inst;
+ sljit_si flags = 0;
+
+ flush_buffer(compiler);
+
+ CHECK_ERROR_PTR();
+ check_sljit_emit_jump(compiler, type);
+
+ jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+ type &= 0xff;
+
+ switch (type) {
+ case SLJIT_C_EQUAL:
+ case SLJIT_C_FLOAT_NOT_EQUAL:
+ BR_NZ(EQUAL_FLAG);
+ break;
+ case SLJIT_C_NOT_EQUAL:
+ case SLJIT_C_FLOAT_EQUAL:
+ BR_Z(EQUAL_FLAG);
+ break;
+ case SLJIT_C_LESS:
+ case SLJIT_C_FLOAT_LESS:
+ BR_Z(ULESS_FLAG);
+ break;
+ case SLJIT_C_GREATER_EQUAL:
+ case SLJIT_C_FLOAT_GREATER_EQUAL:
+ BR_NZ(ULESS_FLAG);
+ break;
+ case SLJIT_C_GREATER:
+ case SLJIT_C_FLOAT_GREATER:
+ BR_Z(UGREATER_FLAG);
+ break;
+ case SLJIT_C_LESS_EQUAL:
+ case SLJIT_C_FLOAT_LESS_EQUAL:
+ BR_NZ(UGREATER_FLAG);
+ break;
+ case SLJIT_C_SIG_LESS:
+ BR_Z(LESS_FLAG);
+ break;
+ case SLJIT_C_SIG_GREATER_EQUAL:
+ BR_NZ(LESS_FLAG);
+ break;
+ case SLJIT_C_SIG_GREATER:
+ BR_Z(GREATER_FLAG);
+ break;
+ case SLJIT_C_SIG_LESS_EQUAL:
+ BR_NZ(GREATER_FLAG);
+ break;
+ case SLJIT_C_OVERFLOW:
+ case SLJIT_C_MUL_OVERFLOW:
+ BR_Z(OVERFLOW_FLAG);
+ break;
+ case SLJIT_C_NOT_OVERFLOW:
+ case SLJIT_C_MUL_NOT_OVERFLOW:
+ BR_NZ(OVERFLOW_FLAG);
+ break;
+ default:
+ /* Not conditional branch. */
+ inst = 0;
+ break;
+ }
+
+ jump->flags |= flags;
+
+ if (inst) {
+ inst = inst | ((type <= SLJIT_JUMP) ? BOFF_X1(5) : BOFF_X1(6));
+ PTR_FAIL_IF(PI(inst));
+ }
+
+ PTR_FAIL_IF(emit_const(compiler, TMP_REG2_mapped, 0, 1));
+ if (type <= SLJIT_JUMP) {
+ jump->addr = compiler->size;
+ PTR_FAIL_IF(JR_SOLO(TMP_REG2_mapped));
+ } else {
+ SLJIT_ASSERT(reg_map[PIC_ADDR_REG] == 16 && PIC_ADDR_REG == TMP_REG2);
+ /* Cannot be optimized out if type is >= CALL0. */
+ jump->flags |= IS_JAL | (type >= SLJIT_CALL0 ? SLJIT_REWRITABLE_JUMP : 0);
+ PTR_FAIL_IF(ADD_SOLO(0, reg_map[SLJIT_SCRATCH_REG1], ZERO));
+ jump->addr = compiler->size;
+ PTR_FAIL_IF(JALR_SOLO(TMP_REG2_mapped));
+ }
+
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
+{
+ return 0;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src, sljit_sw srcw)
+{
+ SLJIT_ASSERT_STOP();
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src1, sljit_sw src1w, sljit_si src2, sljit_sw src2w)
+{
+ SLJIT_ASSERT_STOP();
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const * sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
+{
+ struct sljit_const *const_;
+ sljit_si reg;
+
+ flush_buffer(compiler);
+
+ CHECK_ERROR_PTR();
+ check_sljit_emit_const(compiler, dst, dstw, init_value);
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ const_ = (struct sljit_const *)ensure_abuf(compiler, sizeof(struct sljit_const));
+ PTR_FAIL_IF(!const_);
+ set_const(const_, compiler);
+
+ reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ PTR_FAIL_IF(emit_const_64(compiler, reg, init_value, 1));
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
+ return const_;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+{
+ sljit_ins *inst = (sljit_ins *)addr;
+
+ inst[0] = (inst[0] & ~(0xFFFFL << 43)) | (((new_addr >> 32) & 0xffff) << 43);
+ inst[1] = (inst[1] & ~(0xFFFFL << 43)) | (((new_addr >> 16) & 0xffff) << 43);
+ inst[2] = (inst[2] & ~(0xFFFFL << 43)) | ((new_addr & 0xffff) << 43);
+ SLJIT_CACHE_FLUSH(inst, inst + 3);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+{
+ sljit_ins *inst = (sljit_ins *)addr;
+
+ inst[0] = (inst[0] & ~(0xFFFFL << 43)) | (((new_constant >> 48) & 0xFFFFL) << 43);
+ inst[1] = (inst[1] & ~(0xFFFFL << 43)) | (((new_constant >> 32) & 0xFFFFL) << 43);
+ inst[2] = (inst[2] & ~(0xFFFFL << 43)) | (((new_constant >> 16) & 0xFFFFL) << 43);
+ inst[3] = (inst[3] & ~(0xFFFFL << 43)) | ((new_constant & 0xFFFFL) << 43);
+ SLJIT_CACHE_FLUSH(inst, inst + 4);
+}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_32.c b/src/3rdparty/pcre/sljit/sljitNativeX86_32.c
index 2866e8f2a1..dd03f26618 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeX86_32.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeX86_32.c
@@ -89,11 +89,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
FAIL_IF(!inst);
INC_SIZE(size);
- PUSH_REG(reg_map[TMP_REGISTER]);
+ PUSH_REG(reg_map[TMP_REG1]);
#if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
if (args > 0) {
*inst++ = MOV_r_rm;
- *inst++ = MOD_REG | (reg_map[TMP_REGISTER] << 3) | 0x4 /* esp */;
+ *inst++ = MOD_REG | (reg_map[TMP_REG1] << 3) | 0x4 /* esp */;
}
#endif
if (saveds > 2)
@@ -121,17 +121,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
#else
if (args > 0) {
*inst++ = MOV_r_rm;
- *inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[TMP_REGISTER];
+ *inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[TMP_REG1];
*inst++ = sizeof(sljit_sw) * 2;
}
if (args > 1) {
*inst++ = MOV_r_rm;
- *inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[TMP_REGISTER];
+ *inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[TMP_REG1];
*inst++ = sizeof(sljit_sw) * 3;
}
if (args > 2) {
*inst++ = MOV_r_rm;
- *inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG3] << 3) | reg_map[TMP_REGISTER];
+ *inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG3] << 3) | reg_map[TMP_REG1];
*inst++ = sizeof(sljit_sw) * 4;
}
#endif
@@ -245,7 +245,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
POP_REG(reg_map[SLJIT_SAVED_REG2]);
if (compiler->saveds > 2)
POP_REG(reg_map[SLJIT_SAVED_REG3]);
- POP_REG(reg_map[TMP_REGISTER]);
+ POP_REG(reg_map[TMP_REG1]);
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
if (compiler->args > 2)
RET_I16(sizeof(sljit_sw));
@@ -301,9 +301,9 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
/* Calculate size of b. */
inst_size += 1; /* mod r/m byte. */
if (b & SLJIT_MEM) {
- if ((b & 0x0f) == SLJIT_UNUSED)
+ if ((b & REG_MASK) == SLJIT_UNUSED)
inst_size += sizeof(sljit_sw);
- else if (immb != 0 && !(b & 0xf0)) {
+ else if (immb != 0 && !(b & OFFS_REG_MASK)) {
/* Immediate operand. */
if (immb <= 127 && immb >= -128)
inst_size += sizeof(sljit_sb);
@@ -311,10 +311,10 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
inst_size += sizeof(sljit_sw);
}
- if ((b & 0xf) == SLJIT_LOCALS_REG && !(b & 0xf0))
- b |= SLJIT_LOCALS_REG << 4;
+ if ((b & REG_MASK) == SLJIT_LOCALS_REG && !(b & OFFS_REG_MASK))
+ b |= TO_OFFS_REG(SLJIT_LOCALS_REG);
- if ((b & 0xf0) != SLJIT_UNUSED)
+ if ((b & OFFS_REG_MASK) != SLJIT_UNUSED)
inst_size += 1; /* SIB byte. */
}
@@ -393,8 +393,8 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
#else
*buf_ptr++ |= MOD_REG + reg_map[b];
#endif
- else if ((b & 0x0f) != SLJIT_UNUSED) {
- if ((b & 0xf0) == SLJIT_UNUSED || (b & 0xf0) == (SLJIT_LOCALS_REG << 4)) {
+ else if ((b & REG_MASK) != SLJIT_UNUSED) {
+ if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_LOCALS_REG)) {
if (immb != 0) {
if (immb <= 127 && immb >= -128)
*buf_ptr |= 0x40;
@@ -402,11 +402,11 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
*buf_ptr |= 0x80;
}
- if ((b & 0xf0) == SLJIT_UNUSED)
- *buf_ptr++ |= reg_map[b & 0x0f];
+ if ((b & OFFS_REG_MASK) == SLJIT_UNUSED)
+ *buf_ptr++ |= reg_map[b & REG_MASK];
else {
*buf_ptr++ |= 0x04;
- *buf_ptr++ = reg_map[b & 0x0f] | (reg_map[(b >> 4) & 0x0f] << 3);
+ *buf_ptr++ = reg_map[b & REG_MASK] | (reg_map[OFFS_REG(b)] << 3);
}
if (immb != 0) {
@@ -420,7 +420,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
}
else {
*buf_ptr++ |= 0x04;
- *buf_ptr++ = reg_map[b & 0x0f] | (reg_map[(b >> 4) & 0x0f] << 3) | (immb << 6);
+ *buf_ptr++ = reg_map[b & REG_MASK] | (reg_map[OFFS_REG(b)] << 3) | (immb << 6);
}
}
else {
@@ -495,9 +495,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
/* For UNUSED dst. Uncommon, but possible. */
if (dst == SLJIT_UNUSED)
- dst = TMP_REGISTER;
+ dst = TMP_REG1;
- if (dst <= TMP_REGISTER) {
+ if (FAST_IS_REG(dst)) {
/* Unused dest is possible here. */
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!inst);
@@ -524,7 +524,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
CHECK_EXTRA_REGS(src, srcw, (void)0);
- if (src <= TMP_REGISTER) {
+ if (FAST_IS_REG(src)) {
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
FAIL_IF(!inst);
diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_64.c b/src/3rdparty/pcre/sljit/sljitNativeX86_64.c
index 28f04fddd8..967f3c3444 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeX86_64.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeX86_64.c
@@ -69,7 +69,7 @@ static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_sw addr, sljit_si
{
sljit_sw delta = addr - ((sljit_sw)code_ptr + 1 + sizeof(sljit_si));
- if (delta <= SLJIT_W(0x7fffffff) && delta >= SLJIT_W(-0x80000000)) {
+ if (delta <= HALFWORD_MAX && delta >= HALFWORD_MIN) {
*code_ptr++ = (type == 2) ? CALL_i32 : JMP_i32;
*(sljit_sw*)code_ptr = delta;
}
@@ -420,12 +420,12 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
size &= 0xf;
inst_size = size;
- if ((b & SLJIT_MEM) && !(b & 0xf0) && NOT_HALFWORD(immb)) {
+ if ((b & SLJIT_MEM) && !(b & OFFS_REG_MASK) && NOT_HALFWORD(immb)) {
if (emit_load_imm64(compiler, TMP_REG3, immb))
return NULL;
immb = 0;
- if (b & 0xf)
- b |= TMP_REG3 << 4;
+ if (b & REG_MASK)
+ b |= TO_OFFS_REG(TMP_REG3);
else
b |= TMP_REG3;
}
@@ -445,12 +445,12 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
/* Calculate size of b. */
inst_size += 1; /* mod r/m byte. */
if (b & SLJIT_MEM) {
- if ((b & 0x0f) == SLJIT_UNUSED)
+ if ((b & REG_MASK) == SLJIT_UNUSED)
inst_size += 1 + sizeof(sljit_si); /* SIB byte required to avoid RIP based addressing. */
else {
- if (reg_map[b & 0x0f] >= 8)
+ if (reg_map[b & REG_MASK] >= 8)
rex |= REX_B;
- if (immb != 0 && !(b & 0xf0)) {
+ if (immb != 0 && !(b & OFFS_REG_MASK)) {
/* Immediate operand. */
if (immb <= 127 && immb >= -128)
inst_size += sizeof(sljit_sb);
@@ -459,12 +459,12 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
}
}
- if ((b & 0xf) == SLJIT_LOCALS_REG && !(b & 0xf0))
- b |= SLJIT_LOCALS_REG << 4;
+ if ((b & REG_MASK) == SLJIT_LOCALS_REG && !(b & OFFS_REG_MASK))
+ b |= TO_OFFS_REG(SLJIT_LOCALS_REG);
- if ((b & 0xf0) != SLJIT_UNUSED) {
+ if ((b & OFFS_REG_MASK) != SLJIT_UNUSED) {
inst_size += 1; /* SIB byte. */
- if (reg_map[(b >> 4) & 0x0f] >= 8)
+ if (reg_map[OFFS_REG(b)] >= 8)
rex |= REX_X;
}
}
@@ -563,8 +563,8 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
#else
*buf_ptr++ |= MOD_REG + reg_lmap[b];
#endif
- else if ((b & 0x0f) != SLJIT_UNUSED) {
- if ((b & 0xf0) == SLJIT_UNUSED || (b & 0xf0) == (SLJIT_LOCALS_REG << 4)) {
+ else if ((b & REG_MASK) != SLJIT_UNUSED) {
+ if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_LOCALS_REG)) {
if (immb != 0) {
if (immb <= 127 && immb >= -128)
*buf_ptr |= 0x40;
@@ -572,11 +572,11 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
*buf_ptr |= 0x80;
}
- if ((b & 0xf0) == SLJIT_UNUSED)
- *buf_ptr++ |= reg_lmap[b & 0x0f];
+ if ((b & OFFS_REG_MASK) == SLJIT_UNUSED)
+ *buf_ptr++ |= reg_lmap[b & REG_MASK];
else {
*buf_ptr++ |= 0x04;
- *buf_ptr++ = reg_lmap[b & 0x0f] | (reg_lmap[(b >> 4) & 0x0f] << 3);
+ *buf_ptr++ = reg_lmap[b & REG_MASK] | (reg_lmap[OFFS_REG(b)] << 3);
}
if (immb != 0) {
@@ -590,7 +590,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
}
else {
*buf_ptr++ |= 0x04;
- *buf_ptr++ = reg_lmap[b & 0x0f] | (reg_lmap[(b >> 4) & 0x0f] << 3) | (immb << 6);
+ *buf_ptr++ = reg_lmap[b & REG_MASK] | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6);
}
}
else {
@@ -662,9 +662,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
/* For UNUSED dst. Uncommon, but possible. */
if (dst == SLJIT_UNUSED)
- dst = TMP_REGISTER;
+ dst = TMP_REG1;
- if (dst <= TMP_REGISTER) {
+ if (FAST_IS_REG(dst)) {
if (reg_map[dst] < 8) {
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!inst);
@@ -698,11 +698,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
ADJUST_LOCAL_OFFSET(src, srcw);
if ((src & SLJIT_IMM) && NOT_HALFWORD(srcw)) {
- FAIL_IF(emit_load_imm64(compiler, TMP_REGISTER, srcw));
- src = TMP_REGISTER;
+ FAIL_IF(emit_load_imm64(compiler, TMP_REG1, srcw));
+ src = TMP_REG1;
}
- if (src <= TMP_REGISTER) {
+ if (FAST_IS_REG(src)) {
if (reg_map[src] < 8) {
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
FAIL_IF(!inst);
@@ -765,7 +765,7 @@ static sljit_si emit_mov_int(struct sljit_compiler *compiler, sljit_si sign,
return SLJIT_SUCCESS; /* Empty instruction. */
if (src & SLJIT_IMM) {
- if (dst <= TMP_REGISTER) {
+ if (FAST_IS_REG(dst)) {
if (sign || ((sljit_uw)srcw <= 0x7fffffff)) {
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_si)srcw, dst, dstw);
FAIL_IF(!inst);
@@ -782,9 +782,9 @@ static sljit_si emit_mov_int(struct sljit_compiler *compiler, sljit_si sign,
return SLJIT_SUCCESS;
}
- dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
- if ((dst & SLJIT_MEM) && (src <= TMP_REGISTER))
+ if ((dst & SLJIT_MEM) && FAST_IS_REG(src))
dst_r = src;
else {
if (sign) {
diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c
index ceb3d675b7..653705f6ca 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c
@@ -64,7 +64,7 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
/* Last register + 1. */
-#define TMP_REGISTER (SLJIT_NO_REGISTERS + 1)
+#define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 2] = {
0, 0, 2, 1, 0, 0, 3, 6, 7, 0, 0, 4, 5
@@ -85,7 +85,7 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 2] = {
#else /* SLJIT_CONFIG_X86_32 */
/* Last register + 1. */
-#define TMP_REGISTER (SLJIT_NO_REGISTERS + 1)
+#define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
#define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
@@ -118,8 +118,16 @@ static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = {
#define REX_B 0x41
#define REX 0x40
-#define IS_HALFWORD(x) ((x) <= 0x7fffffffll && (x) >= -0x80000000ll)
-#define NOT_HALFWORD(x) ((x) > 0x7fffffffll || (x) < -0x80000000ll)
+#ifndef _WIN64
+#define HALFWORD_MAX 0x7fffffffl
+#define HALFWORD_MIN -0x80000000l
+#else
+#define HALFWORD_MAX 0x7fffffffll
+#define HALFWORD_MIN -0x80000000ll
+#endif
+
+#define IS_HALFWORD(x) ((x) <= HALFWORD_MAX && (x) >= HALFWORD_MIN)
+#define NOT_HALFWORD(x) ((x) > HALFWORD_MAX || (x) < HALFWORD_MIN)
#define CHECK_EXTRA_REGS(p, w, do)
@@ -397,7 +405,7 @@ static sljit_ub* generate_near_jump_code(struct sljit_jump *jump, sljit_ub *code
short_jump = (sljit_sw)(label_addr - (jump->addr + 2)) >= -128 && (sljit_sw)(label_addr - (jump->addr + 2)) <= 127;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- if ((sljit_sw)(label_addr - (jump->addr + 1)) > 0x7fffffffll || (sljit_sw)(label_addr - (jump->addr + 1)) < -0x80000000ll)
+ if ((sljit_sw)(label_addr - (jump->addr + 1)) > HALFWORD_MAX || (sljit_sw)(label_addr - (jump->addr + 1)) < HALFWORD_MIN)
return generate_far_jump_code(jump, code_ptr, type);
#endif
@@ -526,7 +534,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
*(sljit_sw*)jump->addr = (sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_sw)));
#else
- SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_si))) >= -0x80000000ll && (sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_si))) <= 0x7fffffffll);
+ SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_si))) >= HALFWORD_MIN && (sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_si))) <= HALFWORD_MAX);
*(sljit_si*)jump->addr = (sljit_si)(jump->u.label->addr - (jump->addr + sizeof(sljit_si)));
#endif
}
@@ -534,7 +542,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
*(sljit_sw*)jump->addr = (sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_sw)));
#else
- SLJIT_ASSERT((sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_si))) >= -0x80000000ll && (sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_si))) <= 0x7fffffffll);
+ SLJIT_ASSERT((sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_si))) >= HALFWORD_MIN && (sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_si))) <= HALFWORD_MAX);
*(sljit_si*)jump->addr = (sljit_si)(jump->u.target - (jump->addr + sizeof(sljit_si)));
#endif
}
@@ -633,7 +641,7 @@ static void SLJIT_CALL sljit_grow_stack(sljit_sw local_size)
CPU cycles if the stack is large enough. However, you don't know it in
advance, so it must always be called. I think this is a bad design in
general even if it has some reasons. */
- *(sljit_si*)alloca(local_size) = 0;
+ *(volatile sljit_si*)alloca(local_size) = 0;
}
#endif
@@ -653,20 +661,20 @@ static sljit_si emit_mov(struct sljit_compiler *compiler,
if (dst == SLJIT_UNUSED) {
/* No destination, doesn't need to setup flags. */
if (src & SLJIT_MEM) {
- inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src, srcw);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src, srcw);
FAIL_IF(!inst);
*inst = MOV_r_rm;
}
return SLJIT_SUCCESS;
}
- if (src <= TMP_REGISTER) {
+ if (FAST_IS_REG(src)) {
inst = emit_x86_instruction(compiler, 1, src, 0, dst, dstw);
FAIL_IF(!inst);
*inst = MOV_rm_r;
return SLJIT_SUCCESS;
}
if (src & SLJIT_IMM) {
- if (dst <= TMP_REGISTER) {
+ if (FAST_IS_REG(dst)) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
return emit_do_imm(compiler, MOV_r_i32 + reg_map[dst], srcw);
#else
@@ -692,7 +700,7 @@ static sljit_si emit_mov(struct sljit_compiler *compiler,
*inst = MOV_rm_i32;
return SLJIT_SUCCESS;
}
- if (dst <= TMP_REGISTER) {
+ if (FAST_IS_REG(dst)) {
inst = emit_x86_instruction(compiler, 1, dst, 0, src, srcw);
FAIL_IF(!inst);
*inst = MOV_r_rm;
@@ -700,10 +708,10 @@ static sljit_si emit_mov(struct sljit_compiler *compiler,
}
/* Memory to memory move. Requires two instruction. */
- inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src, srcw);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src, srcw);
FAIL_IF(!inst);
*inst = MOV_r_rm;
- inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);
FAIL_IF(!inst);
*inst = MOV_rm_r;
return SLJIT_SUCCESS;
@@ -745,13 +753,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
SLJIT_COMPILE_ASSERT(
reg_map[SLJIT_SCRATCH_REG1] == 0
&& reg_map[SLJIT_SCRATCH_REG2] == 2
- && reg_map[TMP_REGISTER] > 7,
+ && reg_map[TMP_REG1] > 7,
invalid_register_assignment_for_div_mul);
#else
SLJIT_COMPILE_ASSERT(
reg_map[SLJIT_SCRATCH_REG1] == 0
&& reg_map[SLJIT_SCRATCH_REG2] < 7
- && reg_map[TMP_REGISTER] == 2,
+ && reg_map[TMP_REG1] == 2,
invalid_register_assignment_for_div_mul);
#endif
compiler->mode32 = op & SLJIT_INT_OP;
@@ -760,10 +768,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
op = GET_OPCODE(op);
if (op == SLJIT_UDIV) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
- EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_SCRATCH_REG2, 0);
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_SCRATCH_REG2, 0);
inst = emit_x86_instruction(compiler, 1, SLJIT_SCRATCH_REG2, 0, SLJIT_SCRATCH_REG2, 0);
#else
- inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, TMP_REGISTER, 0);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, TMP_REG1, 0);
#endif
FAIL_IF(!inst);
*inst = XOR_r_rm;
@@ -771,7 +779,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
if (op == SLJIT_SDIV) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
- EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_SCRATCH_REG2, 0);
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_SCRATCH_REG2, 0);
#endif
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
@@ -800,7 +808,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
FAIL_IF(!inst);
INC_SIZE(2);
*inst++ = GROUP_F7;
- *inst = MOD_REG | ((op >= SLJIT_UDIV) ? reg_map[TMP_REGISTER] : reg_map[SLJIT_SCRATCH_REG2]);
+ *inst = MOD_REG | ((op >= SLJIT_UDIV) ? reg_map[TMP_REG1] : reg_map[SLJIT_SCRATCH_REG2]);
#else
#ifdef _WIN64
size = (!compiler->mode32 || op >= SLJIT_UDIV) ? 3 : 2;
@@ -816,7 +824,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
else if (op >= SLJIT_UDIV)
*inst++ = REX_B;
*inst++ = GROUP_F7;
- *inst = MOD_REG | ((op >= SLJIT_UDIV) ? reg_lmap[TMP_REGISTER] : reg_lmap[SLJIT_SCRATCH_REG2]);
+ *inst = MOD_REG | ((op >= SLJIT_UDIV) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_SCRATCH_REG2]);
#else
if (!compiler->mode32)
*inst++ = REX_W;
@@ -839,7 +847,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
break;
}
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64)
- EMIT_MOV(compiler, SLJIT_SCRATCH_REG2, 0, TMP_REGISTER, 0);
+ EMIT_MOV(compiler, SLJIT_SCRATCH_REG2, 0, TMP_REG1, 0);
#endif
break;
}
@@ -873,7 +881,7 @@ static sljit_si emit_mov_byte(struct sljit_compiler *compiler, sljit_si sign,
return SLJIT_SUCCESS; /* Empty instruction. */
if (src & SLJIT_IMM) {
- if (dst <= TMP_REGISTER) {
+ if (FAST_IS_REG(dst)) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
return emit_do_imm(compiler, MOV_r_i32 + reg_map[dst], srcw);
#else
@@ -889,13 +897,13 @@ static sljit_si emit_mov_byte(struct sljit_compiler *compiler, sljit_si sign,
return SLJIT_SUCCESS;
}
- dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
- if ((dst & SLJIT_MEM) && src <= TMP_REGISTER) {
+ if ((dst & SLJIT_MEM) && FAST_IS_REG(src)) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
if (reg_map[src] >= 4) {
- SLJIT_ASSERT(dst_r == TMP_REGISTER);
- EMIT_MOV(compiler, TMP_REGISTER, 0, src, 0);
+ SLJIT_ASSERT(dst_r == TMP_REG1);
+ EMIT_MOV(compiler, TMP_REG1, 0, src, 0);
} else
dst_r = src;
#else
@@ -903,9 +911,9 @@ static sljit_si emit_mov_byte(struct sljit_compiler *compiler, sljit_si sign,
#endif
}
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- else if (src <= TMP_REGISTER && reg_map[src] >= 4) {
+ else if (FAST_IS_REG(src) && reg_map[src] >= 4) {
/* src, dst are registers. */
- SLJIT_ASSERT(dst >= SLJIT_SCRATCH_REG1 && dst <= TMP_REGISTER);
+ SLJIT_ASSERT(SLOW_IS_REG(dst));
if (reg_map[dst] < 4) {
if (dst != src)
EMIT_MOV(compiler, dst, 0, src, 0);
@@ -946,25 +954,25 @@ static sljit_si emit_mov_byte(struct sljit_compiler *compiler, sljit_si sign,
if (dst & SLJIT_MEM) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- if (dst_r == TMP_REGISTER) {
+ if (dst_r == TMP_REG1) {
/* Find a non-used register, whose reg_map[src] < 4. */
- if ((dst & 0xf) == SLJIT_SCRATCH_REG1) {
- if ((dst & 0xf0) == (SLJIT_SCRATCH_REG2 << 4))
+ if ((dst & REG_MASK) == SLJIT_SCRATCH_REG1) {
+ if ((dst & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SCRATCH_REG2))
work_r = SLJIT_SCRATCH_REG3;
else
work_r = SLJIT_SCRATCH_REG2;
}
else {
- if ((dst & 0xf0) != (SLJIT_SCRATCH_REG1 << 4))
+ if ((dst & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_SCRATCH_REG1))
work_r = SLJIT_SCRATCH_REG1;
- else if ((dst & 0xf) == SLJIT_SCRATCH_REG2)
+ else if ((dst & REG_MASK) == SLJIT_SCRATCH_REG2)
work_r = SLJIT_SCRATCH_REG3;
else
work_r = SLJIT_SCRATCH_REG2;
}
if (work_r == SLJIT_SCRATCH_REG1) {
- ENCODE_PREFIX(XCHG_EAX_r + reg_map[TMP_REGISTER]);
+ ENCODE_PREFIX(XCHG_EAX_r + reg_map[TMP_REG1]);
}
else {
inst = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0);
@@ -977,7 +985,7 @@ static sljit_si emit_mov_byte(struct sljit_compiler *compiler, sljit_si sign,
*inst = MOV_rm8_r8;
if (work_r == SLJIT_SCRATCH_REG1) {
- ENCODE_PREFIX(XCHG_EAX_r + reg_map[TMP_REGISTER]);
+ ENCODE_PREFIX(XCHG_EAX_r + reg_map[TMP_REG1]);
}
else {
inst = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0);
@@ -1015,7 +1023,7 @@ static sljit_si emit_mov_half(struct sljit_compiler *compiler, sljit_si sign,
return SLJIT_SUCCESS; /* Empty instruction. */
if (src & SLJIT_IMM) {
- if (dst <= TMP_REGISTER) {
+ if (FAST_IS_REG(dst)) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
return emit_do_imm(compiler, MOV_r_i32 + reg_map[dst], srcw);
#else
@@ -1031,9 +1039,9 @@ static sljit_si emit_mov_half(struct sljit_compiler *compiler, sljit_si sign,
return SLJIT_SUCCESS;
}
- dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
- if ((dst & SLJIT_MEM) && src <= TMP_REGISTER)
+ if ((dst & SLJIT_MEM) && FAST_IS_REG(src))
dst_r = src;
else {
inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw);
@@ -1058,8 +1066,8 @@ static sljit_si emit_unary(struct sljit_compiler *compiler, sljit_ub opcode,
sljit_ub* inst;
if (dst == SLJIT_UNUSED) {
- EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
- inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
+ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
+ inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0);
FAIL_IF(!inst);
*inst++ = GROUP_F7;
*inst |= opcode;
@@ -1073,7 +1081,7 @@ static sljit_si emit_unary(struct sljit_compiler *compiler, sljit_ub opcode,
*inst |= opcode;
return SLJIT_SUCCESS;
}
- if (dst <= TMP_REGISTER) {
+ if (FAST_IS_REG(dst)) {
EMIT_MOV(compiler, dst, 0, src, srcw);
inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
FAIL_IF(!inst);
@@ -1081,12 +1089,12 @@ static sljit_si emit_unary(struct sljit_compiler *compiler, sljit_ub opcode,
*inst |= opcode;
return SLJIT_SUCCESS;
}
- EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
- inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
+ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
+ inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0);
FAIL_IF(!inst);
*inst++ = GROUP_F7;
*inst |= opcode;
- EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
return SLJIT_SUCCESS;
}
@@ -1097,17 +1105,17 @@ static sljit_si emit_not_with_flags(struct sljit_compiler *compiler,
sljit_ub* inst;
if (dst == SLJIT_UNUSED) {
- EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
- inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
+ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
+ inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0);
FAIL_IF(!inst);
*inst++ = GROUP_F7;
*inst |= NOT_rm;
- inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, TMP_REGISTER, 0);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, TMP_REG1, 0);
FAIL_IF(!inst);
*inst = OR_r_rm;
return SLJIT_SUCCESS;
}
- if (dst <= TMP_REGISTER) {
+ if (FAST_IS_REG(dst)) {
EMIT_MOV(compiler, dst, 0, src, srcw);
inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
FAIL_IF(!inst);
@@ -1118,15 +1126,15 @@ static sljit_si emit_not_with_flags(struct sljit_compiler *compiler,
*inst = OR_r_rm;
return SLJIT_SUCCESS;
}
- EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
- inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
+ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
+ inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0);
FAIL_IF(!inst);
*inst++ = GROUP_F7;
*inst |= NOT_rm;
- inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, TMP_REGISTER, 0);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, TMP_REG1, 0);
FAIL_IF(!inst);
*inst = OR_r_rm;
- EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
return SLJIT_SUCCESS;
}
@@ -1140,15 +1148,15 @@ static sljit_si emit_clz(struct sljit_compiler *compiler, sljit_si op_flags,
SLJIT_UNUSED_ARG(op_flags);
if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
/* Just set the zero flag. */
- EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
- inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
+ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
+ inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0);
FAIL_IF(!inst);
*inst++ = GROUP_F7;
*inst |= NOT_rm;
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 31, TMP_REGISTER, 0);
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 31, TMP_REG1, 0);
#else
- inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, !(op_flags & SLJIT_INT_OP) ? 63 : 31, TMP_REGISTER, 0);
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, !(op_flags & SLJIT_INT_OP) ? 63 : 31, TMP_REG1, 0);
#endif
FAIL_IF(!inst);
*inst |= SHR;
@@ -1156,24 +1164,24 @@ static sljit_si emit_clz(struct sljit_compiler *compiler, sljit_si op_flags,
}
if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
- EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_IMM, srcw);
- src = TMP_REGISTER;
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw);
+ src = TMP_REG1;
srcw = 0;
}
- inst = emit_x86_instruction(compiler, 2, TMP_REGISTER, 0, src, srcw);
+ inst = emit_x86_instruction(compiler, 2, TMP_REG1, 0, src, srcw);
FAIL_IF(!inst);
*inst++ = GROUP_0F;
*inst = BSR_r_rm;
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- if (dst <= TMP_REGISTER)
+ if (FAST_IS_REG(dst))
dst_r = dst;
else {
/* Find an unused temporary register. */
- if ((dst & 0xf) != SLJIT_SCRATCH_REG1 && (dst & 0xf0) != (SLJIT_SCRATCH_REG1 << 4))
+ if ((dst & REG_MASK) != SLJIT_SCRATCH_REG1 && (dst & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_SCRATCH_REG1))
dst_r = SLJIT_SCRATCH_REG1;
- else if ((dst & 0xf) != SLJIT_SCRATCH_REG2 && (dst & 0xf0) != (SLJIT_SCRATCH_REG2 << 4))
+ else if ((dst & REG_MASK) != SLJIT_SCRATCH_REG2 && (dst & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_SCRATCH_REG2))
dst_r = SLJIT_SCRATCH_REG2;
else
dst_r = SLJIT_SCRATCH_REG3;
@@ -1181,7 +1189,7 @@ static sljit_si emit_clz(struct sljit_compiler *compiler, sljit_si op_flags,
}
EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, 32 + 31);
#else
- dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REG2;
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
compiler->mode32 = 0;
EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, !(op_flags & SLJIT_INT_OP) ? 64 + 63 : 32 + 31);
compiler->mode32 = op_flags & SLJIT_INT_OP;
@@ -1191,7 +1199,7 @@ static sljit_si emit_clz(struct sljit_compiler *compiler, sljit_si op_flags,
get_cpu_features();
if (cpu_has_cmov) {
- inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REGISTER, 0);
+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG1, 0);
FAIL_IF(!inst);
*inst++ = GROUP_0F;
*inst = CMOVNE_r_rm;
@@ -1204,7 +1212,7 @@ static sljit_si emit_clz(struct sljit_compiler *compiler, sljit_si op_flags,
*inst++ = JE_i8;
*inst++ = 2;
*inst++ = MOV_r_rm;
- *inst++ = MOD_REG | (reg_map[dst_r] << 3) | reg_map[TMP_REGISTER];
+ *inst++ = MOD_REG | (reg_map[dst_r] << 3) | reg_map[TMP_REG1];
#else
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
FAIL_IF(!inst);
@@ -1212,9 +1220,9 @@ static sljit_si emit_clz(struct sljit_compiler *compiler, sljit_si op_flags,
*inst++ = JE_i8;
*inst++ = 3;
- *inst++ = REX_W | (reg_map[dst_r] >= 8 ? REX_R : 0) | (reg_map[TMP_REGISTER] >= 8 ? REX_B : 0);
+ *inst++ = REX_W | (reg_map[dst_r] >= 8 ? REX_R : 0) | (reg_map[TMP_REG1] >= 8 ? REX_B : 0);
*inst++ = MOV_r_rm;
- *inst++ = MOD_REG | (reg_lmap[dst_r] << 3) | reg_lmap[TMP_REGISTER];
+ *inst++ = MOD_REG | (reg_lmap[dst_r] << 3) | reg_lmap[TMP_REG1];
#endif
}
@@ -1271,7 +1279,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
#endif
if (op_flags & SLJIT_INT_OP) {
- if (src <= TMP_REGISTER && src == dst) {
+ if (FAST_IS_REG(src) && src == dst) {
if (!TYPE_CAST_NEEDED(op))
return SLJIT_SUCCESS;
}
@@ -1322,8 +1330,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
#endif
}
- if (SLJIT_UNLIKELY(update) && (src & SLJIT_MEM) && !src_is_ereg && (src & 0xf) && (srcw != 0 || (src & 0xf0) != 0)) {
- inst = emit_x86_instruction(compiler, 1, src & 0xf, 0, src, srcw);
+ if (SLJIT_UNLIKELY(update) && (src & SLJIT_MEM) && !src_is_ereg && (src & REG_MASK) && (srcw != 0 || (src & OFFS_REG_MASK) != 0)) {
+ inst = emit_x86_instruction(compiler, 1, src & REG_MASK, 0, src, srcw);
FAIL_IF(!inst);
*inst = LEA_r_m;
src &= SLJIT_MEM | 0xf;
@@ -1333,7 +1341,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
if (SLJIT_UNLIKELY(dst_is_ereg) && (!(op == SLJIT_MOV || op == SLJIT_MOV_UI || op == SLJIT_MOV_SI || op == SLJIT_MOV_P) || (src & SLJIT_MEM))) {
SLJIT_ASSERT(dst == SLJIT_MEM1(SLJIT_LOCALS_REG));
- dst = TMP_REGISTER;
+ dst = TMP_REG1;
}
#endif
@@ -1369,12 +1377,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
}
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- if (SLJIT_UNLIKELY(dst_is_ereg) && dst == TMP_REGISTER)
- return emit_mov(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), dstw, TMP_REGISTER, 0);
+ if (SLJIT_UNLIKELY(dst_is_ereg) && dst == TMP_REG1)
+ return emit_mov(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), dstw, TMP_REG1, 0);
#endif
- if (SLJIT_UNLIKELY(update) && (dst & SLJIT_MEM) && (dst & 0xf) && (dstw != 0 || (dst & 0xf0) != 0)) {
- inst = emit_x86_instruction(compiler, 1, dst & 0xf, 0, dst, dstw);
+ if (SLJIT_UNLIKELY(update) && (dst & SLJIT_MEM) && (dst & REG_MASK) && (dstw != 0 || (dst & OFFS_REG_MASK) != 0)) {
+ inst = emit_x86_instruction(compiler, 1, dst & REG_MASK, 0, dst, dstw);
FAIL_IF(!inst);
*inst = LEA_r_m;
}
@@ -1447,12 +1455,12 @@ static sljit_si emit_cum_binary(struct sljit_compiler *compiler,
sljit_ub* inst;
if (dst == SLJIT_UNUSED) {
- EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
if (src2 & SLJIT_IMM) {
- BINARY_IMM(op_imm, op_mr, src2w, TMP_REGISTER, 0);
+ BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0);
}
else {
- inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);
FAIL_IF(!inst);
*inst = op_rm;
}
@@ -1472,20 +1480,20 @@ static sljit_si emit_cum_binary(struct sljit_compiler *compiler,
BINARY_IMM(op_imm, op_mr, src2w, dst, dstw);
}
}
- else if (dst <= TMP_REGISTER) {
+ else if (FAST_IS_REG(dst)) {
inst = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w);
FAIL_IF(!inst);
*inst = op_rm;
}
- else if (src2 <= TMP_REGISTER) {
+ else if (FAST_IS_REG(src2)) {
/* Special exception for sljit_emit_op_flags. */
inst = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw);
FAIL_IF(!inst);
*inst = op_mr;
}
else {
- EMIT_MOV(compiler, TMP_REGISTER, 0, src2, src2w);
- inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw);
+ EMIT_MOV(compiler, TMP_REG1, 0, src2, src2w);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);
FAIL_IF(!inst);
*inst = op_mr;
}
@@ -1506,19 +1514,19 @@ static sljit_si emit_cum_binary(struct sljit_compiler *compiler,
BINARY_IMM(op_imm, op_mr, src1w, dst, dstw);
}
}
- else if (dst <= TMP_REGISTER) {
+ else if (FAST_IS_REG(dst)) {
inst = emit_x86_instruction(compiler, 1, dst, dstw, src1, src1w);
FAIL_IF(!inst);
*inst = op_rm;
}
- else if (src1 <= TMP_REGISTER) {
+ else if (FAST_IS_REG(src1)) {
inst = emit_x86_instruction(compiler, 1, src1, src1w, dst, dstw);
FAIL_IF(!inst);
*inst = op_mr;
}
else {
- EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
- inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw);
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);
FAIL_IF(!inst);
*inst = op_mr;
}
@@ -1526,7 +1534,7 @@ static sljit_si emit_cum_binary(struct sljit_compiler *compiler,
}
/* General version. */
- if (dst <= TMP_REGISTER) {
+ if (FAST_IS_REG(dst)) {
EMIT_MOV(compiler, dst, 0, src1, src1w);
if (src2 & SLJIT_IMM) {
BINARY_IMM(op_imm, op_mr, src2w, dst, 0);
@@ -1539,16 +1547,16 @@ static sljit_si emit_cum_binary(struct sljit_compiler *compiler,
}
else {
/* This version requires less memory writing. */
- EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
if (src2 & SLJIT_IMM) {
- BINARY_IMM(op_imm, op_mr, src2w, TMP_REGISTER, 0);
+ BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0);
}
else {
- inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);
FAIL_IF(!inst);
*inst = op_rm;
}
- EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
}
return SLJIT_SUCCESS;
@@ -1563,12 +1571,12 @@ static sljit_si emit_non_cum_binary(struct sljit_compiler *compiler,
sljit_ub* inst;
if (dst == SLJIT_UNUSED) {
- EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
if (src2 & SLJIT_IMM) {
- BINARY_IMM(op_imm, op_mr, src2w, TMP_REGISTER, 0);
+ BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0);
}
else {
- inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);
FAIL_IF(!inst);
*inst = op_rm;
}
@@ -1588,19 +1596,19 @@ static sljit_si emit_non_cum_binary(struct sljit_compiler *compiler,
BINARY_IMM(op_imm, op_mr, src2w, dst, dstw);
}
}
- else if (dst <= TMP_REGISTER) {
+ else if (FAST_IS_REG(dst)) {
inst = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w);
FAIL_IF(!inst);
*inst = op_rm;
}
- else if (src2 <= TMP_REGISTER) {
+ else if (FAST_IS_REG(src2)) {
inst = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw);
FAIL_IF(!inst);
*inst = op_mr;
}
else {
- EMIT_MOV(compiler, TMP_REGISTER, 0, src2, src2w);
- inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw);
+ EMIT_MOV(compiler, TMP_REG1, 0, src2, src2w);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);
FAIL_IF(!inst);
*inst = op_mr;
}
@@ -1608,7 +1616,7 @@ static sljit_si emit_non_cum_binary(struct sljit_compiler *compiler,
}
/* General version. */
- if (dst <= TMP_REGISTER && dst != src2) {
+ if (FAST_IS_REG(dst) && dst != src2) {
EMIT_MOV(compiler, dst, 0, src1, src1w);
if (src2 & SLJIT_IMM) {
BINARY_IMM(op_imm, op_mr, src2w, dst, 0);
@@ -1621,16 +1629,16 @@ static sljit_si emit_non_cum_binary(struct sljit_compiler *compiler,
}
else {
/* This version requires less memory writing. */
- EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
if (src2 & SLJIT_IMM) {
- BINARY_IMM(op_imm, op_mr, src2w, TMP_REGISTER, 0);
+ BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0);
}
else {
- inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);
FAIL_IF(!inst);
*inst = op_rm;
}
- EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
}
return SLJIT_SUCCESS;
@@ -1644,7 +1652,7 @@ static sljit_si emit_mul(struct sljit_compiler *compiler,
sljit_ub* inst;
sljit_si dst_r;
- dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
/* Register destination. */
if (dst_r == src1 && !(src2 & SLJIT_IMM)) {
@@ -1752,7 +1760,7 @@ static sljit_si emit_mul(struct sljit_compiler *compiler,
else {
/* Neither argument is immediate. */
if (ADDRESSING_DEPENDS_ON(src2, dst_r))
- dst_r = TMP_REGISTER;
+ dst_r = TMP_REG1;
EMIT_MOV(compiler, dst_r, 0, src1, src1w);
inst = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w);
FAIL_IF(!inst);
@@ -1760,8 +1768,8 @@ static sljit_si emit_mul(struct sljit_compiler *compiler,
*inst = IMUL_r_rm;
}
- if (dst_r == TMP_REGISTER)
- EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
+ if (dst_r == TMP_REG1)
+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
return SLJIT_SUCCESS;
}
@@ -1782,10 +1790,10 @@ static sljit_si emit_lea_binary(struct sljit_compiler *compiler, sljit_si keep_f
return SLJIT_ERR_UNSUPPORTED;
}
- dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
- if (src1 <= TMP_REGISTER) {
- if (src2 <= TMP_REGISTER || src2 == TMP_REGISTER) {
+ if (FAST_IS_REG(src1)) {
+ if (FAST_IS_REG(src2)) {
inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM2(src1, src2), 0);
FAIL_IF(!inst);
*inst = LEA_r_m;
@@ -1803,7 +1811,7 @@ static sljit_si emit_lea_binary(struct sljit_compiler *compiler, sljit_si keep_f
done = 1;
}
}
- else if (src2 <= TMP_REGISTER) {
+ else if (FAST_IS_REG(src2)) {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if ((src1 & SLJIT_IMM) && (compiler->mode32 || IS_HALFWORD(src1w))) {
inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), (sljit_si)src1w);
@@ -1818,8 +1826,8 @@ static sljit_si emit_lea_binary(struct sljit_compiler *compiler, sljit_si keep_f
}
if (done) {
- if (dst_r == TMP_REGISTER)
- return emit_mov(compiler, dst, dstw, TMP_REGISTER, 0);
+ if (dst_r == TMP_REG1)
+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
return SLJIT_SUCCESS;
}
return SLJIT_ERR_UNSUPPORTED;
@@ -1840,7 +1848,7 @@ static sljit_si emit_cmp_binary(struct sljit_compiler *compiler,
return SLJIT_SUCCESS;
}
- if (src1 <= TMP_REGISTER) {
+ if (FAST_IS_REG(src1)) {
if (src2 & SLJIT_IMM) {
BINARY_IMM(CMP, CMP_rm_r, src2w, src1, 0);
}
@@ -1852,7 +1860,7 @@ static sljit_si emit_cmp_binary(struct sljit_compiler *compiler,
return SLJIT_SUCCESS;
}
- if (src2 <= TMP_REGISTER && !(src1 & SLJIT_IMM)) {
+ if (FAST_IS_REG(src2) && !(src1 & SLJIT_IMM)) {
inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w);
FAIL_IF(!inst);
*inst = CMP_rm_r;
@@ -1861,15 +1869,15 @@ static sljit_si emit_cmp_binary(struct sljit_compiler *compiler,
if (src2 & SLJIT_IMM) {
if (src1 & SLJIT_IMM) {
- EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
- src1 = TMP_REGISTER;
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+ src1 = TMP_REG1;
src1w = 0;
}
BINARY_IMM(CMP, CMP_rm_r, src2w, src1, src1w);
}
else {
- EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
- inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);
FAIL_IF(!inst);
*inst = CMP_r_rm;
}
@@ -1900,7 +1908,7 @@ static sljit_si emit_test_binary(struct sljit_compiler *compiler,
return SLJIT_SUCCESS;
}
- if (src1 <= TMP_REGISTER) {
+ if (FAST_IS_REG(src1)) {
if (src2 & SLJIT_IMM) {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if (IS_HALFWORD(src2w) || compiler->mode32) {
@@ -1928,7 +1936,7 @@ static sljit_si emit_test_binary(struct sljit_compiler *compiler,
return SLJIT_SUCCESS;
}
- if (src2 <= TMP_REGISTER) {
+ if (FAST_IS_REG(src2)) {
if (src1 & SLJIT_IMM) {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if (IS_HALFWORD(src1w) || compiler->mode32) {
@@ -1956,28 +1964,28 @@ static sljit_si emit_test_binary(struct sljit_compiler *compiler,
return SLJIT_SUCCESS;
}
- EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
if (src2 & SLJIT_IMM) {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if (IS_HALFWORD(src2w) || compiler->mode32) {
- inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REGISTER, 0);
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REG1, 0);
FAIL_IF(!inst);
*inst = GROUP_F7;
}
else {
FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));
- inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, TMP_REGISTER, 0);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, TMP_REG1, 0);
FAIL_IF(!inst);
*inst = TEST_rm_r;
}
#else
- inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REGISTER, 0);
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REG1, 0);
FAIL_IF(!inst);
*inst = GROUP_F7;
#endif
}
else {
- inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);
FAIL_IF(!inst);
*inst = TEST_rm_r;
}
@@ -2000,21 +2008,21 @@ static sljit_si emit_shift(struct sljit_compiler *compiler,
return SLJIT_SUCCESS;
}
if (dst == SLJIT_UNUSED) {
- EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
- inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REGISTER, 0);
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REG1, 0);
FAIL_IF(!inst);
*inst |= mode;
return SLJIT_SUCCESS;
}
if (dst == SLJIT_PREF_SHIFT_REG && src2 == SLJIT_PREF_SHIFT_REG) {
- EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
- inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
FAIL_IF(!inst);
*inst |= mode;
- EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
return SLJIT_SUCCESS;
}
- if (dst <= TMP_REGISTER) {
+ if (FAST_IS_REG(dst)) {
EMIT_MOV(compiler, dst, 0, src1, src1w);
inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, 0);
FAIL_IF(!inst);
@@ -2022,36 +2030,36 @@ static sljit_si emit_shift(struct sljit_compiler *compiler,
return SLJIT_SUCCESS;
}
- EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
- inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REGISTER, 0);
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REG1, 0);
FAIL_IF(!inst);
*inst |= mode;
- EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
return SLJIT_SUCCESS;
}
if (dst == SLJIT_PREF_SHIFT_REG) {
- EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
- inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
FAIL_IF(!inst);
*inst |= mode;
- EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
}
- else if (dst <= TMP_REGISTER && dst != src2 && !ADDRESSING_DEPENDS_ON(src2, dst)) {
+ else if (FAST_IS_REG(dst) && dst != src2 && !ADDRESSING_DEPENDS_ON(src2, dst)) {
if (src1 != dst)
EMIT_MOV(compiler, dst, 0, src1, src1w);
- EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_PREF_SHIFT_REG, 0);
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_PREF_SHIFT_REG, 0);
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, dst, 0);
FAIL_IF(!inst);
*inst |= mode;
- EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
}
else {
/* This case is really difficult, since ecx itself may used for
addressing, and we must ensure to work even in that case. */
- EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0);
#else
@@ -2059,7 +2067,7 @@ static sljit_si emit_shift(struct sljit_compiler *compiler,
EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), sizeof(sljit_sw), SLJIT_PREF_SHIFT_REG, 0);
#endif
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
- inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
FAIL_IF(!inst);
*inst |= mode;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
@@ -2067,7 +2075,7 @@ static sljit_si emit_shift(struct sljit_compiler *compiler,
#else
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), sizeof(sljit_sw));
#endif
- EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
}
return SLJIT_SUCCESS;
@@ -2098,12 +2106,12 @@ static sljit_si emit_shift_with_flags(struct sljit_compiler *compiler,
if (!set_flags)
return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);
- if (!(dst <= TMP_REGISTER))
+ if (!FAST_IS_REG(dst))
FAIL_IF(emit_cmp_binary(compiler, src1, src1w, SLJIT_IMM, 0));
FAIL_IF(emit_shift(compiler,mode, dst, dstw, src1, src1w, src2, src2w));
- if (dst <= TMP_REGISTER)
+ if (FAST_IS_REG(dst))
return emit_cmp_binary(compiler, dst, dstw, SLJIT_IMM, 0);
return SLJIT_SUCCESS;
}
@@ -2263,7 +2271,9 @@ static void init_compiler(void)
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
{
-#if (defined SLJIT_SSE2 && SLJIT_SSE2)
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return SLJIT_IS_FPU_AVAILABLE;
+#elif (defined SLJIT_SSE2 && SLJIT_SSE2)
#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
if (cpu_has_sse2 == -1)
get_cpu_features();
@@ -2329,7 +2339,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
if (GET_OPCODE(op) == SLJIT_CMPD) {
compiler->flags_saved = 0;
- if (dst <= SLJIT_FLOAT_REG6)
+ if (FAST_IS_REG(dst))
dst_r = dst;
else {
dst_r = TMP_FREG;
@@ -2339,15 +2349,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
}
if (op == SLJIT_MOVD) {
- if (dst <= SLJIT_FLOAT_REG6)
+ if (FAST_IS_REG(dst))
return emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, dst, src, srcw);
- if (src <= SLJIT_FLOAT_REG6)
+ if (FAST_IS_REG(src))
return emit_sse2_store(compiler, op & SLJIT_SINGLE_OP, dst, dstw, src);
FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, TMP_FREG, src, srcw));
return emit_sse2_store(compiler, op & SLJIT_SINGLE_OP, dst, dstw, TMP_FREG);
}
- if (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG6) {
+ if (SLOW_IS_REG(dst)) {
dst_r = dst;
if (dst != src)
FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, dst_r, src, srcw));
@@ -2386,7 +2396,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
compiler->mode32 = 1;
#endif
- if (dst <= SLJIT_FLOAT_REG6) {
+ if (FAST_IS_REG(dst)) {
dst_r = dst;
if (dst == src1)
; /* Do nothing here. */
@@ -2548,8 +2558,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
if (src == SLJIT_SCRATCH_REG3) {
- EMIT_MOV(compiler, TMP_REGISTER, 0, src, 0);
- src = TMP_REGISTER;
+ EMIT_MOV(compiler, TMP_REG1, 0, src, 0);
+ src = TMP_REG1;
}
if (src == SLJIT_MEM1(SLJIT_LOCALS_REG) && type >= SLJIT_CALL3)
srcw += sizeof(sljit_sw);
@@ -2557,8 +2567,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
#endif
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && defined(_WIN64)
if (src == SLJIT_SCRATCH_REG3) {
- EMIT_MOV(compiler, TMP_REGISTER, 0, src, 0);
- src = TMP_REGISTER;
+ EMIT_MOV(compiler, TMP_REG1, 0, src, 0);
+ src = TMP_REG1;
}
#endif
FAIL_IF(call_with_args(compiler, type));
@@ -2626,22 +2636,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
cond_set = get_jump_code(type) + 0x10;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && dst <= TMP_REGISTER && dst == src) {
+ if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst) && dst == src) {
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 + 3);
FAIL_IF(!inst);
INC_SIZE(4 + 3);
/* Set low register to conditional flag. */
- *inst++ = (reg_map[TMP_REGISTER] <= 7) ? REX : REX_B;
+ *inst++ = (reg_map[TMP_REG1] <= 7) ? REX : REX_B;
*inst++ = GROUP_0F;
*inst++ = cond_set;
- *inst++ = MOD_REG | reg_lmap[TMP_REGISTER];
- *inst++ = REX | (reg_map[TMP_REGISTER] <= 7 ? 0 : REX_R) | (reg_map[dst] <= 7 ? 0 : REX_B);
+ *inst++ = MOD_REG | reg_lmap[TMP_REG1];
+ *inst++ = REX | (reg_map[TMP_REG1] <= 7 ? 0 : REX_R) | (reg_map[dst] <= 7 ? 0 : REX_B);
*inst++ = OR_rm8_r8;
- *inst++ = MOD_REG | (reg_lmap[TMP_REGISTER] << 3) | reg_lmap[dst];
+ *inst++ = MOD_REG | (reg_lmap[TMP_REG1] << 3) | reg_lmap[dst];
return SLJIT_SUCCESS;
}
- reg = (op == SLJIT_MOV && dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
+ reg = (op == SLJIT_MOV && FAST_IS_REG(dst)) ? dst : TMP_REG1;
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 + 4);
FAIL_IF(!inst);
@@ -2656,19 +2666,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
*inst++ = MOVZX_r_rm8;
*inst = MOD_REG | (reg_lmap[reg] << 3) | reg_lmap[reg];
- if (reg != TMP_REGISTER)
+ if (reg != TMP_REG1)
return SLJIT_SUCCESS;
if (GET_OPCODE(op) < SLJIT_ADD) {
compiler->mode32 = GET_OPCODE(op) != SLJIT_MOV;
- return emit_mov(compiler, dst, dstw, TMP_REGISTER, 0);
+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
}
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
compiler->skip_checks = 1;
#endif
- return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REGISTER, 0);
+ return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REG1, 0);
#else /* SLJIT_CONFIG_X86_64 */
- if (GET_OPCODE(op) < SLJIT_ADD && dst <= TMP_REGISTER) {
+ if (GET_OPCODE(op) < SLJIT_ADD && FAST_IS_REG(dst)) {
if (reg_map[dst] <= 4) {
/* Low byte is accessible. */
inst = (sljit_ub*)ensure_buf(compiler, 1 + 3 + 3);
@@ -2690,7 +2700,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
get_cpu_features();
if (cpu_has_cmov) {
- EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_IMM, 1);
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, 1);
/* a xor reg, reg operation would overwrite the flags. */
EMIT_MOV(compiler, dst, 0, SLJIT_IMM, 0);
@@ -2701,14 +2711,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
*inst++ = GROUP_0F;
/* cmovcc = setcc - 0x50. */
*inst++ = cond_set - 0x50;
- *inst++ = MOD_REG | (reg_map[dst] << 3) | reg_map[TMP_REGISTER];
+ *inst++ = MOD_REG | (reg_map[dst] << 3) | reg_map[TMP_REG1];
return SLJIT_SUCCESS;
}
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1);
FAIL_IF(!inst);
INC_SIZE(1 + 3 + 3 + 1);
- *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER];
+ *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];
/* Set al to conditional flag. */
*inst++ = GROUP_0F;
*inst++ = cond_set;
@@ -2717,24 +2727,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
*inst++ = GROUP_0F;
*inst++ = MOVZX_r_rm8;
*inst++ = MOD_REG | (reg_map[dst] << 3) | 0 /* eax */;
- *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER];
+ *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];
return SLJIT_SUCCESS;
}
- if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && dst <= TMP_REGISTER && dst == src && reg_map[dst] <= 4) {
+ if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst) && dst == src && reg_map[dst] <= 4) {
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SCRATCH_REG1] == 0, scratch_reg1_must_be_eax);
if (dst != SLJIT_SCRATCH_REG1) {
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 3 + 2 + 1);
FAIL_IF(!inst);
INC_SIZE(1 + 3 + 2 + 1);
/* Set low register to conditional flag. */
- *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER];
+ *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];
*inst++ = GROUP_0F;
*inst++ = cond_set;
*inst++ = MOD_REG | 0 /* eax */;
*inst++ = OR_rm8_r8;
*inst++ = MOD_REG | (0 /* eax */ << 3) | reg_map[dst];
- *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER];
+ *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];
}
else {
inst = (sljit_ub*)ensure_buf(compiler, 1 + 2 + 3 + 2 + 2);
@@ -2742,23 +2752,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
INC_SIZE(2 + 3 + 2 + 2);
/* Set low register to conditional flag. */
*inst++ = XCHG_r_rm;
- *inst++ = MOD_REG | (1 /* ecx */ << 3) | reg_map[TMP_REGISTER];
+ *inst++ = MOD_REG | (1 /* ecx */ << 3) | reg_map[TMP_REG1];
*inst++ = GROUP_0F;
*inst++ = cond_set;
*inst++ = MOD_REG | 1 /* ecx */;
*inst++ = OR_rm8_r8;
*inst++ = MOD_REG | (1 /* ecx */ << 3) | 0 /* eax */;
*inst++ = XCHG_r_rm;
- *inst++ = MOD_REG | (1 /* ecx */ << 3) | reg_map[TMP_REGISTER];
+ *inst++ = MOD_REG | (1 /* ecx */ << 3) | reg_map[TMP_REG1];
}
return SLJIT_SUCCESS;
}
- /* Set TMP_REGISTER to the bit. */
+ /* Set TMP_REG1 to the bit. */
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1);
FAIL_IF(!inst);
INC_SIZE(1 + 3 + 3 + 1);
- *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER];
+ *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];
/* Set al to conditional flag. */
*inst++ = GROUP_0F;
*inst++ = cond_set;
@@ -2768,15 +2778,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
*inst++ = MOVZX_r_rm8;
*inst++ = MOD_REG | (0 << 3) /* eax */ | 0 /* eax */;
- *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER];
+ *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];
if (GET_OPCODE(op) < SLJIT_ADD)
- return emit_mov(compiler, dst, dstw, TMP_REGISTER, 0);
+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
compiler->skip_checks = 1;
#endif
- return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REGISTER, 0);
+ return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0);
#endif /* SLJIT_CONFIG_X86_64 */
}
@@ -2796,12 +2806,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *co
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if (NOT_HALFWORD(offset)) {
- FAIL_IF(emit_load_imm64(compiler, TMP_REGISTER, offset));
+ FAIL_IF(emit_load_imm64(compiler, TMP_REG1, offset));
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
- SLJIT_ASSERT(emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_LOCALS_REG, 0, TMP_REGISTER, 0) != SLJIT_ERR_UNSUPPORTED);
+ SLJIT_ASSERT(emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_LOCALS_REG, 0, TMP_REG1, 0) != SLJIT_ERR_UNSUPPORTED);
return compiler->error;
#else
- return emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_LOCALS_REG, 0, TMP_REGISTER, 0);
+ return emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_LOCALS_REG, 0, TMP_REG1, 0);
#endif
}
#endif
@@ -2831,13 +2841,13 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
compiler->mode32 = 0;
- reg = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
+ reg = SLOW_IS_REG(dst) ? dst : TMP_REG1;
if (emit_load_imm64(compiler, reg, init_value))
return NULL;
#else
if (dst == SLJIT_UNUSED)
- dst = TMP_REGISTER;
+ dst = TMP_REG1;
if (emit_mov(compiler, dst, dstw, SLJIT_IMM, init_value))
return NULL;
@@ -2850,8 +2860,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
*inst++ = 1;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- if (reg == TMP_REGISTER && dst != SLJIT_UNUSED)
- if (emit_mov(compiler, dst, dstw, TMP_REGISTER, 0))
+ if (dst & SLJIT_MEM)
+ if (emit_mov(compiler, dst, dstw, TMP_REG1, 0))
return NULL;
#endif
diff --git a/src/android/accessibility/jar/src/org/qtproject/qt5/android/accessibility/QtAccessibilityDelegate.java b/src/android/accessibility/jar/src/org/qtproject/qt5/android/accessibility/QtAccessibilityDelegate.java
index 3275b90e33..a4626b9bb1 100644
--- a/src/android/accessibility/jar/src/org/qtproject/qt5/android/accessibility/QtAccessibilityDelegate.java
+++ b/src/android/accessibility/jar/src/org/qtproject/qt5/android/accessibility/QtAccessibilityDelegate.java
@@ -346,13 +346,24 @@ public class QtAccessibilityDelegate extends View.AccessibilityDelegate
{
// Log.i(TAG, "ACTION " + action + " on " + virtualViewId);
// dumpNodes(virtualViewId);
+ boolean success = false;
switch (action) {
case AccessibilityNodeInfo.ACTION_CLICK:
- boolean success = QtNativeAccessibility.clickAction(virtualViewId);
+ success = QtNativeAccessibility.clickAction(virtualViewId);
if (success)
sendEventForVirtualViewId(virtualViewId, AccessibilityEvent.TYPE_VIEW_CLICKED);
- return success;
+ break;
+ case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD:
+ success = QtNativeAccessibility.scrollForward(virtualViewId);
+ if (success)
+ sendEventForVirtualViewId(virtualViewId, AccessibilityEvent.TYPE_VIEW_SCROLLED);
+ break;
+ case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD:
+ success = QtNativeAccessibility.scrollBackward(virtualViewId);
+ if (success)
+ sendEventForVirtualViewId(virtualViewId, AccessibilityEvent.TYPE_VIEW_SCROLLED);
+ break;
}
- return false;
+ return success;
}
}
diff --git a/src/android/accessibility/jar/src/org/qtproject/qt5/android/accessibility/QtNativeAccessibility.java b/src/android/accessibility/jar/src/org/qtproject/qt5/android/accessibility/QtNativeAccessibility.java
index 8a53623957..f0bf4a0897 100644
--- a/src/android/accessibility/jar/src/org/qtproject/qt5/android/accessibility/QtNativeAccessibility.java
+++ b/src/android/accessibility/jar/src/org/qtproject/qt5/android/accessibility/QtNativeAccessibility.java
@@ -53,6 +53,8 @@ class QtNativeAccessibility
static native Rect screenRect(int objectId);
static native int hitTest(float x, float y);
static native boolean clickAction(int objectId);
+ static native boolean scrollForward(int objectId);
+ static native boolean scrollBackward(int objectId);
static native boolean populateNode(int objectId, AccessibilityNodeInfo node);
}
diff --git a/src/android/jar/jar.pri b/src/android/jar/jar.pri
index 5906231c73..66feda1d56 100644
--- a/src/android/jar/jar.pri
+++ b/src/android/jar/jar.pri
@@ -12,7 +12,8 @@ JAVASOURCES += \
$$PATHPREFIX/QtMessageDialogHelper.java \
$$PATHPREFIX/QtNative.java \
$$PATHPREFIX/QtNativeLibrariesDir.java \
- $$PATHPREFIX/QtSurface.java
+ $$PATHPREFIX/QtSurface.java \
+ $$PATHPREFIX/ExtractStyle.java
# install
target.path = $$[QT_INSTALL_PREFIX]/jar
diff --git a/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java b/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java
new file mode 100644
index 0000000000..ef6d20fc9a
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java
@@ -0,0 +1,1686 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Android port 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+package org.qtproject.qt5.android;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.xmlpull.v1.XmlPullParser;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Canvas;
+import android.graphics.NinePatch;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ClipDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.GradientDrawable.Orientation;
+import android.graphics.drawable.LayerDrawable;
+import android.graphics.drawable.NinePatchDrawable;
+import android.graphics.drawable.RotateDrawable;
+import android.graphics.drawable.ScaleDrawable;
+import android.graphics.drawable.StateListDrawable;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+import android.view.inputmethod.EditorInfo;
+
+
+public class ExtractStyle {
+
+ native static int[] extractChunkInfo(byte[] chunkData);
+ native static int[] extractNativeChunkInfo(int nativeChunk);
+
+ Class<?> styleableClass = getStylableClass();
+ final int[] EMPTY_STATE_SET = {};
+ final int[] ENABLED_STATE_SET = {android.R.attr.state_enabled};
+ final int[] FOCUSED_STATE_SET = {android.R.attr.state_focused};
+ final int[] SELECTED_STATE_SET = {android.R.attr.state_selected};
+ final int[] PRESSED_STATE_SET = {android.R.attr.state_pressed};
+ final int[] WINDOW_FOCUSED_STATE_SET = {android.R.attr.state_window_focused};
+ final int[] ENABLED_FOCUSED_STATE_SET = stateSetUnion(ENABLED_STATE_SET, FOCUSED_STATE_SET);
+ final int[] ENABLED_SELECTED_STATE_SET = stateSetUnion(ENABLED_STATE_SET, SELECTED_STATE_SET);
+ final int[] ENABLED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(ENABLED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
+ final int[] FOCUSED_SELECTED_STATE_SET = stateSetUnion(FOCUSED_STATE_SET, SELECTED_STATE_SET);
+ final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
+ final int[] SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
+ final int[] ENABLED_FOCUSED_SELECTED_STATE_SET = stateSetUnion(ENABLED_FOCUSED_STATE_SET, SELECTED_STATE_SET);
+ final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(ENABLED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
+ final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(ENABLED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
+ final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
+ final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(ENABLED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
+ final int[] PRESSED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
+ final int[] PRESSED_SELECTED_STATE_SET = stateSetUnion(PRESSED_STATE_SET, SELECTED_STATE_SET);
+ final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
+ final int[] PRESSED_FOCUSED_STATE_SET = stateSetUnion(PRESSED_STATE_SET, FOCUSED_STATE_SET);
+ final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
+ final int[] PRESSED_FOCUSED_SELECTED_STATE_SET = stateSetUnion(PRESSED_FOCUSED_STATE_SET, SELECTED_STATE_SET);
+ final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
+ final int[] PRESSED_ENABLED_STATE_SET = stateSetUnion(PRESSED_STATE_SET, ENABLED_STATE_SET);
+ final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_ENABLED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
+ final int[] PRESSED_ENABLED_SELECTED_STATE_SET = stateSetUnion(PRESSED_ENABLED_STATE_SET, SELECTED_STATE_SET);
+ final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_ENABLED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
+ final int[] PRESSED_ENABLED_FOCUSED_STATE_SET = stateSetUnion(PRESSED_ENABLED_STATE_SET, FOCUSED_STATE_SET);
+ final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_ENABLED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
+ final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = stateSetUnion(PRESSED_ENABLED_FOCUSED_STATE_SET, SELECTED_STATE_SET);
+ final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
+
+
+ final int View_background = getField(styleableClass,"View_background");
+ final int View_padding = getField(styleableClass,"View_padding");
+ final int View_paddingLeft = getField(styleableClass,"View_paddingLeft");
+ final int View_paddingTop = getField(styleableClass,"View_paddingTop");
+ final int View_paddingRight = getField(styleableClass,"View_paddingRight");
+ final int View_paddingBottom = getField(styleableClass,"View_paddingBottom");
+ final int View_scrollX = getField(styleableClass,"View_scrollX");
+ final int View_scrollY = getField(styleableClass,"View_scrollY");
+ final int View_id = getField(styleableClass,"View_id");
+ final int View_tag = getField(styleableClass,"View_tag");
+ final int View_fitsSystemWindows = getField(styleableClass,"View_fitsSystemWindows");
+ final int View_focusable = getField(styleableClass,"View_focusable");
+ final int View_focusableInTouchMode = getField(styleableClass,"View_focusableInTouchMode");
+ final int View_clickable = getField(styleableClass,"View_clickable");
+ final int View_longClickable = getField(styleableClass,"View_longClickable");
+ final int View_saveEnabled = getField(styleableClass,"View_saveEnabled");
+ final int View_duplicateParentState = getField(styleableClass,"View_duplicateParentState");
+ final int View_visibility = getField(styleableClass,"View_visibility");
+ final int View_drawingCacheQuality = getField(styleableClass,"View_drawingCacheQuality");
+ final int View_contentDescription = getField(styleableClass,"View_contentDescription");
+ final int View_soundEffectsEnabled = getField(styleableClass,"View_soundEffectsEnabled");
+ final int View_hapticFeedbackEnabled = getField(styleableClass,"View_hapticFeedbackEnabled");
+ final int View_scrollbars = getField(styleableClass,"View_scrollbars");
+ final int View_fadingEdge = getField(styleableClass,"View_fadingEdge");
+ final int View_scrollbarStyle = getField(styleableClass,"View_scrollbarStyle");
+ final int View_scrollbarFadeDuration = getField(styleableClass,"View_scrollbarFadeDuration");
+ final int View_scrollbarDefaultDelayBeforeFade = getField(styleableClass,"View_scrollbarDefaultDelayBeforeFade");
+ final int View_scrollbarSize = getField(styleableClass,"View_scrollbarSize");
+ final int View_scrollbarThumbHorizontal = getField(styleableClass,"View_scrollbarThumbHorizontal");
+ final int View_scrollbarThumbVertical = getField(styleableClass,"View_scrollbarThumbVertical");
+ final int View_scrollbarTrackHorizontal = getField(styleableClass,"View_scrollbarTrackHorizontal");
+ final int View_scrollbarTrackVertical = getField(styleableClass,"View_scrollbarTrackVertical");
+ final int View_isScrollContainer = getField(styleableClass,"View_isScrollContainer");
+ final int View_keepScreenOn = getField(styleableClass,"View_keepScreenOn");
+ final int View_filterTouchesWhenObscured = getField(styleableClass,"View_filterTouchesWhenObscured");
+ final int View_nextFocusLeft = getField(styleableClass,"View_nextFocusLeft");
+ final int View_nextFocusRight = getField(styleableClass,"View_nextFocusRight");
+ final int View_nextFocusUp = getField(styleableClass,"View_nextFocusUp");
+ final int View_nextFocusDown = getField(styleableClass,"View_nextFocusDown");
+ final int View_minWidth = getField(styleableClass,"View_minWidth");
+ final int View_minHeight = getField(styleableClass,"View_minHeight");
+ final int View_onClick = getField(styleableClass,"View_onClick");
+ final int View_overScrollMode = getField(styleableClass,"View_overScrollMode");
+ final int View_paddingStart = getField(styleableClass,"View_paddingStart");
+ final int View_paddingEnd = getField(styleableClass,"View_paddingEnd");
+
+ final int TextAppearance_textColorHighlight = getField(styleableClass,"TextAppearance_textColorHighlight");
+ final int TextAppearance_textColor = getField(styleableClass,"TextAppearance_textColor");
+ final int TextAppearance_textColorHint = getField(styleableClass,"TextAppearance_textColorHint");
+ final int TextAppearance_textColorLink = getField(styleableClass,"TextAppearance_textColorLink");
+ final int TextAppearance_textSize = getField(styleableClass,"TextAppearance_textSize");
+ final int TextAppearance_typeface = getField(styleableClass,"TextAppearance_typeface");
+ final int TextAppearance_textStyle = getField(styleableClass,"TextAppearance_textStyle");
+ final int TextAppearance_textAllCaps = getField(styleableClass,"TextAppearance_textAllCaps");
+ final int TextView_editable = getField(styleableClass,"TextView_editable");
+ final int TextView_inputMethod = getField(styleableClass,"TextView_inputMethod");
+ final int TextView_numeric = getField(styleableClass,"TextView_numeric");
+ final int TextView_digits = getField(styleableClass,"TextView_digits");
+ final int TextView_phoneNumber = getField(styleableClass,"TextView_phoneNumber");
+ final int TextView_autoText = getField(styleableClass,"TextView_autoText");
+ final int TextView_capitalize = getField(styleableClass,"TextView_capitalize");
+ final int TextView_bufferType = getField(styleableClass,"TextView_bufferType");
+ final int TextView_selectAllOnFocus = getField(styleableClass,"TextView_selectAllOnFocus");
+ final int TextView_autoLink = getField(styleableClass,"TextView_autoLink");
+ final int TextView_linksClickable = getField(styleableClass,"TextView_linksClickable");
+ final int TextView_drawableLeft = getField(styleableClass,"TextView_drawableLeft");
+ final int TextView_drawableTop = getField(styleableClass,"TextView_drawableTop");
+ final int TextView_drawableRight = getField(styleableClass,"TextView_drawableRight");
+ final int TextView_drawableBottom = getField(styleableClass,"TextView_drawableBottom");
+ final int TextView_drawableStart = getField(styleableClass,"TextView_drawableStart");
+ final int TextView_drawableEnd = getField(styleableClass,"TextView_drawableEnd");
+ final int TextView_drawablePadding = getField(styleableClass,"TextView_drawablePadding");
+ final int TextView_textCursorDrawable = getField(styleableClass,"TextView_textCursorDrawable");
+ final int TextView_maxLines = getField(styleableClass,"TextView_maxLines");
+ final int TextView_maxHeight = getField(styleableClass,"TextView_maxHeight");
+ final int TextView_lines = getField(styleableClass,"TextView_lines");
+ final int TextView_height = getField(styleableClass,"TextView_height");
+ final int TextView_minLines = getField(styleableClass,"TextView_minLines");
+ final int TextView_minHeight = getField(styleableClass,"TextView_minHeight");
+ final int TextView_maxEms = getField(styleableClass,"TextView_maxEms");
+ final int TextView_maxWidth = getField(styleableClass,"TextView_maxWidth");
+ final int TextView_ems = getField(styleableClass,"TextView_ems");
+ final int TextView_width = getField(styleableClass,"TextView_width");
+ final int TextView_minEms = getField(styleableClass,"TextView_minEms");
+ final int TextView_minWidth = getField(styleableClass,"TextView_minWidth");
+ final int TextView_gravity = getField(styleableClass,"TextView_gravity");
+ final int TextView_hint = getField(styleableClass,"TextView_hint");
+ final int TextView_text = getField(styleableClass,"TextView_text");
+ final int TextView_scrollHorizontally = getField(styleableClass,"TextView_scrollHorizontally");
+ final int TextView_singleLine = getField(styleableClass,"TextView_singleLine");
+ final int TextView_ellipsize = getField(styleableClass,"TextView_ellipsize");
+ final int TextView_marqueeRepeatLimit = getField(styleableClass,"TextView_marqueeRepeatLimit");
+ final int TextView_includeFontPadding = getField(styleableClass,"TextView_includeFontPadding");
+ final int TextView_cursorVisible = getField(styleableClass,"TextView_cursorVisible");
+ final int TextView_maxLength = getField(styleableClass,"TextView_maxLength");
+ final int TextView_textScaleX = getField(styleableClass,"TextView_textScaleX");
+ final int TextView_freezesText = getField(styleableClass,"TextView_freezesText");
+ final int TextView_shadowColor = getField(styleableClass,"TextView_shadowColor");
+ final int TextView_shadowDx = getField(styleableClass,"TextView_shadowDx");
+ final int TextView_shadowDy = getField(styleableClass,"TextView_shadowDy");
+ final int TextView_shadowRadius = getField(styleableClass,"TextView_shadowRadius");
+ final int TextView_enabled = getField(styleableClass,"TextView_enabled");
+ final int TextView_textColorHighlight = getField(styleableClass,"TextView_textColorHighlight");
+ final int TextView_textColor = getField(styleableClass,"TextView_textColor");
+ final int TextView_textColorHint = getField(styleableClass,"TextView_textColorHint");
+ final int TextView_textColorLink = getField(styleableClass,"TextView_textColorLink");
+ final int TextView_textSize = getField(styleableClass,"TextView_textSize");
+ final int TextView_typeface = getField(styleableClass,"TextView_typeface");
+ final int TextView_textStyle = getField(styleableClass,"TextView_textStyle");
+ final int TextView_password = getField(styleableClass,"TextView_password");
+ final int TextView_lineSpacingExtra = getField(styleableClass,"TextView_lineSpacingExtra");
+ final int TextView_lineSpacingMultiplier = getField(styleableClass,"TextView_lineSpacingMultiplier");
+ final int TextView_inputType = getField(styleableClass,"TextView_inputType");
+ final int TextView_imeOptions = getField(styleableClass,"TextView_imeOptions");
+ final int TextView_imeActionLabel = getField(styleableClass,"TextView_imeActionLabel");
+ final int TextView_imeActionId = getField(styleableClass,"TextView_imeActionId");
+ final int TextView_privateImeOptions = getField(styleableClass,"TextView_privateImeOptions");
+ final int TextView_textSelectHandleLeft = getField(styleableClass,"TextView_textSelectHandleLeft");
+ final int TextView_textSelectHandleRight = getField(styleableClass,"TextView_textSelectHandleRight");
+ final int TextView_textSelectHandle = getField(styleableClass,"TextView_textSelectHandle");
+ final int TextView_textIsSelectable = getField(styleableClass,"TextView_textIsSelectable");
+ final int TextView_textAllCaps = getField(styleableClass,"TextView_textAllCaps");
+
+ final int ImageView_src = getField(styleableClass,"ImageView_src");
+ final int ImageView_baselineAlignBottom = getField(styleableClass,"ImageView_baselineAlignBottom");
+ final int ImageView_adjustViewBounds = getField(styleableClass,"ImageView_adjustViewBounds");
+ final int ImageView_maxWidth = getField(styleableClass,"ImageView_maxWidth");
+ final int ImageView_maxHeight = getField(styleableClass,"ImageView_maxHeight");
+ final int ImageView_scaleType = getField(styleableClass,"ImageView_scaleType");
+ final int ImageView_tint = getField(styleableClass,"ImageView_tint");
+ final int ImageView_cropToPadding = getField(styleableClass,"ImageView_cropToPadding");
+
+ final Resources.Theme m_theme;
+ final String m_extractPath;
+ Context m_context;
+ final int defaultBackgroundColor;
+ final int defaultTextColor;
+
+ class SimpleJsonWriter
+ {
+ private OutputStreamWriter m_writer;
+ private boolean m_addComma = false;
+ private int m_indentLevel = 0;
+ public SimpleJsonWriter(String filePath) throws FileNotFoundException
+ {
+ m_writer = new OutputStreamWriter(new FileOutputStream(filePath));
+ }
+
+ public void close() throws IOException
+ {
+ m_writer.close();
+ }
+
+ private void writeIndent() throws IOException
+ {
+ m_writer.write(" ", 0, m_indentLevel);
+ }
+
+ SimpleJsonWriter beginObject() throws IOException
+ {
+ writeIndent();
+ m_writer.write("{\n");
+ ++m_indentLevel;
+ m_addComma = false;
+ return this;
+ }
+
+ SimpleJsonWriter endObject() throws IOException
+ {
+ m_writer.write("\n");
+ writeIndent();
+ m_writer.write("}\n");
+ --m_indentLevel;
+ m_addComma = false;
+ return this;
+ }
+
+ SimpleJsonWriter name(String name) throws IOException
+ {
+ if (m_addComma) {
+ m_writer.write(",\n");
+ }
+ writeIndent();
+ m_writer.write(JSONObject.quote(name) + ": ");
+ m_addComma = true;
+ return this;
+ }
+
+ SimpleJsonWriter value(JSONObject value) throws IOException
+ {
+ m_writer.write(value.toString());
+ return this;
+ }
+ }
+
+ class FakeCanvas extends Canvas {
+ int[] chunkData = null;
+ class Size {
+ public int s,e;
+ Size(int start, int end)
+ {
+ s=start;
+ e=end;
+ }
+ }
+
+ public boolean isHardwareAccelerated() {
+ return true;
+ }
+
+ public void drawPatch(Bitmap bmp, byte[] chunks, RectF dst, Paint paint) {
+ chunkData = extractChunkInfo(chunks);
+ }
+ }
+
+
+
+ private int[] stateSetUnion(final int[] stateSet1, final int[] stateSet2)
+ {
+ try
+ {
+ final int stateSet1Length = stateSet1.length;
+ final int stateSet2Length = stateSet2.length;
+ final int[] newSet = new int[stateSet1Length + stateSet2Length];
+ int k = 0;
+ int i = 0;
+ int j = 0;
+ // This is a merge of the two input state sets and assumes that the
+ // input sets are sorted by the order imposed by ViewDrawableStates.
+ int[] viewDrawableStatesState=(int[]) styleableClass.getDeclaredField("ViewDrawableStates").get(null);
+ for (int viewState : viewDrawableStatesState)
+ {
+ if (i < stateSet1Length && stateSet1[i] == viewState)
+ {
+ newSet[k++] = viewState;
+ i++;
+ } else if (j < stateSet2Length && stateSet2[j] == viewState) {
+ newSet[k++] = viewState;
+ j++;
+ }
+ if (k > 1) {
+ assert(newSet[k - 1] > newSet[k - 2]);
+ }
+ }
+ return newSet;
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ private Class<?> getStylableClass() {
+ try {
+ return Class.forName("android.R$styleable");
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ int getField(Class<?> clazz, String fieldName)
+ {
+ try {
+ return clazz.getDeclaredField(fieldName).getInt(null);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return -1;
+ }
+
+ JSONObject getColorStateList(ColorStateList colorList)
+ {
+ JSONObject json = new JSONObject();
+ try
+ {
+ json.put("EMPTY_STATE_SET", colorList.getColorForState(EMPTY_STATE_SET, 0));
+ json.put("WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(WINDOW_FOCUSED_STATE_SET, 0));
+ json.put("SELECTED_STATE_SET", colorList.getColorForState(SELECTED_STATE_SET, 0));
+ json.put("SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(SELECTED_WINDOW_FOCUSED_STATE_SET, 0));
+ json.put("FOCUSED_STATE_SET", colorList.getColorForState(FOCUSED_STATE_SET, 0));
+ json.put("FOCUSED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(FOCUSED_WINDOW_FOCUSED_STATE_SET, 0));
+ json.put("FOCUSED_SELECTED_STATE_SET", colorList.getColorForState(FOCUSED_SELECTED_STATE_SET, 0));
+ json.put("FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0));
+ json.put("ENABLED_STATE_SET", colorList.getColorForState(ENABLED_STATE_SET, 0));
+ json.put("ENABLED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(ENABLED_WINDOW_FOCUSED_STATE_SET, 0));
+ json.put("ENABLED_SELECTED_STATE_SET", colorList.getColorForState(ENABLED_SELECTED_STATE_SET, 0));
+ json.put("ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0));
+ json.put("ENABLED_FOCUSED_STATE_SET", colorList.getColorForState(ENABLED_FOCUSED_STATE_SET, 0));
+ json.put("ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET, 0));
+ json.put("ENABLED_FOCUSED_SELECTED_STATE_SET", colorList.getColorForState(ENABLED_FOCUSED_SELECTED_STATE_SET, 0));
+ json.put("ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0));
+ json.put("PRESSED_STATE_SET", colorList.getColorForState(PRESSED_STATE_SET, 0));
+ json.put("PRESSED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_WINDOW_FOCUSED_STATE_SET, 0));
+ json.put("PRESSED_SELECTED_STATE_SET", colorList.getColorForState(PRESSED_SELECTED_STATE_SET, 0));
+ json.put("PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0));
+ json.put("PRESSED_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_FOCUSED_STATE_SET, 0));
+ json.put("PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET, 0));
+ json.put("PRESSED_FOCUSED_SELECTED_STATE_SET", colorList.getColorForState(PRESSED_FOCUSED_SELECTED_STATE_SET, 0));
+ json.put("PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0));
+ json.put("PRESSED_ENABLED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_STATE_SET, 0));
+ json.put("PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET, 0));
+ json.put("PRESSED_ENABLED_SELECTED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_SELECTED_STATE_SET, 0));
+ json.put("PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0));
+ json.put("PRESSED_ENABLED_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_FOCUSED_STATE_SET, 0));
+ json.put("PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET, 0));
+ json.put("PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET, 0));
+ json.put("PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0));
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+
+ return json;
+ }
+
+ final int [] DrawableStates ={android.R.attr.state_active, android.R.attr.state_checked
+ , android.R.attr.state_enabled, android.R.attr.state_focused
+ , android.R.attr.state_pressed, android.R.attr.state_selected
+ , android.R.attr.state_window_focused, 16908288, 16843597, 16843518};
+ final String[] DrawableStatesLabels = {"active", "checked", "enabled", "focused", "pressed", "selected", "window_focused", "background", "multiline", "activated"};
+ final String[] DisableDrawableStatesLabels = {"inactive", "unchecked", "disabled", "not_focused", "no_pressed", "unselected", "window_not_focused", "background", "multiline", "activated"};
+
+ String getFileName(String file, String[] states)
+ {
+ for (String state: states)
+ file+="__"+state;
+ return file;
+ }
+
+ String getStatesName(String[] states)
+ {
+ String statesName="";
+ for (String state: states)
+ {
+ if (statesName.length()>0)
+ statesName+="__";
+ statesName += state;
+ }
+ return statesName;
+ }
+
+ void addDrawableItemIfNotExists(JSONObject json, ArrayList<Integer> list, Drawable item, String[] states, String filename)
+ {
+ for (Integer it : list)
+ {
+ if (it.equals(item.hashCode()))
+ return;
+ }
+ list.add(item.hashCode());
+ try {
+ json.put(getStatesName(states), getDrawable(item, getFileName(filename, states)));
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+ void addSolution(String filename, JSONObject json, int c, Drawable drawable, ArrayList<Integer> drawableList, int u)
+ {
+ int pos=0;
+ int states[] = new int[c];
+ String [] statesText = new String[c];
+
+ for (int n= 0;u > 0;++n, u>>= 1)
+ if ((u & 1) > 0)
+ {
+ statesText[pos]=DrawableStatesLabels[n];
+ states[pos++]=DrawableStates[n];
+ }
+ drawable.setState(states);
+ addDrawableItemIfNotExists(json, drawableList, drawable.getCurrent(), statesText, filename);
+ }
+
+ int bitCount(int u)
+ {
+ int n;
+ for (n= 0;u > 0;++n, u&= (u - 1));
+ return n;
+ }
+
+ Object getStateListDrawable_old(Drawable drawable, String filename)
+ {
+ JSONObject json = new JSONObject();
+ ArrayList<Integer> drawableList= new ArrayList<Integer>();
+ drawable.setState(EMPTY_STATE_SET);
+ try {
+ json.put("empty", getDrawable(drawable.getCurrent(), filename));
+ drawableList.add(drawable.getCurrent().hashCode());
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ for (int c = 1;c<=DrawableStates.length;c++)
+ for (int u= 0;u < 1 << DrawableStates.length;u++)
+ if (bitCount(u) == c)
+ addSolution(filename, json, c, drawable, drawableList, u);
+ return json;
+ }
+
+ JSONObject getStatesList(int [] states) throws JSONException
+ {
+ JSONObject json = new JSONObject();
+ for (int s : states)
+ {
+ boolean found=false;
+ for (int d = 0;d<DrawableStates.length;d++)
+ {
+ if (s==DrawableStates[d])
+ {
+ json.put(DrawableStatesLabels[d], true);
+ found=true;
+ break;
+ }
+ else if (s==-DrawableStates[d])
+ {
+ json.put(DrawableStatesLabels[d], false);
+
+ found=true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ json.put("unhandled_state_"+s,s>0);
+ }
+ }
+ return json;
+ }
+
+ String getStatesName(int [] states)
+ {
+ String statesName="";
+ for (int s : states)
+ {
+ boolean found=false;
+ for (int d = 0;d<DrawableStates.length;d++)
+ {
+ if (s==DrawableStates[d])
+ {
+ if (statesName.length()>0)
+ statesName+="__";
+ statesName+=DrawableStatesLabels[d];
+ found=true;
+ break;
+ }
+ else if (s==-DrawableStates[d])
+ {
+ if (statesName.length()>0)
+ statesName+="__";
+ statesName+=DisableDrawableStatesLabels[d];
+ found=true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ if (statesName.length()>0)
+ statesName+=";";
+ statesName+=s;
+ }
+ }
+ if (statesName.length()>0)
+ return statesName;
+ return "empty";
+ }
+
+ private JSONObject getLayerDrawable(Object drawable, String filename)
+ {
+ JSONObject json = new JSONObject();
+ LayerDrawable layers = (LayerDrawable) drawable;
+ final int nr=layers.getNumberOfLayers();
+ try {
+ JSONArray array =new JSONArray();
+ for (int i = 0; i < nr; i++)
+ {
+ int id = layers.getId(i);
+ if (id == -1)
+ id = i;
+ JSONObject layerJsonObject=getDrawable(layers.getDrawable(i), filename+"__"+id);
+ layerJsonObject.put("id", id);
+ array.put(layerJsonObject);
+ }
+ json.put("type", "layer");
+ Rect padding = new Rect();
+ if (layers.getPadding(padding))
+ json.put("padding", getJsonRect(padding));
+ json.put("layers", array);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return json;
+ }
+
+ private JSONObject getStateListDrawable(Object drawable, String filename)
+ {
+ JSONObject json = new JSONObject();
+ try {
+ StateListDrawable stateList = (StateListDrawable) drawable;
+ final int numStates = (Integer) StateListDrawable.class.getMethod("getStateCount").invoke(stateList);
+ JSONArray array =new JSONArray();
+ for (int i = 0; i < numStates; i++)
+ {
+ JSONObject stateJson = new JSONObject();
+ final Drawable d = (Drawable) StateListDrawable.class.getMethod("getStateDrawable", Integer.TYPE).invoke(stateList, i);
+ final int [] states = (int[]) StateListDrawable.class.getMethod("getStateSet", Integer.TYPE).invoke(stateList, i);
+ stateJson.put("states", getStatesList(states));
+ stateJson.put("drawable", getDrawable(d, filename+"__"+getStatesName(states)));
+ array.put(stateJson);
+ }
+ json.put("type", "stateslist");
+ Rect padding = new Rect();
+ if (stateList.getPadding(padding))
+ json.put("padding", getJsonRect(padding));
+ json.put("stateslist", array);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return json;
+ }
+
+ private JSONObject getGradientDrawable(GradientDrawable drawable) {
+ JSONObject json = new JSONObject();
+ try {
+ json.put("type", "gradient");
+ Object obj=drawable.getConstantState();
+ Class<?> gradientStateClass=obj.getClass();
+ json.put("shape",gradientStateClass.getField("mShape").getInt(obj));
+ json.put("gradient",gradientStateClass.getField("mGradient").getInt(obj));
+ GradientDrawable.Orientation orientation=(Orientation) gradientStateClass.getField("mOrientation").get(obj);
+ json.put("orientation",orientation.name());
+ int [] intArray=(int[]) gradientStateClass.getField("mColors").get(obj);
+ json.put("colors",getJsonArray(intArray, 0, intArray.length));
+ json.put("positions",getJsonArray((float[]) gradientStateClass.getField("mPositions").get(obj)));
+ json.put("solidColor",gradientStateClass.getField("mSolidColor").getInt(obj));
+ json.put("strokeWidth",gradientStateClass.getField("mStrokeWidth").getInt(obj));
+ json.put("strokeColor",gradientStateClass.getField("mStrokeColor").getInt(obj));
+ json.put("strokeDashWidth",gradientStateClass.getField("mStrokeDashWidth").getFloat(obj));
+ json.put("strokeDashGap",gradientStateClass.getField("mStrokeDashGap").getFloat(obj));
+ json.put("radius",gradientStateClass.getField("mRadius").getFloat(obj));
+ float [] floatArray=(float[]) gradientStateClass.getField("mRadiusArray").get(obj);
+ if (floatArray!=null)
+ json.put("radiusArray",getJsonArray(floatArray));
+ Rect rc= (Rect) gradientStateClass.getField("mPadding").get(obj);
+ if (rc!=null)
+ json.put("padding",getJsonRect(rc));
+ json.put("width",gradientStateClass.getField("mWidth").getInt(obj));
+ json.put("height",gradientStateClass.getField("mHeight").getInt(obj));
+ json.put("innerRadiusRatio",gradientStateClass.getField("mInnerRadiusRatio").getFloat(obj));
+ json.put("thicknessRatio",gradientStateClass.getField("mThicknessRatio").getFloat(obj));
+ json.put("innerRadius",gradientStateClass.getField("mInnerRadius").getInt(obj));
+ json.put("thickness",gradientStateClass.getField("mThickness").getInt(obj));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return json;
+ }
+
+ private JSONObject getRotateDrawable(RotateDrawable drawable, String filename) {
+ JSONObject json = new JSONObject();
+ try {
+ json.put("type", "rotate");
+ Object obj = drawable.getConstantState();
+ Class<?> rotateStateClass = obj.getClass();
+ Field f = rotateStateClass.getDeclaredField("mDrawable");
+ f.setAccessible(true);
+ json.put("drawable", getDrawable(f.get(obj), filename));
+ f = rotateStateClass.getDeclaredField("mPivotX");
+ f.setAccessible(true);
+ json.put("pivotX", f.getFloat(obj));
+ f = rotateStateClass.getDeclaredField("mPivotXRel");
+ f.setAccessible(true);
+ json.put("pivotXRel", f.getBoolean(obj));
+ f = rotateStateClass.getDeclaredField("mPivotY");
+ f.setAccessible(true);
+ json.put("pivotY", f.getFloat(obj));
+ f = rotateStateClass.getDeclaredField("mPivotYRel");
+ f.setAccessible(true);
+ json.put("pivotYRel", f.getBoolean(obj));
+ f = rotateStateClass.getDeclaredField("mFromDegrees");
+ f.setAccessible(true);
+ json.put("fromDegrees", f.getFloat(obj));
+ f = rotateStateClass.getDeclaredField("mToDegrees");
+ f.setAccessible(true);
+ json.put("toDegrees", f.getFloat(obj));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return json;
+ }
+
+ private JSONObject getAnimationDrawable(AnimationDrawable drawable, String filename) {
+ JSONObject json = new JSONObject();
+ try {
+ json.put("type", "animation");
+ json.put("oneshot", drawable.isOneShot());
+ final int count = drawable.getNumberOfFrames();
+ JSONArray frames = new JSONArray();
+ for (int i = 0; i < count; ++i)
+ {
+ JSONObject frame = new JSONObject();
+ frame.put("duration", drawable.getDuration(i));
+ frame.put("drawable", getDrawable(drawable.getFrame(i), filename+"__"+i));
+ frames.put(frame);
+ }
+ json.put("frames", frames);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return json;
+ }
+
+ private JSONObject getJsonRect(Rect rect) throws JSONException
+ {
+ JSONObject jsonRect = new JSONObject();
+ jsonRect.put("left", rect.left);
+ jsonRect.put("top", rect.top);
+ jsonRect.put("right", rect.right);
+ jsonRect.put("bottom", rect.bottom);
+ return jsonRect;
+
+ }
+
+ private JSONArray getJsonArray(int[] array, int pos, int len)
+ {
+ JSONArray a = new JSONArray();
+ final int l = pos+len;
+ for (int i=pos; i<l;i++)
+ a.put(array[i]);
+ return a;
+ }
+
+ private JSONArray getJsonArray(float[] array) throws JSONException
+ {
+ JSONArray a = new JSONArray();
+ if (array != null)
+ for (float val: array)
+ a.put(val);
+ return a;
+ }
+
+ private JSONObject getJsonChunkInfo(int[] chunkData) throws JSONException
+ {
+ JSONObject jsonRect = new JSONObject();
+ jsonRect.put("xdivs", getJsonArray(chunkData, 3, chunkData[0]));
+ jsonRect.put("ydivs", getJsonArray(chunkData, 3 + chunkData[0], chunkData[1]));
+ jsonRect.put("colors", getJsonArray(chunkData, 3 + chunkData[0] + chunkData[1], chunkData[2]));
+ return jsonRect;
+ }
+
+ private JSONObject findPatchesMarings(Drawable d) throws JSONException, NoSuchFieldException, IllegalAccessException
+ {
+ Field mNinePatch = ((NinePatchDrawable)d).getClass().getDeclaredField("mNinePatch");
+ mNinePatch.setAccessible(true);
+ NinePatch np = (NinePatch) mNinePatch.get(d);
+ if (Build.VERSION.SDK_INT < 19)
+ {
+ Field mChunk = np.getClass().getDeclaredField("mChunk");
+ mChunk.setAccessible(true);
+ return getJsonChunkInfo(extractChunkInfo((byte[]) mChunk.get(np)));
+ }
+ else
+ {
+ Field mNativeChunk = np.getClass().getDeclaredField("mNativeChunk");
+ mNativeChunk.setAccessible(true);
+ return getJsonChunkInfo(extractNativeChunkInfo(mNativeChunk.getInt(np)));
+ }
+ }
+
+ public JSONObject getDrawable(Object drawable, String filename)
+ {
+ JSONObject json = new JSONObject();
+ Bitmap bmp;
+ if (drawable instanceof Bitmap)
+ bmp = (Bitmap) drawable;
+ else
+ {
+ if (drawable instanceof BitmapDrawable)
+ bmp = ((BitmapDrawable)drawable).getBitmap();
+ else
+ {
+ if (drawable instanceof ScaleDrawable)
+ {
+ return getDrawable(((ScaleDrawable)drawable).getDrawable(), filename);
+ }
+ if (drawable instanceof LayerDrawable)
+ {
+ return getLayerDrawable(drawable, filename);
+ }
+ if (drawable instanceof StateListDrawable)
+ {
+ return getStateListDrawable(drawable, filename);
+ }
+ if (drawable instanceof GradientDrawable)
+ {
+ return getGradientDrawable((GradientDrawable) drawable);
+ }
+ if (drawable instanceof RotateDrawable)
+ {
+ return getRotateDrawable((RotateDrawable) drawable, filename);
+ }
+ if (drawable instanceof AnimationDrawable)
+ {
+ return getAnimationDrawable((AnimationDrawable) drawable, filename);
+ }
+ if (drawable instanceof ClipDrawable)
+ {
+ try {
+ json.put("type", "clipDrawable");
+ Drawable.ConstantState dcs = ((ClipDrawable)drawable).getConstantState();
+ Field f = dcs.getClass().getDeclaredField("mDrawable");
+ f.setAccessible(true);
+ json.put("drawable", getDrawable(f.get(dcs), filename));
+ Rect padding = new Rect();
+ if (((Drawable) drawable).getPadding(padding))
+ json.put("padding", getJsonRect(padding));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return json;
+ }
+ if (drawable instanceof ColorDrawable)
+ {
+ bmp = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
+ Drawable d = (Drawable) drawable;
+ d.setBounds(0, 0, 1, 1);
+ d.draw(new Canvas(bmp));
+ Rect padding = new Rect();
+ try {
+ json.put("type", "color");
+ json.put("color", bmp.getPixel(0, 0));
+ if (d.getPadding(padding))
+ json.put("padding", getJsonRect(padding));
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return json;
+ }
+ else
+ {
+ Drawable d = (Drawable) drawable;
+ int w=d.getIntrinsicWidth();
+ int h=d.getIntrinsicHeight();
+ d.setLevel(10000);
+ if (w<1 || h< 1)
+ {
+ w=100;
+ h=100;
+ }
+ bmp = Bitmap.createBitmap(w, h, Config.ARGB_8888);
+ d.setBounds(0, 0, w, h);
+ d.draw(new Canvas(bmp));
+ if (drawable instanceof NinePatchDrawable)
+ {
+ NinePatchDrawable npd = (NinePatchDrawable) drawable;
+ try {
+ json.put("type", "9patch");
+ json.put("drawable", getDrawable(bmp, filename));
+ Rect padding = new Rect();
+ if (npd.getPadding(padding))
+ json.put("padding", getJsonRect(padding));
+ json.put("chunkInfo", findPatchesMarings(d));
+ return json;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+ FileOutputStream out;
+ try {
+ filename = m_extractPath+filename+".png";
+ out = new FileOutputStream(filename);
+ bmp.compress(Bitmap.CompressFormat.PNG, 100, out);
+ out.close();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ try {
+ json.put("type", "image");
+ json.put("path", filename);
+ json.put("width", bmp.getWidth());
+ json.put("height", bmp.getHeight());
+// MinistroActivity.nativeChmode(filename, 0644);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return json;
+ }
+
+ public void extractViewInformations(String styleName, int styleId, JSONObject json, String qtClassName, AttributeSet attribSet)
+ {
+ try {
+ int[] viewAttrs;
+ viewAttrs = (int[]) styleableClass.getDeclaredField("View").get(null);
+ TypedArray a =m_theme.obtainStyledAttributes(attribSet, viewAttrs, styleId, 0);
+
+ if (null != qtClassName)
+ json.put("qtClass", qtClassName);
+ json.put("defaultBackgroundColor", defaultBackgroundColor);
+ json.put("defaultTextColorPrimary", defaultTextColor);
+ final int N = a.getIndexCount();
+ for (int i = 0; i < N; i++) {
+ int attr = a.getIndex(i);
+ if (attr == View_background)
+ json.put("View_background", getDrawable(a.getDrawable(attr), styleName + "_View_background"));
+ else if (attr == View_padding)
+ json.put("View_padding", a.getDimensionPixelSize(attr, -1));
+ else if (attr == View_paddingLeft)
+ json.put("View_paddingLeft", a.getDimensionPixelSize(attr, -1));
+ else if (attr == View_paddingTop)
+ json.put("View_paddingTop", a.getDimensionPixelSize(attr, -1));
+ else if (attr == View_paddingRight)
+ json.put("View_paddingRight", a.getDimensionPixelSize(attr, -1));
+ else if (attr == View_paddingBottom)
+ json.put("View_paddingBottom", a.getDimensionPixelSize(attr, -1));
+ else if (attr == View_scrollX)
+ json.put("View_paddingBottom", a.getDimensionPixelOffset(attr, 0));
+ else if (attr == View_scrollY)
+ json.put("View_scrollY", a.getDimensionPixelOffset(attr, 0));
+ else if (attr == View_id)
+ json.put("View_id", a.getResourceId(attr, -1));
+ else if (attr == View_tag)
+ json.put("View_tag", a.getText(attr));
+ else if (attr == View_fitsSystemWindows)
+ json.put("View_fitsSystemWindows", a.getBoolean(attr, false));
+ else if (attr == View_focusable)
+ json.put("View_focusable", a.getBoolean(attr, false));
+ else if (attr == View_focusableInTouchMode)
+ json.put("View_focusableInTouchMode", a.getBoolean(attr, false));
+ else if (attr == View_clickable)
+ json.put("View_clickable", a.getBoolean(attr, false));
+ else if (attr == View_longClickable)
+ json.put("View_longClickable", a.getBoolean(attr, false));
+ else if (attr == View_saveEnabled)
+ json.put("View_saveEnabled", a.getBoolean(attr, true));
+ else if (attr == View_duplicateParentState)
+ json.put("View_duplicateParentState", a.getBoolean(attr, false));
+ else if (attr == View_visibility)
+ json.put("View_visibility", a.getInt(attr, 0));
+ else if (attr == View_drawingCacheQuality)
+ json.put("View_drawingCacheQuality", a.getInt(attr, 0));
+ else if (attr == View_drawingCacheQuality)
+ json.put("View_contentDescription", a.getString(attr));
+ else if (attr == View_soundEffectsEnabled)
+ json.put("View_soundEffectsEnabled", a.getBoolean(attr, true));
+ else if (attr == View_hapticFeedbackEnabled)
+ json.put("View_hapticFeedbackEnabled", a.getBoolean(attr, true));
+ else if (attr == View_scrollbars)
+ json.put("View_scrollbars", a.getInt(attr, 0));
+ else if (attr == View_fadingEdge)
+ json.put("View_fadingEdge", a.getInt(attr, 0));
+ else if (attr == View_scrollbarStyle)
+ json.put("View_scrollbarStyle", a.getInt(attr, 0));
+ else if (attr == View_scrollbarFadeDuration)
+ json.put("View_scrollbarFadeDuration", a.getInt(attr, 0));
+ else if (attr == View_scrollbarDefaultDelayBeforeFade)
+ json.put("View_scrollbarDefaultDelayBeforeFade", a.getInt(attr, 0));
+ else if (attr == View_scrollbarSize)
+ json.put("View_scrollbarSize", a.getDimensionPixelSize(attr, -1));
+ else if (attr == View_scrollbarThumbHorizontal)
+ json.put("View_scrollbarThumbHorizontal", getDrawable(a.getDrawable(attr), styleName + "_View_scrollbarThumbHorizontal"));
+ else if (attr == View_scrollbarThumbVertical)
+ json.put("View_scrollbarThumbVertical", getDrawable(a.getDrawable(attr), styleName + "_View_scrollbarThumbVertical"));
+ else if (attr == View_scrollbarTrackHorizontal)
+ json.put("View_scrollbarTrackHorizontal", getDrawable(a.getDrawable(attr), styleName + "_View_scrollbarTrackHorizontal"));
+ else if (attr == View_scrollbarTrackVertical)
+ json.put("View_scrollbarTrackVertical", getDrawable(a.getDrawable(attr), styleName + "_View_scrollbarTrackVertical"));
+ else if (attr == View_isScrollContainer)
+ json.put("View_isScrollContainer", a.getBoolean(attr, false));
+ else if (attr == View_keepScreenOn)
+ json.put("View_keepScreenOn", a.getBoolean(attr, false));
+ else if (attr == View_filterTouchesWhenObscured)
+ json.put("View_filterTouchesWhenObscured", a.getBoolean(attr, false));
+ else if (attr == View_nextFocusLeft)
+ json.put("View_nextFocusLeft", a.getResourceId(attr, -1));
+ else if (attr == View_nextFocusRight)
+ json.put("View_nextFocusRight", a.getResourceId(attr, -1));
+ else if (attr == View_nextFocusUp)
+ json.put("View_nextFocusUp", a.getResourceId(attr, -1));
+ else if (attr == View_nextFocusDown)
+ json.put("View_nextFocusDown", a.getResourceId(attr, -1));
+ else if (attr == View_minWidth)
+ json.put("View_minWidth", a.getDimensionPixelSize(attr, 0));
+ else if (attr == View_minHeight)
+ json.put("View_minHeight", a.getDimensionPixelSize(attr, 0));
+ else if (attr == View_onClick)
+ json.put("View_onClick", a.getString(attr));
+ else if (attr == View_overScrollMode)
+ json.put("View_overScrollMode", a.getInt(attr, 1));
+ else if (attr == View_paddingStart)
+ json.put("View_paddingStart", a.getDimensionPixelSize(attr, 0));
+ else if (attr == View_paddingEnd)
+ json.put("View_paddingEnd", a.getDimensionPixelSize(attr, 0));
+ }
+ a.recycle();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public JSONObject extractTextAppearance(int styleId)
+ {
+ JSONObject json = new JSONObject();
+ try
+ {
+ TypedArray a = m_theme.obtainStyledAttributes(styleId, (int[]) styleableClass.getDeclaredField("TextAppearance").get(null));
+ int n = a.getIndexCount();
+ for (int i = 0; i < n; i++)
+ {
+ int attr = a.getIndex(i);
+ if (attr == TextAppearance_textColorHighlight)
+ json.put("TextAppearance_textColorHighlight", a.getColor(attr, 0));
+ else if (attr == TextAppearance_textColor)
+ json.put("TextAppearance_textColor", getColorStateList(a.getColorStateList(attr)));
+ else if (attr == TextAppearance_textColorHint)
+ json.put("TextAppearance_textColorHint", getColorStateList(a.getColorStateList(attr)));
+ else if (attr == TextAppearance_textColorLink)
+ json.put("TextAppearance_textColorLink", getColorStateList(a.getColorStateList(attr)));
+ else if (attr == TextAppearance_textSize)
+ json.put("TextAppearance_textSize", a.getDimensionPixelSize(attr, 15));
+ else if (attr == TextAppearance_typeface)
+ json.put("TextAppearance_typeface", a.getInt(attr, -1));
+ else if (attr == TextAppearance_textStyle)
+ json.put("TextAppearance_textStyle", a.getInt(attr, -1));
+ else if (attr == TextAppearance_textAllCaps)
+ json.put("TextAppearance_textAllCaps", a.getBoolean(attr, false));
+ }
+ a.recycle();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return json;
+ }
+
+ public JSONObject extractTextAppearanceInformations(String styleName, String qtClass, AttributeSet attribSet, int textAppearance)
+ {
+ JSONObject json = new JSONObject();
+ try
+ {
+ int textColorHighlight = 0; //
+ ColorStateList textColor = null; //
+ ColorStateList textColorHint = null; //
+ ColorStateList textColorLink = null; //
+ int textSize = 15; //
+ int typefaceIndex = -1; //
+ int styleIndex = -1;
+ boolean allCaps = false;
+
+ Class<?> attrClass= Class.forName("android.R$attr");
+ int styleId = attrClass.getDeclaredField(styleName).getInt(null);
+
+ extractViewInformations(styleName, styleId, json, qtClass, attribSet);
+
+ int[] textViewAttrs=(int[]) styleableClass.getDeclaredField("TextView").get(null);
+ TypedArray a =m_theme.obtainStyledAttributes(null, textViewAttrs, styleId, 0);
+
+ TypedArray appearance = null;
+ if (-1==textAppearance)
+ textAppearance = a.getResourceId(styleableClass.getDeclaredField("TextView_textAppearance").getInt(null), -1);
+
+ if (textAppearance != -1)
+ appearance = m_theme.obtainStyledAttributes(textAppearance, (int[]) styleableClass.getDeclaredField("TextAppearance").get(null));
+
+ if (appearance != null)
+ {
+ int n = appearance.getIndexCount();
+ for (int i = 0; i < n; i++)
+ {
+ int attr = appearance.getIndex(i);
+ if (attr == TextAppearance_textColorHighlight)
+ textColorHighlight = appearance.getColor(attr, textColorHighlight);
+ else if (attr == TextAppearance_textColor)
+ textColor = appearance.getColorStateList(attr);
+ else if (attr == TextAppearance_textColorHint)
+ textColorHint = appearance.getColorStateList(attr);
+ else if (attr == TextAppearance_textColorLink)
+ textColorLink = appearance.getColorStateList(attr);
+ else if (attr == TextAppearance_textSize)
+ textSize = appearance.getDimensionPixelSize(attr, textSize);
+ else if (attr == TextAppearance_typeface)
+ typefaceIndex = appearance.getInt(attr, -1);
+ else if (attr == TextAppearance_textStyle)
+ styleIndex = appearance.getInt(attr, -1);
+ else if (attr == TextAppearance_textAllCaps)
+ allCaps = appearance.getBoolean(attr, false);
+ }
+ appearance.recycle();
+ }
+
+ int n = a.getIndexCount();
+
+ for (int i = 0; i < n; i++) {
+ int attr = a.getIndex(i);
+
+ if (attr == TextView_editable)
+ json.put("TextView_editable", a.getBoolean(attr, false));
+ else if (attr == TextView_inputMethod)
+ json.put("TextView_inputMethod", a.getText(attr));
+ else if (attr == TextView_numeric)
+ json.put("TextView_numeric", a.getInt(attr, 0));
+ else if (attr == TextView_digits)
+ json.put("TextView_digits", a.getText(attr));
+ else if (attr == TextView_phoneNumber)
+ json.put("TextView_phoneNumber", a.getBoolean(attr, false));
+ else if (attr == TextView_autoText)
+ json.put("TextView_autoText", a.getBoolean(attr, false));
+ else if (attr == TextView_capitalize)
+ json.put("TextView_capitalize", a.getInt(attr, -1));
+ else if (attr == TextView_bufferType)
+ json.put("TextView_bufferType", a.getInt(attr, 0));
+ else if (attr == TextView_selectAllOnFocus)
+ json.put("TextView_selectAllOnFocus", a.getBoolean(attr, false));
+ else if (attr == TextView_autoLink)
+ json.put("TextView_autoLink", a.getInt(attr, 0));
+ else if (attr == TextView_linksClickable)
+ json.put("TextView_linksClickable", a.getBoolean(attr, true));
+ else if (attr == TextView_linksClickable)
+ json.put("TextView_linksClickable", a.getBoolean(attr, true));
+ else if (attr == TextView_drawableLeft)
+ json.put("TextView_drawableLeft", getDrawable(a.getDrawable(attr), styleName + "_TextView_drawableLeft"));
+ else if (attr == TextView_drawableTop)
+ json.put("TextView_drawableTop", getDrawable(a.getDrawable(attr), styleName + "_TextView_drawableTop"));
+ else if (attr == TextView_drawableRight)
+ json.put("TextView_drawableRight", getDrawable(a.getDrawable(attr), styleName + "_TextView_drawableRight"));
+ else if (attr == TextView_drawableBottom)
+ json.put("TextView_drawableBottom", getDrawable(a.getDrawable(attr), styleName + "_TextView_drawableBottom"));
+ else if (attr == TextView_drawableStart)
+ json.put("TextView_drawableStart", getDrawable(a.getDrawable(attr), styleName + "_TextView_drawableStart"));
+ else if (attr == TextView_drawableEnd)
+ json.put("TextView_drawableEnd", getDrawable(a.getDrawable(attr), styleName + "_TextView_drawableEnd"));
+ else if (attr == TextView_drawablePadding)
+ json.put("TextView_drawablePadding", a.getDimensionPixelSize(attr, 0));
+ else if (attr == TextView_textCursorDrawable)
+ json.put("TextView_textCursorDrawable", getDrawable(m_context.getResources().getDrawable(a.getResourceId(attr, 0)), styleName + "_TextView_textCursorDrawable"));
+ else if (attr == TextView_maxLines)
+ json.put("TextView_maxLines", a.getInt(attr, -1));
+ else if (attr == TextView_maxHeight)
+ json.put("TextView_maxHeight", a.getDimensionPixelSize(attr, -1));
+ else if (attr == TextView_lines)
+ json.put("TextView_lines", a.getInt(attr, -1));
+ else if (attr == TextView_height)
+ json.put("TextView_height", a.getDimensionPixelSize(attr, -1));
+ else if (attr == TextView_minLines)
+ json.put("TextView_minLines", a.getInt(attr, -1));
+ else if (attr == TextView_minHeight)
+ json.put("TextView_minHeight", a.getDimensionPixelSize(attr, -1));
+ else if (attr == TextView_maxEms)
+ json.put("TextView_maxEms", a.getInt(attr, -1));
+ else if (attr == TextView_maxWidth)
+ json.put("TextView_maxWidth", a.getDimensionPixelSize(attr, -1));
+ else if (attr == TextView_ems)
+ json.put("TextView_ems", a.getInt(attr, -1));
+ else if (attr == TextView_width)
+ json.put("TextView_width", a.getDimensionPixelSize(attr, -1));
+ else if (attr == TextView_minEms)
+ json.put("TextView_minEms", a.getInt(attr, -1));
+ else if (attr == TextView_minWidth)
+ json.put("TextView_minWidth", a.getDimensionPixelSize(attr, -1));
+ else if (attr == TextView_gravity)
+ json.put("TextView_gravity", a.getInt(attr, -1));
+ else if (attr == TextView_hint)
+ json.put("TextView_hint", a.getText(attr));
+ else if (attr == TextView_text)
+ json.put("TextView_text", a.getText(attr));
+ else if (attr == TextView_scrollHorizontally)
+ json.put("TextView_scrollHorizontally", a.getBoolean(attr, false));
+ else if (attr == TextView_singleLine)
+ json.put("TextView_singleLine", a.getBoolean(attr, false));
+ else if (attr == TextView_ellipsize)
+ json.put("TextView_ellipsize", a.getInt(attr, -1));
+ else if (attr == TextView_marqueeRepeatLimit)
+ json.put("TextView_marqueeRepeatLimit", a.getInt(attr, 3));
+ else if (attr == TextView_includeFontPadding)
+ json.put("TextView_includeFontPadding", a.getBoolean(attr, true));
+ else if (attr == TextView_cursorVisible)
+ json.put("TextView_cursorVisible", a.getBoolean(attr, true));
+ else if (attr == TextView_maxLength)
+ json.put("TextView_maxLength", a.getInt(attr, -1));
+ else if (attr == TextView_textScaleX)
+ json.put("TextView_textScaleX", a.getFloat(attr, 1.0f));
+ else if (attr == TextView_freezesText)
+ json.put("TextView_freezesText", a.getBoolean(attr, false));
+ else if (attr == TextView_shadowColor)
+ json.put("TextView_shadowColor", a.getInt(attr, 0));
+ else if (attr == TextView_shadowDx)
+ json.put("TextView_shadowDx", a.getFloat(attr, 0));
+ else if (attr == TextView_shadowDy)
+ json.put("TextView_shadowDy", a.getFloat(attr, 0));
+ else if (attr == TextView_shadowRadius)
+ json.put("TextView_shadowRadius", a.getFloat(attr, 0));
+ else if (attr == TextView_enabled)
+ json.put("TextView_enabled", a.getBoolean(attr,true));
+ else if (attr == TextView_textColorHighlight)
+ textColorHighlight = a.getColor(attr, textColorHighlight);
+ else if (attr == TextView_textColor)
+ textColor = a.getColorStateList(attr);
+ else if (attr == TextView_textColorHint)
+ textColorHint = a.getColorStateList(attr);
+ else if (attr == TextView_textColorLink)
+ textColorLink = a.getColorStateList(attr);
+ else if (attr == TextView_textSize)
+ textSize = a.getDimensionPixelSize(attr, textSize);
+ else if (attr == TextView_typeface)
+ typefaceIndex = a.getInt(attr, typefaceIndex);
+ else if (attr == TextView_textStyle)
+ styleIndex = a.getInt(attr, styleIndex);
+ else if (attr == TextView_password)
+ json.put("TextView_password", a.getBoolean(attr,false));
+ else if (attr == TextView_lineSpacingExtra)
+ json.put("TextView_lineSpacingExtra", a.getDimensionPixelSize(attr, 0));
+ else if (attr == TextView_lineSpacingMultiplier)
+ json.put("TextView_lineSpacingMultiplier", a.getFloat(attr, 1.0f));
+ else if (attr == TextView_inputType)
+ json.put("TextView_inputType", a.getInt(attr, EditorInfo.TYPE_NULL));
+ else if (attr == TextView_imeOptions)
+ json.put("TextView_imeOptions", a.getInt(attr, EditorInfo.IME_NULL));
+ else if (attr == TextView_imeActionLabel)
+ json.put("TextView_imeActionLabel", a.getText(attr));
+ else if (attr == TextView_imeActionId)
+ json.put("TextView_imeActionId", a.getInt(attr,0));
+ else if (attr == TextView_privateImeOptions)
+ json.put("TextView_privateImeOptions", a.getString(attr));
+ else if (attr == TextView_textSelectHandleLeft && styleName.equals("textViewStyle"))
+ json.put("TextView_textSelectHandleLeft", getDrawable(m_context.getResources().getDrawable(a.getResourceId(attr, 0)), styleName + "_TextView_textSelectHandleLeft"));
+ else if (attr == TextView_textSelectHandleRight && styleName.equals("textViewStyle"))
+ json.put("TextView_textSelectHandleRight", getDrawable(m_context.getResources().getDrawable(a.getResourceId(attr, 0)), styleName + "_TextView_textSelectHandleRight"));
+ else if (attr == TextView_textSelectHandle && styleName.equals("textViewStyle"))
+ json.put("TextView_textSelectHandle", getDrawable(m_context.getResources().getDrawable(a.getResourceId(attr, 0)), styleName + "_TextView_textSelectHandle"));
+ else if (attr == TextView_textIsSelectable)
+ json.put("TextView_textIsSelectable", a.getBoolean(attr, false));
+ else if (attr == TextView_textAllCaps)
+ allCaps = a.getBoolean(attr, false);
+ }
+ a.recycle();
+
+ json.put("TextAppearance_textColorHighlight",textColorHighlight);
+ json.put("TextAppearance_textColor", getColorStateList(textColor));
+ json.put("TextAppearance_textColorHint", getColorStateList(textColorHint));
+ json.put("TextAppearance_textColorLink", getColorStateList(textColorLink));
+ json.put("TextAppearance_textSize",textSize);
+ json.put("TextAppearance_typeface",typefaceIndex);
+ json.put("TextAppearance_textStyle",styleIndex);
+ json.put("TextAppearance_textAllCaps",allCaps);
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ }
+ return json;
+ }
+
+ final String[] sScaleTypeArray = {
+ "MATRIX",
+ "FIT_XY",
+ "FIT_START",
+ "FIT_CENTER",
+ "FIT_END",
+ "CENTER",
+ "CENTER_CROP",
+ "CENTER_INSIDE"
+ };
+
+ public JSONObject extractImageViewInformations(String styleName, String qtClassName )
+ {
+ JSONObject json = new JSONObject();
+ try
+ {
+ Class<?> attrClass= Class.forName("android.R$attr");
+ int styleId = attrClass.getDeclaredField(styleName).getInt(null);
+
+ extractViewInformations(styleName, styleId, json, qtClassName, null);
+
+ int[] imageViewAttrs=(int[]) styleableClass.getDeclaredField("ImageView").get(null);
+ TypedArray a =m_theme.obtainStyledAttributes(null, imageViewAttrs, styleId, 0);
+ Drawable d = a.getDrawable(ImageView_src);
+ if (d != null)
+ json.put("ImageView_src", getDrawable(d, styleName + "_ImageView_src"));
+
+ json.put("ImageView_baselineAlignBottom", a.getBoolean(ImageView_baselineAlignBottom, false));
+ json.put("ImageView_adjustViewBounds", a.getBoolean(ImageView_adjustViewBounds, false));
+ json.put("ImageView_maxWidth", a.getDimensionPixelSize(ImageView_maxWidth, Integer.MAX_VALUE));
+ json.put("ImageView_maxHeight", a.getDimensionPixelSize(ImageView_maxHeight, Integer.MAX_VALUE));
+ int index = a.getInt(ImageView_scaleType, -1);
+ if (index >= 0)
+ json.put("ImageView_scaleType", sScaleTypeArray[index]);
+
+ int tint = a.getInt(ImageView_tint, 0);
+ if (tint != 0)
+ json.put("ImageView_tint", tint);
+
+
+ json.put("ImageView_cropToPadding",a.getBoolean(ImageView_cropToPadding, false));
+ a.recycle();
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ }
+ return json;
+
+ }
+
+ void extractCompoundButton(SimpleJsonWriter jsonWriter, String styleName, String qtClass)
+ {
+ JSONObject json = extractTextAppearanceInformations(styleName, qtClass, null, -1);
+ Class<?> attrClass;
+ try {
+ attrClass = Class.forName("android.R$attr");
+ int styleId = attrClass.getDeclaredField(styleName).getInt(null);
+ int[] compoundButtonAttrs=(int[]) styleableClass.getDeclaredField("CompoundButton").get(null);
+
+ TypedArray a = m_theme.obtainStyledAttributes(
+ null, compoundButtonAttrs, styleId, 0);
+
+ Drawable d = a.getDrawable(getField(styleableClass,"CompoundButton_button"));
+ if (d != null)
+ json.put("CompoundButton_button", getDrawable(d, styleName + "_CompoundButton_button"));
+
+ a.recycle();
+ jsonWriter.name(styleName).value(json);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ void extractProgressBarInfo(JSONObject json, String styleName)
+ {
+ Class<?> attrClass;
+ try {
+ attrClass = Class.forName("android.R$attr");
+ int styleId = attrClass.getDeclaredField(styleName).getInt(null);
+ int[] progressBarAttrs=(int[]) styleableClass.getDeclaredField("ProgressBar").get(null);
+
+ TypedArray a = m_theme.obtainStyledAttributes(null, progressBarAttrs, styleId, 0);
+ int mMinWidth = 24;
+ int mMaxWidth = 48;
+ int mMinHeight = 24;
+ int mMaxHeight = 48;
+ mMinWidth = a.getDimensionPixelSize(getField(styleableClass, "ProgressBar_minWidth"), mMinWidth);
+ mMaxWidth = a.getDimensionPixelSize(getField(styleableClass, "ProgressBar_maxWidth"), mMaxWidth);
+ mMinHeight = a.getDimensionPixelSize(getField(styleableClass, "ProgressBar_minHeight"), mMinHeight);
+ mMaxHeight = a.getDimensionPixelSize(getField(styleableClass, "ProgressBar_maxHeight"), mMaxHeight);
+
+ json.put("ProgressBar_indeterminateDuration", a.getInt(getField(styleableClass, "ProgressBar_indeterminateDuration"), 4000));
+ json.put("ProgressBar_minWidth", mMinWidth);
+ json.put("ProgressBar_maxWidth", mMaxWidth);
+ json.put("ProgressBar_minHeight", mMinHeight);
+ json.put("ProgressBar_maxHeight", mMaxHeight);
+ json.put("ProgressBar_progress_id", android.R.id.progress);
+ json.put("ProgressBar_secondaryProgress_id", android.R.id.secondaryProgress);
+
+ Drawable d = a.getDrawable(getField(styleableClass,"ProgressBar_progressDrawable"));
+ if (d != null)
+ json.put("ProgressBar_progressDrawable", getDrawable(d, styleName + "_ProgressBar_progressDrawable"));
+
+ d = a.getDrawable(getField(styleableClass,"ProgressBar_indeterminateDrawable"));
+ if (d != null)
+ json.put("ProgressBar_indeterminateDrawable", getDrawable(d, styleName + "_ProgressBar_indeterminateDrawable"));
+
+ a.recycle();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ void extractProgressBar(SimpleJsonWriter writer, String styleName, String qtClass)
+ {
+ JSONObject json = extractTextAppearanceInformations(styleName, qtClass, null, -1);
+ try {
+ extractProgressBarInfo(json, styleName);
+ writer.name(styleName).value(json);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ void extractAbsSeekBar(SimpleJsonWriter jsonWriter, String styleName, String qtClass)
+ {
+ JSONObject json = extractTextAppearanceInformations(styleName, qtClass, null, -1);
+ extractProgressBarInfo(json, styleName);
+ Class<?> attrClass;
+ try {
+ attrClass = Class.forName("android.R$attr");
+ int styleId = attrClass.getDeclaredField(styleName).getInt(null);
+ int[] compoundButtonAttrs=(int[]) styleableClass.getDeclaredField("SeekBar").get(null);
+
+ TypedArray a = m_theme.obtainStyledAttributes(
+ null, compoundButtonAttrs, styleId, 0);
+
+ Drawable d = a.getDrawable(getField(styleableClass,"SeekBar_thumb"));
+ if (d != null)
+ json.put("SeekBar_thumb", getDrawable(d, styleName + "_SeekBar_thumb"));
+
+ try {
+ json.put("SeekBar_thumbOffset", styleableClass.getDeclaredField("SeekBar_thumbOffset").getInt(null));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ a.recycle();
+ jsonWriter.name(styleName).value(json);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ void extractSwitch(SimpleJsonWriter jsonWriter, String styleName, String qtClass)
+ {
+ JSONObject json = new JSONObject();
+ try {
+ Class<?> attrClass = Class.forName("com.android.internal.R$attr");
+ int styleId = attrClass.getDeclaredField(styleName).getInt(null);
+
+ int[] switchAttrs = (int[]) styleableClass.getDeclaredField("Switch").get(null);
+ TypedArray a = m_theme.obtainStyledAttributes(null, switchAttrs, styleId, 0);
+
+ Drawable thumb = a.getDrawable(getField(styleableClass,"Switch_thumb"));
+ if (thumb != null)
+ json.put("Switch_thumb", getDrawable(thumb, styleName + "_Switch_thumb"));
+
+ Drawable track = a.getDrawable(getField(styleableClass,"Switch_track"));
+ if (track != null)
+ json.put("Switch_track", getDrawable(track, styleName + "_Switch_track"));
+
+ int textAppearance = a.getResourceId(styleableClass.getDeclaredField("Switch_switchTextAppearance").getInt(null), -1);
+ json.put("Switch_switchTextAppearance", extractTextAppearance(textAppearance));
+
+ json.put("Switch_textOn", a.getText(getField(styleableClass, "Switch_textOn")));
+ json.put("Switch_textOff", a.getText(getField(styleableClass, "Switch_textOff")));
+ json.put("Switch_switchMinWidth", a.getDimensionPixelSize(getField(styleableClass, "Switch_switchMinWidth"), 0));
+ json.put("Switch_switchPadding", a.getDimensionPixelSize(getField(styleableClass, "Switch_switchPadding"), 0));
+ json.put("Switch_thumbTextPadding", a.getDimensionPixelSize(getField(styleableClass, "Switch_thumbTextPadding"), 0));
+
+ a.recycle();
+ jsonWriter.name(styleName).value(json);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ JSONObject extractCheckedTextView(AttributeSet attribSet, String itemName)
+ {
+ JSONObject json = extractTextAppearanceInformations("textViewStyle", itemName, attribSet, -1);
+ try {
+ Class<?> attrClass= Class.forName("android.R$attr");
+ int styleId = attrClass.getDeclaredField("textViewStyle").getInt(null);
+ int[] compoundButtonAttrs=(int[]) styleableClass.getDeclaredField("CheckedTextView").get(null);
+
+ TypedArray a = m_theme.obtainStyledAttributes(attribSet, compoundButtonAttrs, styleId, 0);
+
+ Drawable d = a.getDrawable(getField(styleableClass,"CheckedTextView_checkMark"));
+ if (d != null)
+ json.put("CheckedTextView_checkMark", getDrawable(d, itemName+"_CheckedTextView_checkMark"));
+
+ a.recycle();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return json;
+ }
+
+ private JSONObject extractItemStyle(int resourceId, String itemName, int textAppearance) {
+ try
+ {
+ XmlResourceParser parser = m_context.getResources().getLayout(resourceId);
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG &&
+ type != XmlPullParser.END_DOCUMENT) {
+ // Empty
+ }
+
+ if (type != XmlPullParser.START_TAG) {
+ return null;
+ }
+
+ AttributeSet attributes = Xml.asAttributeSet(parser);
+ String name = parser.getName();
+ if (name.equals("TextView"))
+ return extractTextAppearanceInformations("textViewStyle", itemName, attributes, textAppearance);
+ if (name.equals("CheckedTextView"))
+ return extractCheckedTextView(attributes, itemName);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ private void extractItemsStyle(SimpleJsonWriter jsonWriter) {
+ try
+ {
+ jsonWriter.name("simple_list_item").value(extractItemStyle(android.R.layout.simple_list_item_1, "simple_list_item", android.R.style.TextAppearance_Large));
+ jsonWriter.name("simple_list_item_checked").value(extractItemStyle(android.R.layout.simple_list_item_checked, "simple_list_item_checked", android.R.style.TextAppearance_Large));
+ jsonWriter.name("simple_list_item_multiple_choice").value(extractItemStyle(android.R.layout.simple_list_item_multiple_choice, "simple_list_item_multiple_choice", android.R.style.TextAppearance_Large));
+ jsonWriter.name("simple_list_item_single_choice").value(extractItemStyle(android.R.layout.simple_list_item_single_choice, "simple_list_item_single_choice", android.R.style.TextAppearance_Large));
+ jsonWriter.name("simple_spinner_item").value(extractItemStyle(android.R.layout.simple_spinner_item, "simple_spinner_item", -1));
+ jsonWriter.name("simple_spinner_dropdown_item").value(extractItemStyle(android.R.layout.simple_spinner_dropdown_item, "simple_spinner_dropdown_item",android.R.style.TextAppearance_Large));
+ jsonWriter.name("simple_dropdown_item_1line").value(extractItemStyle(android.R.layout.simple_dropdown_item_1line, "simple_dropdown_item_1line",android.R.style.TextAppearance_Large));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ void extractCalendar(SimpleJsonWriter writer, String styleName, String qtClass)
+ {
+ JSONObject json = extractTextAppearanceInformations(styleName, qtClass, null, -1);
+ try {
+ Class<?> attrClass = Class.forName("android.R$attr");
+ int styleId = attrClass.getDeclaredField(styleName).getInt(null);
+
+ int[] styleAttrs = (int[]) styleableClass.getDeclaredField("CalendarView").get(null);
+ TypedArray a = m_theme.obtainStyledAttributes(null, styleAttrs, styleId, 0);
+
+ Drawable d = a.getDrawable(getField(styleableClass,"CalendarView_selectedDateVerticalBar"));
+ if (d != null)
+ json.put("CalendarView_selectedDateVerticalBar", getDrawable(d, styleName + "_CalendarView_selectedDateVerticalBar"));
+
+ int dateTextAppearance = a.getResourceId(styleableClass.getDeclaredField("CalendarView_dateTextAppearance").getInt(null), -1);
+ json.put("CalendarView_dateTextAppearance", extractTextAppearance(dateTextAppearance));
+
+ int weekDayTextAppearance = a.getResourceId(styleableClass.getDeclaredField("CalendarView_weekDayTextAppearance").getInt(null), -1);
+ json.put("CalendarView_weekDayTextAppearance", extractTextAppearance(weekDayTextAppearance));
+
+ json.put("CalendarView_firstDayOfWeek", a.getInt(getField(styleableClass, "CalendarView_firstDayOfWeek"), 0));
+ json.put("CalendarView_focusedMonthDateColor", a.getColor(getField(styleableClass, "CalendarView_focusedMonthDateColor"), 0));
+ json.put("CalendarView_selectedWeekBackgroundColor", a.getColor(getField(styleableClass, "CalendarView_selectedWeekBackgroundColor"), 0));
+ json.put("CalendarView_showWeekNumber", a.getBoolean(getField(styleableClass, "CalendarView_showWeekNumber"), true));
+ json.put("CalendarView_shownWeekCount", a.getInt(getField(styleableClass, "CalendarView_shownWeekCount"), 6));
+ json.put("CalendarView_unfocusedMonthDateColor", a.getColor(getField(styleableClass, "CalendarView_unfocusedMonthDateColor"), 0));
+ json.put("CalendarView_weekNumberColor", a.getColor(getField(styleableClass, "CalendarView_weekNumberColor"), 0));
+ json.put("CalendarView_weekSeparatorLineColor", a.getColor(getField(styleableClass, "CalendarView_weekSeparatorLineColor"), 0));
+
+ a.recycle();
+ writer.name(styleName).value(json);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ void extractToolBar(SimpleJsonWriter writer, String styleName, String qtClass)
+ {
+ JSONObject json = extractTextAppearanceInformations(styleName, qtClass, null, -1);
+ try {
+ Class<?> attrClass = Class.forName("com.android.internal.R$attr");
+ int styleId = attrClass.getDeclaredField(styleName).getInt(null);
+
+ int[] styleAttrs = (int[]) styleableClass.getDeclaredField("ActionBar").get(null);
+ TypedArray a = m_theme.obtainStyledAttributes(null, styleAttrs, styleId, 0);
+
+ Drawable d = a.getDrawable(getField(styleableClass,"ActionBar_background"));
+ if (d != null)
+ json.put("ActionBar_background", getDrawable(d, styleName + "_ActionBar_background"));
+
+ d = a.getDrawable(getField(styleableClass,"ActionBar_backgroundStacked"));
+ if (d != null)
+ json.put("ActionBar_backgroundStacked", getDrawable(d, styleName + "_ActionBar_backgroundStacked"));
+
+ d = a.getDrawable(getField(styleableClass,"ActionBar_backgroundSplit"));
+ if (d != null)
+ json.put("ActionBar_backgroundSplit", getDrawable(d, styleName + "_ActionBar_backgroundSplit"));
+
+ d = a.getDrawable(getField(styleableClass,"ActionBar_divider"));
+ if (d != null)
+ json.put("ActionBar_divider", getDrawable(d, styleName + "_ActionBar_divider"));
+
+ json.put("ActionBar_itemPadding", a.getDimensionPixelSize(getField(styleableClass, "ActionBar_itemPadding"), 0));
+
+ a.recycle();
+ writer.name(styleName).value(json);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ void extractTabBar(SimpleJsonWriter writer, String styleName, String qtClass)
+ {
+ JSONObject json = extractTextAppearanceInformations(styleName, qtClass, null, -1);
+ try {
+ Class<?> attrClass = Class.forName("android.R$attr");
+ int styleId = attrClass.getDeclaredField(styleName).getInt(null);
+
+ int[] styleAttrs = (int[]) styleableClass.getDeclaredField("LinearLayout").get(null);
+ TypedArray a = m_theme.obtainStyledAttributes(null, styleAttrs, styleId, 0);
+
+ Drawable d = a.getDrawable(getField(styleableClass,"LinearLayout_divider"));
+ if (d != null)
+ json.put("LinearLayout_divider", getDrawable(d, styleName + "_LinearLayout_divider"));
+ json.put("LinearLayout_showDividers", a.getInt(getField(styleableClass, "LinearLayout_showDividers"), 0));
+ json.put("LinearLayout_dividerPadding", a.getDimensionPixelSize(getField(styleableClass, "LinearLayout_dividerPadding"), 0));
+
+ a.recycle();
+ writer.name(styleName).value(json);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public ExtractStyle(Context context, String extractPath)
+ {
+// Log.i(MinistroService.TAG, "Extract " + extractPath);
+ m_extractPath = extractPath + "/";
+ new File(m_extractPath).mkdirs();
+// MinistroActivity.nativeChmode(m_extractPath, 0755);
+ m_context = context;
+ m_theme = context.getTheme();
+ TypedArray array = m_theme.obtainStyledAttributes(new int[]{
+ android.R.attr.colorBackground,
+ android.R.attr.textColorPrimary,
+ });
+ defaultBackgroundColor = array.getColor(0, 0);
+ defaultTextColor = array.getColor(1, 0xFFFFFF);
+ array.recycle();
+
+ try
+ {
+ SimpleJsonWriter jsonWriter = new SimpleJsonWriter(m_extractPath+"style.json");
+ jsonWriter.beginObject();
+ try {
+ jsonWriter.name("buttonStyle").value(extractTextAppearanceInformations("buttonStyle", "QPushButton", null, -1));
+ jsonWriter.name("spinnerStyle").value(extractTextAppearanceInformations("spinnerStyle", "QComboBox", null, -1));
+ extractProgressBar(jsonWriter, "progressBarStyleHorizontal", "QProgressBar");
+ extractProgressBar(jsonWriter, "progressBarStyleLarge", null);
+ extractProgressBar(jsonWriter, "progressBarStyleSmall", null);
+ extractProgressBar(jsonWriter, "progressBarStyle", null);
+ extractAbsSeekBar(jsonWriter, "seekBarStyle", "QSlider");
+ if (Build.VERSION.SDK_INT > 13) {
+ extractSwitch(jsonWriter, "switchStyle", null);
+ }
+ extractCompoundButton(jsonWriter, "checkboxStyle", "QCheckBox");
+ jsonWriter.name("editTextStyle").value(extractTextAppearanceInformations("editTextStyle", "QLineEdit", null, -1));
+ extractCompoundButton(jsonWriter, "radioButtonStyle", "QRadioButton");
+ jsonWriter.name("textViewStyle").value(extractTextAppearanceInformations("textViewStyle", "QWidget", null, -1));
+ jsonWriter.name("scrollViewStyle").value(extractTextAppearanceInformations("scrollViewStyle", "QAbstractScrollArea", null, -1));
+ extractItemsStyle(jsonWriter);
+ extractCompoundButton(jsonWriter, "buttonStyleToggle", null);
+ if (Build.VERSION.SDK_INT > 10) {
+ extractCalendar(jsonWriter, "calendarViewStyle", "QCalendarWidget");
+ extractToolBar(jsonWriter, "actionBarStyle", "QToolBar");
+ jsonWriter.name("actionButtonStyle").value(extractTextAppearanceInformations("actionButtonStyle", "QToolButton", null, -1));
+ jsonWriter.name("actionBarTabTextStyle").value(extractTextAppearanceInformations("actionBarTabTextStyle", null, null, -1));
+ jsonWriter.name("actionBarTabStyle").value(extractTextAppearanceInformations("actionBarTabStyle", null, null, -1));
+ jsonWriter.name("actionOverflowButtonStyle").value(extractImageViewInformations("actionOverflowButtonStyle", null));
+ extractTabBar(jsonWriter, "actionBarTabBarStyle", "QTabBar");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ jsonWriter.endObject();
+ jsonWriter.close();
+// MinistroActivity.nativeChmode(m_extractPath+"style.json", 0644);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
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 8e8b50f737..79e30f0552 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
@@ -99,6 +99,7 @@ public class QtActivityDelegate
private static final String APPLICATION_PARAMETERS_KEY = "application.parameters";
private static final String STATIC_INIT_CLASSES_KEY = "static.init.classes";
private static final String NECESSITAS_API_LEVEL_KEY = "necessitas.api.level";
+ private static final String EXTRACT_STYLE_KEY = "extract.android.style";
private static String m_environmentVariables = null;
private static String m_applicationParameters = null;
@@ -427,6 +428,11 @@ public class QtActivityDelegate
if (null == m_mainLib && libraries.size() > 0)
m_mainLib = libraries.get(libraries.size() - 1);
+ if (loaderParams.containsKey(EXTRACT_STYLE_KEY)) {
+ String path = loaderParams.getString(EXTRACT_STYLE_KEY);
+ new ExtractStyle(m_activity, path);
+ }
+
try {
m_super_dispatchKeyEvent = m_activity.getClass().getMethod("super_dispatchKeyEvent", KeyEvent.class);
m_super_onRestoreInstanceState = m_activity.getClass().getMethod("super_onRestoreInstanceState", Bundle.class);
@@ -888,7 +894,7 @@ public class QtActivityDelegate
return false;
}
- private boolean m_opionsMenuIsVisible = false;
+ private boolean m_optionsMenuIsVisible = false;
public boolean onCreateOptionsMenu(Menu menu)
{
menu.clear();
@@ -896,7 +902,7 @@ public class QtActivityDelegate
}
public boolean onPrepareOptionsMenu(Menu menu)
{
- m_opionsMenuIsVisible = true;
+ m_optionsMenuIsVisible = true;
boolean res = QtNative.onPrepareOptionsMenu(menu);
setActionBarVisibility(res && menu.size() > 0);
return res;
@@ -909,7 +915,7 @@ public class QtActivityDelegate
public void onOptionsMenuClosed(Menu menu)
{
- m_opionsMenuIsVisible = false;
+ m_optionsMenuIsVisible = false;
QtNative.onOptionsMenuClosed(menu);
}
@@ -923,7 +929,7 @@ public class QtActivityDelegate
}
}
else
- if (m_opionsMenuIsVisible)
+ if (m_optionsMenuIsVisible)
m_activity.closeOptionsMenu();
}
private boolean m_contextMenuVisible = false;
diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
index 45be15bc01..13d6359d36 100644
--- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
@@ -117,6 +117,7 @@ public class QtActivity extends Activity
private static final String MAIN_LIBRARY_KEY = "main.library";
private static final String STATIC_INIT_CLASSES_KEY = "static.init.classes";
private static final String NECESSITAS_API_LEVEL_KEY = "necessitas.api.level";
+ private static final String EXTRACT_STYLE_KEY = "extract.android.style";
/// Ministro server parameter keys
private static final String REQUIRED_MODULES_KEY = "required.modules";
@@ -178,6 +179,7 @@ public class QtActivity extends Activity
// * unstable - unstable repository, DO NOT use this repository in production,
// this repository is used to push Qt snapshots.
private String[] m_qtLibs = null; // required qt libs
+ private int m_displayDensity = -1;
public QtActivity()
{
@@ -630,6 +632,17 @@ public class QtActivity extends Activity
m_activityInfo.metaData.getString("android.app.static_init_classes").split(":"));
}
loaderParams.putStringArrayList(NATIVE_LIBRARIES_KEY, libraryList);
+
+
+ if (bundlingQtLibs) {
+ String themePath = pluginsPrefix + "android-style/";
+ String stylePath = themePath + m_displayDensity + "/";
+ if (!(new File(stylePath)).exists())
+ loaderParams.putString(EXTRACT_STYLE_KEY, stylePath);
+ ENVIRONMENT_VARIABLES += "\tMINISTRO_ANDROID_STYLE_PATH=" + stylePath
+ + "\tQT_ANDROID_THEMES_ROOT_PATH=" + themePath;
+ }
+
loaderParams.putString(ENVIRONMENT_VARIABLES_KEY, ENVIRONMENT_VARIABLES
+ "\tQML2_IMPORT_PATH=" + pluginsPrefix + "/qml"
+ "\tQML_IMPORT_PATH=" + pluginsPrefix + "/imports"
@@ -868,8 +881,10 @@ public class QtActivity extends Activity
return;
}
+ m_displayDensity = getResources().getDisplayMetrics().densityDpi;
+
ENVIRONMENT_VARIABLES += "\tQT_ANDROID_THEME=" + QT_ANDROID_DEFAULT_THEME
- + "/\tQT_ANDROID_THEME_DISPLAY_DPI=" + getResources().getDisplayMetrics().densityDpi + "\t";
+ + "/\tQT_ANDROID_THEME_DISPLAY_DPI=" + m_displayDensity + "\t";
if (null == getLastNonConfigurationInstance()) {
// if splash screen is defined, then show it
diff --git a/src/angle/patches/0019-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch b/src/angle/patches/0019-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch
new file mode 100644
index 0000000000..b0939a1126
--- /dev/null
+++ b/src/angle/patches/0019-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch
@@ -0,0 +1,28 @@
+From 6a3ced5ce411cdcc27308996db496a9d0ca0496f Mon Sep 17 00:00:00 2001
+From: Thiago Macieira <thiago.macieira@intel.com>
+Date: Wed, 18 Jun 2014 16:32:53 -0700
+Subject: [PATCH 19/19] Fix ANGLE build with Microsoft Visual Studio "14" CTP
+
+This version has a few new C99 support added, including snprintf.
+
+Change-Id: I5776456fd94254a64f08791f59bc775cb24c9b7f
+---
+ src/3rdparty/angle/src/common/angleutils.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h
+index 7723f0f..3d4246f 100644
+--- a/src/3rdparty/angle/src/common/angleutils.h
++++ b/src/3rdparty/angle/src/common/angleutils.h
+@@ -56,7 +56,7 @@ void SafeDeleteArray(T*& resource)
+ resource = NULL;
+ }
+
+-#if defined(_MSC_VER)
++#if defined(_MSC_VER) && _MSC_VER < 1900
+ #define snprintf _snprintf
+ #endif
+
+--
+1.8.4.5
+
diff --git a/src/concurrent/doc/qtconcurrent.qdocconf b/src/concurrent/doc/qtconcurrent.qdocconf
index e45047cb51..d8ee963ef5 100644
--- a/src/concurrent/doc/qtconcurrent.qdocconf
+++ b/src/concurrent/doc/qtconcurrent.qdocconf
@@ -2,7 +2,6 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = QtConcurrent
description = Qt Concurrent Reference Documentation
-url = http://qt-project.org/doc/qt-$QT_VER
version = $QT_VERSION
examplesinstallpath = qtconcurrent
diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp
index a23a6a7cda..61fe6e8c88 100644
--- a/src/corelib/animation/qvariantanimation.cpp
+++ b/src/corelib/animation/qvariantanimation.cpp
@@ -206,11 +206,11 @@ void QVariantAnimationPrivate::convertValues(int t)
//this ensures that all the keyValues are of type t
for (int i = 0; i < keyValues.count(); ++i) {
QVariantAnimation::KeyValue &pair = keyValues[i];
- pair.second.convert(static_cast<QVariant::Type>(t));
+ pair.second.convert(t);
}
//we also need update to the current interval if needed
- currentInterval.start.second.convert(static_cast<QVariant::Type>(t));
- currentInterval.end.second.convert(static_cast<QVariant::Type>(t));
+ currentInterval.start.second.convert(t);
+ currentInterval.end.second.convert(t);
//... and the interpolator
updateInterpolator();
diff --git a/src/corelib/codecs/qutfcodec.cpp b/src/corelib/codecs/qutfcodec.cpp
index 4fb32dcc59..9139e61700 100644
--- a/src/corelib/codecs/qutfcodec.cpp
+++ b/src/corelib/codecs/qutfcodec.cpp
@@ -100,27 +100,44 @@ static inline bool simdDecodeAscii(ushort *&dst, const uchar *&nextAscii, const
for ( ; end - src >= 16; src += 16, dst += 16) {
__m128i data = _mm_loadu_si128((__m128i*)src);
+#ifdef __AVX2__
+ const int BitSpacing = 2;
+ // load and zero extend to an YMM register
+ const __m256i extended = _mm256_cvtepu8_epi16(data);
+
+ uint n = _mm256_movemask_epi8(extended);
+ if (!n) {
+ // store
+ _mm256_storeu_si256((__m256i*)dst, extended);
+ continue;
+ }
+#else
+ const int BitSpacing = 1;
+
// check if everything is ASCII
// movemask extracts the high bit of every byte, so n is non-zero if something isn't ASCII
uint n = _mm_movemask_epi8(data);
- if (n) {
- // copy the front part that is still ASCII
- while (!(n & 1)) {
- *dst++ = *src++;
- n >>= 1;
- }
+ if (!n) {
+ // unpack
+ _mm_storeu_si128((__m128i*)dst, _mm_unpacklo_epi8(data, _mm_setzero_si128()));
+ _mm_storeu_si128(1+(__m128i*)dst, _mm_unpackhi_epi8(data, _mm_setzero_si128()));
+ continue;
+ }
+#endif
- // find the next probable ASCII character
- // we don't want to load 16 bytes again in this loop if we know there are non-ASCII
- // characters still coming
- n = _bit_scan_reverse(n);
- nextAscii = src + n + 1;
- return false;
+ // copy the front part that is still ASCII
+ while (!(n & 1)) {
+ *dst++ = *src++;
+ n >>= BitSpacing;
}
- // unpack
- _mm_storeu_si128((__m128i*)dst, _mm_unpacklo_epi8(data, _mm_setzero_si128()));
- _mm_storeu_si128(1+(__m128i*)dst, _mm_unpackhi_epi8(data, _mm_setzero_si128()));
+ // find the next probable ASCII character
+ // we don't want to load 16 bytes again in this loop if we know there are non-ASCII
+ // characters still coming
+ n = _bit_scan_reverse(n);
+ nextAscii = src + (n / BitSpacing) + 1;
+ return false;
+
}
return src == end;
}
diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro
index 812aee3252..2d78041752 100644
--- a/src/corelib/corelib.pro
+++ b/src/corelib/corelib.pro
@@ -31,6 +31,7 @@ ANDROID_PERMISSIONS = \
android.permission.WRITE_EXTERNAL_STORAGE
load(qt_module)
+load(qfeatures)
include(animation/animation.pri)
include(arch/arch.pri)
@@ -84,7 +85,6 @@ cmake_umbrella_config_version_file.input = $$PWD/../../mkspecs/features/data/cma
cmake_umbrella_config_version_file.output = $$DESTDIR/cmake/Qt5/Qt5ConfigVersion.cmake
load(cmake_functions)
-load(qfeatures)
CMAKE_DISABLED_FEATURES = $$join(QT_DISABLED_FEATURES, "$$escape_expand(\\n) ")
@@ -116,17 +116,3 @@ 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
-
-mips_dsp:*-g++* {
- HEADERS += $$MIPS_DSP_HEADERS
-
- mips_dsp_corelib_assembler.commands = $$QMAKE_CXX -c
- mips_dsp_corelib_assembler.commands += $(CXXFLAGS) $(INCPATH) -mips32r2 -mdsp ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
- mips_dsp_corelib_assembler.dependency_type = TYPE_C
- mips_dsp_corelib_assembler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
- mips_dsp_corelib_assembler.input = MIPS_DSP_ASM
- mips_dsp_corelib_assembler.variable_out = OBJECTS
- mips_dsp_corelib_assembler.name = assembling[mips_dsp] ${QMAKE_FILE_IN}
- silent:mips_dsp_corelib_assembler.commands = @echo assembling[mips_dsp] ${QMAKE_FILE_IN} && $$mips_dsp_corelib_assembler.commands
- QMAKE_EXTRA_COMPILERS += mips_dsp_corelib_assembler
-}
diff --git a/src/corelib/doc/qtcore.qdocconf b/src/corelib/doc/qtcore.qdocconf
index c9c8f1da54..7c879cbbfd 100644
--- a/src/corelib/doc/qtcore.qdocconf
+++ b/src/corelib/doc/qtcore.qdocconf
@@ -2,7 +2,6 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = QtCore
description = Qt Core Reference Documentation
-url = http://qt-project.org/doc/qt-$QT_VER
version = $QT_VERSION
examplesinstallpath = core
diff --git a/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp b/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
index b907c9acb1..d804514584 100644
--- a/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
@@ -136,9 +136,9 @@ int roundedValueB = qRound(valueB);
qreal valueA = 42949672960.3;
qreal valueB = 42949672960.7;
-int roundedValueA = qRound(valueA);
+qint64 roundedValueA = qRound64(valueA);
// roundedValueA = 42949672960
-int roundedValueB = qRound(valueB);
+qint64 roundedValueB = qRound64(valueB);
// roundedValueB = 42949672961
//! [12]
@@ -305,7 +305,7 @@ void load(const QString &fileName)
{
QFile file(fileName);
if (!file.exists())
- qCritical("File '%s' does not exist!", qPrintable(fileName));
+ qCritical("File '%s' does not exist!", qUtf8Printable(fileName));
}
//! [28]
@@ -424,7 +424,7 @@ void TheClass::addLabels()
//! [37]
-qWarning("%s: %s", qPrintable(key), qPrintable(value));
+qWarning("%s: %s", qUtf8Printable(key), qUtf8Printable(value));
//! [37]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
index 8c21083976..aa0473964c 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
@@ -297,3 +297,13 @@ while (i != hash.end() && i.key() == "plenty") {
++i;
}
//! [26]
+
+//! [qhashbits]
+inline uint qHash(const std::vector<int> &key, uint seed = 0)
+{
+ if (key.empty())
+ return seed;
+ else
+ return qHashBits(&key.front(), key.size() * sizeof(int), seed);
+}
+//! [qhashbits]
diff --git a/src/corelib/doc/snippets/qloggingcategory/main.cpp b/src/corelib/doc/snippets/qloggingcategory/main.cpp
index 628243dbdd..3c6424921e 100644
--- a/src/corelib/doc/snippets/qloggingcategory/main.cpp
+++ b/src/corelib/doc/snippets/qloggingcategory/main.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
@@ -43,12 +43,15 @@
//![1]
// in a header
-Q_DECLARE_LOGGING_CATEGORY(QT_DRIVER_USB)
+Q_DECLARE_LOGGING_CATEGORY(driverUsb)
// in one source file
-Q_LOGGING_CATEGORY(QT_DRIVER_USB, "qt.driver.usb")
+Q_LOGGING_CATEGORY(driverUsb, "driver.usb")
//![1]
+//![5]
+Q_LOGGING_CATEGORY(driverUsbEvents, "driver.usb.events", QtWarningMsg)
+//![5]
// Completely made up example, inspired by en.wikipedia.org/wiki/USB :)
struct UsbEntry {
@@ -76,8 +79,8 @@ QLoggingCategory::CategoryFilter oldCategoryFilter;
void myCategoryFilter(QLoggingCategory *category)
{
- // configure qt.driver.usb category here, otherwise forward to to default filter.
- if (qstrcmp(category->categoryName(), "qt.driver.usb") == 0)
+ // configure driver.usb category here, otherwise forward to to default filter.
+ if (qstrcmp(category->categoryName(), "driver.usb") == 0)
category->setEnabled(QtDebugMsg, true);
else
oldCategoryFilter(category);
@@ -89,7 +92,7 @@ int main(int argc, char *argv[])
QCoreApplication a(argc, argv);
//![2]
- QLoggingCategory::setFilterRules(QStringLiteral("qt.driver.usb.debug=true"));
+ QLoggingCategory::setFilterRules(QStringLiteral("driver.usb.debug=true"));
//![2]
//![22]
@@ -103,48 +106,48 @@ oldCategoryFilter = QLoggingCategory::installFilter(myCategoryFilter);
//![3]
//![4]
- // usbEntries() will only be called if QT_DRIVER_USB category is enabled
- qCDebug(QT_DRIVER_USB) << "devices: " << usbEntries();
+ // usbEntries() will only be called if driverUsb category is enabled
+ qCDebug(driverUsb) << "devices: " << usbEntries();
//![4]
{
//![10]
- QLoggingCategory category("qt.driver.usb");
+ QLoggingCategory category("driver.usb");
qCDebug(category) << "a debug message";
//![10]
}
{
//![11]
- QLoggingCategory category("qt.driver.usb");
+ QLoggingCategory category("driver.usb");
qCWarning(category) << "a warning message";
//![11]
}
{
//![12]
- QLoggingCategory category("qt.driver.usb");
+ QLoggingCategory category("driver.usb");
qCCritical(category) << "a critical message";
//![12]
}
{
//![13]
- QLoggingCategory category("qt.driver.usb");
+ QLoggingCategory category("driver.usb");
qCDebug(category, "a debug message logged into category %s", category.categoryName());
//![13]
}
{
//![14]
- QLoggingCategory category("qt.driver.usb");
+ QLoggingCategory category("driver.usb");
qCWarning(category, "a warning message logged into category %s", category.categoryName());
//![14]
}
{
//![15]
- QLoggingCategory category("qt.driver.usb");
+ QLoggingCategory category("driver.usb");
qCCritical(category, "a critical message logged into category %s", category.categoryName());
//![15]
}
diff --git a/src/corelib/global/archdetect.cpp b/src/corelib/global/archdetect.cpp
new file mode 100644
index 0000000000..9540e391ba
--- /dev/null
+++ b/src/corelib/global/archdetect.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Intel Corporation
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the FOO 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qprocessordetection.h"
+
+// main part: processor type
+#if defined(Q_PROCESSOR_ALPHA)
+# define ARCH_PROCESSOR "alpha"
+#elif defined(Q_PROCESSOR_ARM_32)
+# define ARCH_PROCESSOR "arm"
+#elif defined(Q_PROCESSOR_ARM_64)
+# define ARCH_PROCESSOR "arm64"
+#elif defined(Q_PROCESSOR_AVR32)
+# define ARCH_PROCESSOR "avr32"
+#elif defined(Q_PROCESSOR_BLACKFIN)
+# define ARCH_PROCESSOR "bfin"
+#elif defined(Q_PROCESSOR_X86_32)
+# define ARCH_PROCESSOR "i386"
+#elif defined(Q_PROCESSOR_X86_64)
+# define ARCH_PROCESSOR "x86_64"
+#elif defined(Q_PROCESSOR_IA64)
+# define ARCH_PROCESSOR "ia64"
+#elif defined(Q_PROCESSOR_MIPS_64)
+# define ARCH_PROCESSOR "mips64"
+#elif defined(Q_PROCESSOR_MIPS)
+# define ARCH_PROCESSOR "mips"
+#elif defined(Q_PROCESSOR_POWER_32)
+# define ARCH_PROCESSOR "power"
+#elif defined(Q_PROCESSOR_POWER_64)
+# define ARCH_PROCESSOR "power64"
+#elif defined(Q_PROCESSOR_S390_X)
+# define ARCH_PROCESSOR "s390x"
+#elif defined(Q_PROCESSOR_S390)
+# define ARCH_PROCESSOR "s390"
+#elif defined(Q_PROCESSOR_SH)
+# define ARCH_PROCESSOR "sh"
+#elif defined(Q_PROCESSOR_SPARC_V9)
+# define ARCH_PROCESSOR "sparcv9"
+#elif defined(Q_PROCESSOR_SPARC)
+# define ARCH_PROCESSOR "sparc"
+#else
+# define ARCH_PROCESSOR "unknown"
+#endif
+
+// endinanness
+#if defined(Q_LITTLE_ENDIAN)
+# define ARCH_ENDIANNESS "little_endian"
+#elif defined(Q_BIG_ENDIAN)
+# define ARCH_ENDIANNESS "big_endian"
+#endif
+
+// pointer type
+#if defined(Q_OS_WIN64) || (defined(Q_OS_WINRT) && defined(_M_X64))
+# define ARCH_POINTER "llp64"
+#elif defined(__LP64__) || QT_POINTER_SIZE - 0 == 8
+# define ARCH_POINTER "lp64"
+#else
+# define ARCH_POINTER "ilp32"
+#endif
+
+// qreal type, if not double (includes the dash)
+#ifdef QT_COORD_TYPE_STRING
+# define ARCH_COORD_TYPE "-qreal_" QT_COORD_TYPE_STRING
+#else
+# define ARCH_COORD_TYPE ""
+#endif
+
+// secondary: ABI string (includes the dash)
+#if defined(__ARM_EABI__) || defined(__mips_eabi)
+# define ARCH_ABI1 "-eabi"
+#elif defined(_MIPS_SIM)
+# if _MIPS_SIM == _ABIO32
+# define ARCH_ABI1 "-o32"
+# elif _MIPS_SIM == _ABIN32
+# define ARCH_ABI1 "-n32"
+# elif _MIPS_SIM == _ABI64
+# define ARCH_ABI1 "-n64"
+# elif _MIPS_SIM == _ABIO64
+# define ARCH_ABI1 "-o64"
+# endif
+#else
+# define ARCH_ABI1 ""
+#endif
+#if defined(__ARM_PCS_VFP) || defined(__mips_hard_float)
+# define ARCH_ABI2 "-hardfloat"
+#else
+# define ARCH_ABI2 ""
+#endif
+
+#define ARCH_ABI ARCH_ABI1 ARCH_ABI2
+
+#define ARCH_FULL ARCH_PROCESSOR "-" ARCH_ENDIANNESS "-" ARCH_POINTER ARCH_COORD_TYPE ARCH_ABI
diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri
index efa585ff3e..fb0e7fd708 100644
--- a/src/corelib/global/global.pri
+++ b/src/corelib/global/global.pri
@@ -16,15 +16,18 @@ HEADERS += \
global/qsysinfo.h \
global/qisenum.h \
global/qtypetraits.h \
- global/qflags.h
+ global/qflags.h \
+ global/qhooks_p.h
SOURCES += \
+ global/archdetect.cpp \
global/qglobal.cpp \
global/qglobalstatic.cpp \
global/qlibraryinfo.cpp \
global/qmalloc.cpp \
global/qnumeric.cpp \
- global/qlogging.cpp
+ global/qlogging.cpp \
+ global/qhooks.cpp
# qlibraryinfo.cpp includes qconfig.cpp
INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index b12f944357..693d7e5c75 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2012 Intel Corporation
** Contact: http://www.qt-project.org/legal
**
@@ -89,7 +89,9 @@
# define Q_CC_MSVC
# define Q_CC_MSVC_NET
# define Q_OUTOFLINE_TEMPLATE inline
-# define Q_NO_TEMPLATE_FRIENDS
+# if _MSC_VER < 1600
+# define Q_NO_TEMPLATE_FRIENDS
+# endif
# define Q_COMPILER_MANGLES_RETURN_TYPE
# define Q_FUNC_INFO __FUNCSIG__
# define Q_ALIGNOF(type) __alignof(type)
@@ -200,6 +202,8 @@
# define Q_UNLIKELY(expr) __builtin_expect(!!(expr), false)
# define Q_NORETURN __attribute__((__noreturn__))
# define Q_REQUIRED_RESULT __attribute__ ((__warn_unused_result__))
+# define Q_DECL_PURE_FUNCTION __attribute__((pure))
+# define Q_DECL_CONST_FUNCTION __attribute__((const))
# if !defined(QT_MOC_CPP)
# define Q_PACKED __attribute__ ((__packed__))
# ifndef __ARM_EABI__
@@ -439,59 +443,55 @@
/*
* C++11 support
*
- * Paper Macro
+ * Paper Macro SD-6 macro
* N2341 Q_COMPILER_ALIGNAS
* N2341 Q_COMPILER_ALIGNOF
* N2427 Q_COMPILER_ATOMICS
- * N2761 Q_COMPILER_ATTRIBUTES
+ * N2761 Q_COMPILER_ATTRIBUTES __cpp_attributes = 200809
* N2541 Q_COMPILER_AUTO_FUNCTION
* N1984 N2546 Q_COMPILER_AUTO_TYPE
* N2437 Q_COMPILER_CLASS_ENUM
- * N2235 Q_COMPILER_CONSTEXPR
- * N2343 N3276 Q_COMPILER_DECLTYPE
+ * N2235 Q_COMPILER_CONSTEXPR __cpp_constexpr = 200704
+ * N2343 N3276 Q_COMPILER_DECLTYPE __cpp_decltype = 200707
* N2346 Q_COMPILER_DEFAULT_MEMBERS
* N2346 Q_COMPILER_DELETE_MEMBERS
* N1986 Q_COMPILER_DELEGATING_CONSTRUCTORS
* N2437 Q_COMPILER_EXPLICIT_CONVERSIONS
- * N3206 N3272 Q_COMPILER_EXPLICIT_OVERRIDES (v0.9 and above only)
+ * N3206 N3272 Q_COMPILER_EXPLICIT_OVERRIDES
* N1987 Q_COMPILER_EXTERN_TEMPLATES
* N2540 Q_COMPILER_INHERITING_CONSTRUCTORS
* N2672 Q_COMPILER_INITIALIZER_LISTS
- * N2658 N2927 Q_COMPILER_LAMBDA (v1.0 and above only)
+ * N2658 N2927 Q_COMPILER_LAMBDA __cpp_lambdas = 200907
* N2756 Q_COMPILER_NONSTATIC_MEMBER_INIT
* N2855 N3050 Q_COMPILER_NOEXCEPT
* N2431 Q_COMPILER_NULLPTR
* N2930 Q_COMPILER_RANGE_FOR
- * N2442 Q_COMPILER_RAW_STRINGS
+ * N2442 Q_COMPILER_RAW_STRINGS __cpp_raw_strings = 200710
* N2439 Q_COMPILER_REF_QUALIFIERS
- * N2118 N2844 N3053 Q_COMPILER_RVALUE_REFS (Note: GCC 4.3 implements only the oldest)
- * N1720 Q_COMPILER_STATIC_ASSERT
+ * N2118 N2844 N3053 Q_COMPILER_RVALUE_REFS __cpp_rvalue_references = 200610
+ * N1720 Q_COMPILER_STATIC_ASSERT __cpp_static_assert = 200410
* N2258 Q_COMPILER_TEMPLATE_ALIAS
* N2659 Q_COMPILER_THREAD_LOCAL
- * N2765 Q_COMPILER_UDL
- * N2442 Q_COMPILER_UNICODE_STRINGS
+ * N2660 Q_COMPILER_THREADSAFE_STATICS
+ * N2765 Q_COMPILER_UDL __cpp_user_defined_literals = 200809
+ * N2442 Q_COMPILER_UNICODE_STRINGS __cpp_unicode_literals = 200710
* N2640 Q_COMPILER_UNIFORM_INIT
* N2544 Q_COMPILER_UNRESTRICTED_UNIONS
* N1653 Q_COMPILER_VARIADIC_MACROS
- * N2242 N2555 Q_COMPILER_VARIADIC_TEMPLATES
- *
- * C++1y proposed features
- *
- * N3472 Q_COMPILER_BINARY_LITERALS
- * N3649 Q_COMPILER_GENERIC_LAMBDA
- * N3638 Q_COMPILER_LAMBDA_CAPTURES
- * N3652 Q_COMPILER_RELAXED_CONSTEXPR_FUNCTIONS
- * N3386 N3638 Q_COMPILER_RETURN_TYPE_DEDUCTION
- * N3651 Q_COMPILER_VARIABLE_TEMPLATES
+ * N2242 N2555 Q_COMPILER_VARIADIC_TEMPLATES __cpp_variadic_templates = 200704
*
- * C++14 Technical Specifications / C++17:
- * N3639 Q_COMPILER_VLA (see also Q_COMPILER_RESTRICTED_VLA)
+ * For any future version of the C++ standard, we use only the SD-6 macro.
+ * For full listing, see
+ * http://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations
*
+ * C++ extensions:
+ * Q_COMPILER_RESTRICTED_VLA variable-length arrays, prior to __cpp_runtime_arrays
*/
#ifdef Q_CC_INTEL
# define Q_COMPILER_RESTRICTED_VLA
# define Q_COMPILER_VARIADIC_MACROS // C++11 feature supported as an extension in other modes, too
+# define Q_COMPILER_THREADSAFE_STATICS
# if __INTEL_COMPILER < 1200
# define Q_NO_TEMPLATE_FRIENDS
# endif
@@ -533,18 +533,28 @@
// causes issues with QArrayData and QtPrivate::RefCount - Intel issue ID 6000056211, bug DPD200534796
//# define Q_COMPILER_CONSTEXPR
# define Q_COMPILER_DELEGATING_CONSTRUCTORS
+# define Q_COMPILER_EXPLICIT_CONVERSIONS
# define Q_COMPILER_EXPLICIT_OVERRIDES
# define Q_COMPILER_NONSTATIC_MEMBER_INIT
+# define Q_COMPILER_RANGE_FOR
# define Q_COMPILER_RAW_STRINGS
# define Q_COMPILER_REF_QUALIFIERS
# define Q_COMPILER_UNRESTRICTED_UNIONS
# endif
+# if __INTEL_COMPILER >= 1500
+# define Q_COMPILER_ALIGNAS
+# define Q_COMPILER_ALIGNOF
+# define Q_COMPILER_INHERITING_CONSTRUCTORS
+# define Q_COMPILER_THREAD_LOCAL
+# define Q_COMPILER_UDL
+# endif
# endif
#endif
#if defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
/* General C++ features */
# define Q_COMPILER_RESTRICTED_VLA
+# define Q_COMPILER_THREADSAFE_STATICS
# if !__has_feature(cxx_exceptions)
# ifndef QT_NO_EXCEPTIONS
# define QT_NO_EXCEPTIONS
@@ -671,8 +681,7 @@
# endif
# endif
-/* C++1y features, see http://clang.llvm.org/cxx_status.html and
- * http://clang.llvm.org/docs/LanguageExtensions.html#checks-for-standard-language-features */
+/* C++1y features, deprecated macros. Do not update this list. */
# if __cplusplus > 201103L
//# if __has_feature(cxx_binary_literals)
//# define Q_COMPILER_BINARY_LITERALS // see above
@@ -696,10 +705,18 @@
# define Q_COMPILER_VLA
# endif
# endif
+
+# if defined(__has_warning)
+# if __has_warning("-Wunused-private-field")
+# define Q_DECL_UNUSED_MEMBER Q_DECL_UNUSED
+# endif
+# endif
+
#endif // Q_CC_CLANG
#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG)
# define Q_COMPILER_RESTRICTED_VLA
+# define Q_COMPILER_THREADSAFE_STATICS
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403
// GCC supports binary literals in C, C++98 and C++11 modes
# define Q_COMPILER_BINARY_LITERALS
@@ -773,7 +790,7 @@
# endif
# if __cplusplus > 201103L
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409
- /* C++1y features in GCC 4.9 */
+ /* C++1y features in GCC 4.9 - deprecated, do not update this list */
//# define Q_COMPILER_BINARY_LITERALS // already supported since GCC 4.3 as an extension
# define Q_COMPILER_LAMBDA_CAPTURES
# define Q_COMPILER_RETURN_TYPE_DEDUCTION
@@ -782,6 +799,7 @@
#endif
#if defined(Q_CC_MSVC) && !defined(Q_CC_INTEL)
+# if defined(__cplusplus)
# if _MSC_VER >= 1400
/* C++11 features supported in VC8 = VC2005: */
# define Q_COMPILER_VARIADIC_MACROS
@@ -804,8 +822,10 @@
/* C++11 features supported in VC10 = VC2010: */
# define Q_COMPILER_AUTO_FUNCTION
# define Q_COMPILER_AUTO_TYPE
-# define Q_COMPILER_LAMBDA
# define Q_COMPILER_DECLTYPE
+# define Q_COMPILER_EXTERN_TEMPLATES
+# define Q_COMPILER_LAMBDA
+# define Q_COMPILER_NULLPTR
# define Q_COMPILER_RVALUE_REFS
# define Q_COMPILER_STATIC_ASSERT
// MSVC's library has std::initializer_list, but the compiler does not support the braces initialization
@@ -817,7 +837,6 @@
# undef Q_DECL_OVERRIDE /* undo 2005/2008 settings... */
# undef Q_DECL_FINAL /* undo 2005/2008 settings... */
# define Q_COMPILER_EXPLICIT_OVERRIDES /* ...and use std C++11 now */
-# define Q_COMPILER_RANGE_FOR
# define Q_COMPILER_CLASS_ENUM
# define Q_COMPILER_ATOMICS
# endif /* VC 11 */
@@ -840,6 +859,7 @@
# define Q_COMPILER_INITIALIZER_LISTS
# endif /* VC 12 SP 2 RC */
+# endif /* __cplusplus */
#endif /* Q_CC_MSVC */
#ifdef __cplusplus
@@ -864,6 +884,13 @@
# undef Q_COMPILER_RVALUE_REFS
# undef Q_COMPILER_REF_QUALIFIERS
# endif
+# if defined(Q_COMPILER_THREADSAFE_STATICS) && defined(Q_OS_MAC)
+// Mac OS X: Apple's low-level implementation of the C++ support library
+// (libc++abi.dylib, shared between libstdc++ and libc++) has deadlocks. The
+// C++11 standard requires the deadlocks to be removed, so this will eventually
+// be fixed; for now, let's disable this.
+# undef Q_COMPILER_THREADSAFE_STATICS
+# endif
#endif
/*
@@ -976,6 +1003,9 @@
#ifndef Q_DECL_UNUSED
# define Q_DECL_UNUSED
#endif
+#ifndef Q_DECL_UNUSED_MEMBER
+# define Q_DECL_UNUSED_MEMBER
+#endif
#ifndef Q_FUNC_INFO
# if defined(Q_OS_SOLARIS) || defined(Q_CC_XLC)
# define Q_FUNC_INFO __FILE__ "(line number unavailable)"
@@ -989,17 +1019,11 @@
#ifndef Q_DECL_NS_RETURNS_AUTORELEASED
# define Q_DECL_NS_RETURNS_AUTORELEASED
#endif
-
-/*
- Workaround for static const members on MSVC++.
-*/
-
-#if defined(Q_CC_MSVC)
-# define QT_STATIC_CONST static
-# define QT_STATIC_CONST_IMPL
-#else
-# define QT_STATIC_CONST static const
-# define QT_STATIC_CONST_IMPL const
+#ifndef Q_DECL_PURE_FUNCTION
+# define Q_DECL_PURE_FUNCTION
+#endif
+#ifndef Q_DECL_CONST_FUNCTION
+# define Q_DECL_CONST_FUNCTION Q_DECL_PURE_FUNCTION
#endif
/*
diff --git a/src/corelib/global/qflags.h b/src/corelib/global/qflags.h
index bdfc453e08..097f2760b4 100644
--- a/src/corelib/global/qflags.h
+++ b/src/corelib/global/qflags.h
@@ -47,6 +47,10 @@
#include <QtCore/qtypeinfo.h>
#include <QtCore/qtypetraits.h>
+#ifdef Q_COMPILER_INITIALIZER_LISTS
+#include <initializer_list>
+#endif
+
QT_BEGIN_NAMESPACE
class QFlag
@@ -116,6 +120,11 @@ public:
Q_DECL_CONSTEXPR inline QFlags(Zero = 0) : i(0) {}
Q_DECL_CONSTEXPR inline QFlags(QFlag f) : i(f) {}
+#ifdef Q_COMPILER_INITIALIZER_LISTS
+ Q_DECL_CONSTEXPR inline QFlags(std::initializer_list<Enum> flags)
+ : i(initializer_list_helper(flags.begin(), flags.end())) {}
+#endif
+
inline QFlags &operator&=(int mask) { i &= mask; return *this; }
inline QFlags &operator&=(uint mask) { i &= mask; return *this; }
inline QFlags &operator&=(Enum mask) { i &= Int(mask); return *this; }
@@ -139,6 +148,14 @@ public:
Q_DECL_CONSTEXPR inline bool testFlag(Enum f) const { return (i & Int(f)) == Int(f) && (Int(f) != 0 || i == Int(f) ); }
private:
+#ifdef Q_COMPILER_INITIALIZER_LISTS
+ Q_DECL_CONSTEXPR static inline Int initializer_list_helper(typename std::initializer_list<Enum>::const_iterator it,
+ typename std::initializer_list<Enum>::const_iterator end)
+ {
+ return (it == end ? Int(0) : (Int(*it) | initializer_list_helper(it + 1, end)));
+ }
+#endif
+
Int i;
};
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 6b5638d336..66f2923370 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Intel Corporation
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -80,6 +81,17 @@
#include <private/qjni_p.h>
#endif
+#if defined(Q_OS_BLACKBERRY)
+# include <bps/deviceinfo.h>
+#endif
+
+#ifdef Q_OS_UNIX
+#include <sys/utsname.h>
+#include <private/qcore_unix_p.h>
+#endif
+
+#include "archdetect.cpp"
+
QT_BEGIN_NAMESPACE
#if !QT_DEPRECATED_SINCE(5, 0)
@@ -258,6 +270,16 @@ Q_STATIC_ASSERT_X(UCHAR_MAX == 255, "Qt assumes that char is 8 bits");
*/
/*!
+ \fn QFlags::QFlags(std::initializer_list<Enum> flags)
+ \since 5.4
+
+ Constructs a QFlags object initialized with all \a flags
+ combined using the bitwise OR operator.
+
+ \sa operator|=(), operator|()
+*/
+
+/*!
\fn QFlags &QFlags::operator=(const QFlags &other)
Assigns \a other to this object and returns a reference to this
@@ -568,8 +590,8 @@ Q_STATIC_ASSERT_X(UCHAR_MAX == 255, "Qt assumes that char is 8 bits");
64-bit integer literals in a platform-independent way. The
Q_CHECK_PTR() macro prints a warning containing the source code's
file name and line number, saying that the program ran out of
- memory, if the pointer is 0. The qPrintable() macro represent an
- easy way of printing text.
+ memory, if the pointer is 0. The qPrintable() and qUtf8Printable()
+ macros represent an easy way of printing text.
Finally, the QT_POINTER_SIZE macro expands to the size of a
pointer in bytes, and the QT_VERSION and QT_VERSION_STR macros
@@ -1096,6 +1118,7 @@ bool qSharedBuild() Q_DECL_NOTHROW
\value MV_10_7 OS X 10.7
\value MV_10_8 OS X 10.8
\value MV_10_9 OS X 10.9
+ \value MV_10_10 OS X 10.10
\value MV_Unknown An unknown and currently unsupported platform
\value MV_CHEETAH Apple codename for MV_10_0
@@ -1108,6 +1131,7 @@ bool qSharedBuild() Q_DECL_NOTHROW
\value MV_LION Apple codename for MV_10_7
\value MV_MOUNTAINLION Apple codename for MV_10_8
\value MV_MAVERICKS Apple codename for MV_10_9
+ \value MV_YOSEMITE Apple codename for MV_10_10
\value MV_IOS iOS (any)
\value MV_IOS_4_3 iOS 4.3
@@ -1117,6 +1141,7 @@ bool qSharedBuild() Q_DECL_NOTHROW
\value MV_IOS_6_1 iOS 6.1
\value MV_IOS_7_0 iOS 7.0
\value MV_IOS_7_1 iOS 7.1
+ \value MV_IOS_8_0 iOS 8.0
\sa WinVersion
*/
@@ -1500,6 +1525,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
\relates <QtGlobal>
Defined if the application is compiled for Alpha processors.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1509,6 +1536,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for ARM processors. Qt currently
supports three optional ARM revisions: \l Q_PROCESSOR_ARM_V5, \l
Q_PROCESSOR_ARM_V6, and \l Q_PROCESSOR_ARM_V7.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_ARM_V5
@@ -1516,6 +1545,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for ARMv5 processors. The \l
Q_PROCESSOR_ARM macro is also defined when Q_PROCESSOR_ARM_V5 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_ARM_V6
@@ -1524,6 +1555,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for ARMv6 processors. The \l
Q_PROCESSOR_ARM and \l Q_PROCESSOR_ARM_V5 macros are also defined when
Q_PROCESSOR_ARM_V6 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_ARM_V7
@@ -1532,6 +1565,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for ARMv7 processors. The \l
Q_PROCESSOR_ARM, \l Q_PROCESSOR_ARM_V5, and \l Q_PROCESSOR_ARM_V6 macros
are also defined when Q_PROCESSOR_ARM_V7 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1539,6 +1574,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
\relates <QtGlobal>
Defined if the application is compiled for AVR32 processors.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1546,6 +1583,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
\relates <QtGlobal>
Defined if the application is compiled for Blackfin processors.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1554,6 +1593,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for IA-64 processors. This includes
all Itanium and Itanium 2 processors.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1564,6 +1605,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
supports seven MIPS revisions: \l Q_PROCESSOR_MIPS_I, \l
Q_PROCESSOR_MIPS_II, \l Q_PROCESSOR_MIPS_III, \l Q_PROCESSOR_MIPS_IV, \l
Q_PROCESSOR_MIPS_V, \l Q_PROCESSOR_MIPS_32, and \l Q_PROCESSOR_MIPS_64.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_MIPS_I
@@ -1571,6 +1614,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for MIPS-I processors. The \l
Q_PROCESSOR_MIPS macro is also defined when Q_PROCESSOR_MIPS_I is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_MIPS_II
@@ -1579,6 +1624,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for MIPS-II processors. The \l
Q_PROCESSOR_MIPS and \l Q_PROCESSOR_MIPS_I macros are also defined when
Q_PROCESSOR_MIPS_II is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_MIPS_32
@@ -1587,6 +1634,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for MIPS32 processors. The \l
Q_PROCESSOR_MIPS, \l Q_PROCESSOR_MIPS_I, and \l Q_PROCESSOR_MIPS_II macros
are also defined when Q_PROCESSOR_MIPS_32 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_MIPS_III
@@ -1595,6 +1644,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for MIPS-III processors. The \l
Q_PROCESSOR_MIPS, \l Q_PROCESSOR_MIPS_I, and \l Q_PROCESSOR_MIPS_II macros
are also defined when Q_PROCESSOR_MIPS_III is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_MIPS_IV
@@ -1604,6 +1655,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Q_PROCESSOR_MIPS, \l Q_PROCESSOR_MIPS_I, \l Q_PROCESSOR_MIPS_II, and \l
Q_PROCESSOR_MIPS_III macros are also defined when Q_PROCESSOR_MIPS_IV is
defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_MIPS_V
@@ -1613,6 +1666,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Q_PROCESSOR_MIPS, \l Q_PROCESSOR_MIPS_I, \l Q_PROCESSOR_MIPS_II, \l
Q_PROCESSOR_MIPS_III, and \l Q_PROCESSOR_MIPS_IV macros are also defined
when Q_PROCESSOR_MIPS_V is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_MIPS_64
@@ -1622,6 +1677,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Q_PROCESSOR_MIPS, \l Q_PROCESSOR_MIPS_I, \l Q_PROCESSOR_MIPS_II, \l
Q_PROCESSOR_MIPS_III, \l Q_PROCESSOR_MIPS_IV, and \l Q_PROCESSOR_MIPS_V
macros are also defined when Q_PROCESSOR_MIPS_64 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1631,6 +1688,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for POWER processors. Qt currently
supports two Power variants: \l Q_PROCESSOR_POWER_32 and \l
Q_PROCESSOR_POWER_64.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_POWER_32
@@ -1639,6 +1698,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for 32-bit Power processors. The \l
Q_PROCESSOR_POWER macro is also defined when Q_PROCESSOR_POWER_32 is
defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_POWER_64
@@ -1647,6 +1708,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for 64-bit Power processors. The \l
Q_PROCESSOR_POWER macro is also defined when Q_PROCESSOR_POWER_64 is
defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1655,6 +1718,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for S/390 processors. Qt supports
one optional variant of S/390: Q_PROCESSOR_S390_X.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_S390_X
@@ -1662,6 +1727,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for S/390x processors. The \l
Q_PROCESSOR_S390 macro is also defined when Q_PROCESSOR_S390_X is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1670,6 +1737,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for SuperH processors. Qt currently
supports one SuperH revision: \l Q_PROCESSOR_SH_4A.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_SH_4A
@@ -1677,6 +1746,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for SuperH 4A processors. The \l
Q_PROCESSOR_SH macro is also defined when Q_PROCESSOR_SH_4A is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1685,6 +1756,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for SPARC processors. Qt currently
supports one optional SPARC revision: \l Q_PROCESSOR_SPARC_V9.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_SPARC_V9
@@ -1693,6 +1766,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for SPARC V9 processors. The \l
Q_PROCESSOR_SPARC macro is also defined when Q_PROCESSOR_SPARC_V9 is
defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1701,6 +1776,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for x86 processors. Qt currently
supports two x86 variants: \l Q_PROCESSOR_X86_32 and \l Q_PROCESSOR_X86_64.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_X86_32
@@ -1709,6 +1786,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for 32-bit x86 processors. This
includes all i386, i486, i586, and i686 processors. The \l Q_PROCESSOR_X86
macro is also defined when Q_PROCESSOR_X86_32 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_X86_64
@@ -1717,6 +1796,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for 64-bit x86 processors. This
includes all AMD64, Intel 64, and other x86_64/x64 processors. The \l
Q_PROCESSOR_X86 macro is also defined when Q_PROCESSOR_X86_64 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1838,7 +1919,7 @@ QSysInfo::WinVersion QSysInfo::windowsVersion()
if (winver)
return winver;
#ifdef Q_OS_WINRT
- winver = QSysInfo::WV_WINDOWS8;
+ winver = QSysInfo::WV_WINDOWS8_1;
#else
winver = QSysInfo::WV_NT;
const OSVERSIONINFO osver = winOsVersion();
@@ -1931,9 +2012,479 @@ QSysInfo::WinVersion QSysInfo::windowsVersion()
return winver;
}
+static const char *winVer_helper()
+{
+ switch (int(QSysInfo::WindowsVersion)) {
+ case QSysInfo::WV_NT:
+ return "NT";
+ case QSysInfo::WV_2000:
+ return "2000";
+ case QSysInfo::WV_XP:
+ return "XP";
+ case QSysInfo::WV_2003:
+ return "2003";
+ case QSysInfo::WV_VISTA:
+ return "Vista";
+ case QSysInfo::WV_WINDOWS7:
+ return "7";
+ case QSysInfo::WV_WINDOWS8:
+ return "8";
+ case QSysInfo::WV_WINDOWS8_1:
+ return "8.1";
+
+ case QSysInfo::WV_CE:
+ return "CE";
+ case QSysInfo::WV_CENET:
+ return "CENET";
+ case QSysInfo::WV_CE_5:
+ return "CE5";
+ case QSysInfo::WV_CE_6:
+ return "CE6";
+ }
+ // unknown, future version
+ return 0;
+}
+
const QSysInfo::WinVersion QSysInfo::WindowsVersion = QSysInfo::windowsVersion();
#endif
+#if defined(Q_OS_UNIX)
+# if (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD)
+# define USE_ETC_OS_RELEASE
+# endif
+struct QUnixOSVersion
+{
+ // from uname(2)
+ QString sysName;
+ QString sysNameLower;
+ QString sysRelease;
+
+# if !defined(Q_OS_ANDROID) && !defined(Q_OS_BLACKBERRY) && !defined(Q_OS_MAC)
+ // from /etc/os-release or guessed
+ QString versionIdentifier; // ${ID}_$VERSION_ID
+ QString versionText; // $PRETTY_NAME
+# endif
+};
+
+# ifdef USE_ETC_OS_RELEASE
+static QString unquote(const char *begin, const char *end)
+{
+ if (*begin == '"') {
+ Q_ASSERT(end[-1] == '"');
+ return QString::fromLatin1(begin + 1, end - begin - 2);
+ }
+ return QString::fromLatin1(begin, end - begin);
+}
+
+static bool readEtcOsRelease(QUnixOSVersion &v)
+{
+ // we're avoiding QFile here
+ int fd = qt_safe_open("/etc/os-release", O_RDONLY);
+ if (fd == -1)
+ return false;
+
+ QT_STATBUF sbuf;
+ if (QT_FSTAT(fd, &sbuf) == -1) {
+ qt_safe_close(fd);
+ return false;
+ }
+
+ QString partialIdentifier;
+ QByteArray buffer(sbuf.st_size, Qt::Uninitialized);
+ buffer.resize(qt_safe_read(fd, buffer.data(), sbuf.st_size));
+ qt_safe_close(fd);
+
+ const char *ptr = buffer.constData();
+ const char *end = buffer.constEnd();
+ const char *eol;
+ for ( ; ptr != end; ptr = eol + 1) {
+ static const char idString[] = "ID=";
+ static const char prettyNameString[] = "PRETTY_NAME=";
+ static const char versionIdString[] = "VERSION_ID=";
+
+ // find the end of the line after ptr
+ eol = static_cast<const char *>(memchr(ptr, '\n', end - ptr));
+ if (!eol)
+ eol = end - 1;
+
+ int cmp = strncmp(ptr, idString, strlen(idString));
+ if (cmp < 0)
+ continue;
+ if (cmp == 0) {
+ ptr += strlen(idString);
+ QString id = unquote(ptr, eol);
+ if (partialIdentifier.isNull())
+ partialIdentifier = id;
+ else
+ v.versionIdentifier = id + QLatin1Char('_') + partialIdentifier;
+ continue;
+ }
+
+ cmp = strncmp(ptr, prettyNameString, strlen(prettyNameString));
+ if (cmp < 0)
+ continue;
+ if (cmp == 0) {
+ ptr += strlen(prettyNameString);
+ v.versionText = unquote(ptr, eol);
+ continue;
+ }
+
+ cmp = strncmp(ptr, versionIdString, strlen(versionIdString));
+ if (cmp < 0)
+ continue;
+ if (cmp == 0) {
+ ptr += strlen(versionIdString);
+ QString id = unquote(ptr, eol);
+ if (partialIdentifier.isNull())
+ partialIdentifier = id;
+ else
+ v.versionIdentifier = partialIdentifier + QLatin1Char('_') + id;
+ continue;
+ }
+ }
+
+ return true;
+}
+# endif // USE_ETC_OS_RELEASE
+
+static QUnixOSVersion detectUnixVersion()
+{
+ QUnixOSVersion v;
+ struct utsname u;
+ if (uname(&u) != -1) {
+ v.sysName = QString::fromLatin1(u.sysname);
+ v.sysNameLower = v.sysName.toLower();
+ v.sysRelease = QString::fromLatin1(u.release);
+ } else {
+ v.sysName = QLatin1String("Detection failed");
+ // leave sysNameLower & sysRelease unset
+ }
+
+# if !defined(Q_OS_ANDROID) && !defined(Q_OS_BLACKBERRY) && !defined(Q_OS_MAC)
+# ifdef USE_ETC_OS_RELEASE
+ if (readEtcOsRelease(v))
+ return v;
+# endif
+
+ if (!v.sysNameLower.isEmpty()) {
+ // will produce "qnx_6.5" or "sunos_5.9"
+ v.versionIdentifier = v.sysNameLower + QLatin1Char('_') + v.sysRelease;
+ }
+# endif
+
+ return v;
+}
+#endif // Q_OS_UNIX
+
+
+/*!
+ \since 5.4
+
+ Returns the architecture of the CPU that Qt was compiled for, in text
+ format. Note that this may not match the actual CPU that the application is
+ running on if there's an emulation layer or if the CPU supports multiple
+ architectures (like x86-64 processors supporting i386 applications).
+
+ Values returned by this function are stable and will not change over time,
+ so applications can rely on the returned value as an identifier, except
+ that new CPU types may be added over time.
+
+ Typical returned values are (note: list not exhaustive):
+ \list
+ \li "arm"
+ \li "i386"
+ \li "mips"
+ \li "x86_64"
+ \li "power"
+ \li "sparc"
+ \endlist
+
+ \sa QSysInfo::buildAbi()
+*/
+QString QSysInfo::buildCpuArchitecture()
+{
+ return QStringLiteral(ARCH_PROCESSOR);
+}
+
+/*!
+ \since 5.4
+
+ Returns the full architecture string that Qt was compiled for. This string
+ is useful for identifying different, incompatible builds. For example, it
+ can be used as an identifier to request an upgrade package from a server.
+
+ The values returned from this function are kept stable as follows: the
+ mandatory components of the result will not change in future versions of
+ Qt, but optional suffixes may be added.
+
+ The returned value is composed of three or more parts, separated by dashes
+ ("-"). They are:
+
+ \table
+ \header \li Component \li Value
+ \row \li CPU Architecture \li The same as QSysInfo::buildCpuArchitecture(), such as "arm", "i386", "mips" or "x86_64"
+ \row \li Endianness \li "little_endian" or "big_endian"
+ \row \li Word size \li Whether it's a 32- or 64-bit application. Possible values are:
+ "llp64" (Windows 64-bit), "lp64" (Unix 64-bit), "ilp32" (32-bit)
+ \row \li (Optional) ABI \li Zero or more components identifying different ABIs possible in this architecture.
+ Currently, Qt has optional ABI components for ARM and MIPS processors: one
+ component is the main ABI (such as "eabi", "o32", "n32", "o64"); another is
+ whether the calling convention is using hardware floating point registers ("hardfloat"
+ is present).
+
+ Additionally, if Qt was configured with \c{-qreal float}, the ABI option tag "qreal_float"
+ will be present. If Qt was configured with another type as qreal, that type is present after
+ "qreal_", with all characters other than letters and digits escaped by an underscore, followed
+ by two hex digits. For example, \c{-qreal long double} becomes "qreal_long_20double".
+ \endtable
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+QString QSysInfo::buildAbi()
+{
+#ifdef Q_COMPILER_UNICODE_STRINGS
+ // ARCH_FULL is a concatenation of strings (incl. ARCH_PROCESSOR), which breaks
+ // QStringLiteral on MSVC. Since the concatenation behavior we want is specified
+ // the same C++11 paper as the Unicode strings, we'll use that macro and hope
+ // that Microsoft implements the new behavior when they add support for Unicode strings.
+ return QStringLiteral(ARCH_FULL);
+#else
+ return QLatin1String(ARCH_FULL);
+#endif
+}
+
+static QString unknownText()
+{
+ return QStringLiteral("unknown");
+}
+
+/*!
+ \since 5.4
+
+ Returns the type of the operating system Qt was compiled for. It's also the
+ operating system the application is running on, unless the host operating
+ system is running a form of compatibility layer.
+
+ Values returned by this function are stable and will not change over time,
+ so applications can rely on the returned value as an identifier, except
+ that new OS types may be added over time.
+
+ \b{Android note}: this function returns "android" for Linux systems running
+ Android userspace, notably when using the Bionic library. For all other
+ Linux systems, regardless of C library being used, it returns "linux".
+
+ \b{BlackBerry note}: this function returns "blackberry" for QNX systems
+ running the BlackBerry userspace, but "qnx" for all other QNX-based
+ systems.
+
+ \b{Darwin, OS X and iOS note}: this function returns "osx" for OS X
+ systems, "ios" for iOS systems and "darwin" in case the system could not be
+ determined.
+
+ \b{FreeBSD note}: this function returns "freebsd" for systems running the
+ FreeBSD kernel, regardless of whether the userspace runs the traditional
+ BSD code or whether it's the GNU system (Debian GNU/kFreeBSD).
+
+ \sa QFileSelector, prettyOsName()
+*/
+QString QSysInfo::osType()
+{
+ // similar, but not identical to QFileSelectorPrivate::platformSelectors
+#if defined(Q_OS_WINPHONE)
+ return QStringLiteral("winphone");
+#elif defined(Q_OS_WINRT)
+ return QStringLiteral("winrt");
+#elif defined(Q_OS_WINCE)
+ return QStringLiteral("wince");
+#elif defined(Q_OS_WIN)
+ return QStringLiteral("windows");
+
+#elif defined(Q_OS_BLACKBERRY)
+ return QStringLiteral("blackberry");
+#elif defined(Q_OS_QNX)
+ return QStringLiteral("qnx");
+
+#elif defined(Q_OS_ANDROID)
+ return QStringLiteral("android");
+#elif defined(Q_OS_LINUX)
+ return QStringLiteral("linux");
+
+#elif defined(Q_OS_IOS)
+ return QStringLiteral("ios");
+#elif defined(Q_OS_OSX)
+ return QStringLiteral("osx");
+#elif defined(Q_OS_DARWIN)
+ return QStringLiteral("darwin");
+
+#elif defined(Q_OS_FREEBSD_KERNEL)
+ return QStringLiteral("freebsd");
+#elif defined(Q_OS_UNIX)
+ QUnixOSVersion unixOsVersion = detectUnixVersion();
+ if (!unixOsVersion.sysNameLower.isEmpty())
+ return unixOsVersion.sysNameLower;
+#endif
+ return unknownText();
+}
+
+/*!
+ \since 5.4
+
+ Returns the version of the host operating system in string form. For both
+ OS X and iOS systems, this returns just the main OS version, such as "7.1",
+ "10.6" and "10.7". For Windows systems, this returns the same types
+ detected by winVersion(), without the word "Windows". For Linux-based
+ systems, it will try to determine the Linux distribution and version.
+
+ If the version could not be determined, this function returns "unknown" for
+ Windows and a combination of the osType() and osKernelVersion() for Unix
+ systems.
+
+ \sa prettyOsName(), osKernelVersion()
+*/
+QString QSysInfo::osVersion()
+{
+#if defined(Q_OS_IOS)
+ int major = (int(MacintoshVersion) >> 4) & 0xf;
+ int minor = int(MacintoshVersion) & 0xf;
+ if (Q_LIKELY(major < 10 && minor < 10)) {
+ char buf[4] = { char(major + '0'), '.', char(minor + '0'), '\0' };
+ return QString::fromLatin1(buf, 3);
+ }
+ return QString::number(major) + QLatin1Char('.') + QString::number(minor);
+#elif defined(Q_OS_OSX)
+ int minor = int(MacintoshVersion) - 2; // we're not running on Mac OS 9
+ Q_ASSERT(minor < 100);
+ char buf[] = "10.0\0";
+ if (Q_LIKELY(minor < 10)) {
+ buf[3] += minor;
+ } else {
+ buf[3] += minor / 10;
+ buf[4] = '0' + minor % 10;
+ }
+ return QString::fromLatin1(buf);
+#elif defined(Q_OS_WIN)
+ const char *version = winVer_helper();
+ if (version)
+ return QString::fromLatin1(version).toLower();
+ // fall through
+
+// Android and Blackberry should not fall through to the Unix code
+#elif defined(Q_OS_ANDROID)
+ // TBD
+#elif defined(Q_OS_BLACKBERRY)
+ deviceinfo_details_t *deviceInfo;
+ if (deviceinfo_get_details(&deviceInfo) == BPS_SUCCESS) {
+ QString bbVersion = QString::fromLatin1(deviceinfo_details_get_device_os_version(deviceInfo));
+ deviceinfo_free_details(&deviceInfo);
+ return bbVersion;
+ }
+#elif defined(Q_OS_UNIX)
+ QUnixOSVersion unixOsVersion = detectUnixVersion();
+ if (!unixOsVersion.versionIdentifier.isEmpty())
+ return unixOsVersion.versionIdentifier;
+#endif
+
+ // fallback
+ return unknownText();
+}
+
+/*!
+ \since 5.4
+
+ Returns a prettier form of osVersion(), containing other information like
+ the operating system type, codenames and other information. The result of
+ this function is suitable for displaying to the user, but not for long-term
+ storage, as the string may change with updates to Qt.
+
+ \sa osType(), osVersion()
+*/
+QString QSysInfo::prettyOsName()
+{
+#if defined(Q_OS_IOS)
+ return QLatin1String("iOS ") + osVersion();
+#elif defined(Q_OS_OSX)
+ // get the known codenames
+ const char *basename = 0;
+ switch (int(MacintoshVersion)) {
+ case MV_CHEETAH:
+ case MV_PUMA:
+ case MV_JAGUAR:
+ case MV_PANTHER:
+ case MV_TIGER:
+ // This version of Qt does not run on those versions of OS X
+ // so this case label will never be reached
+ Q_UNREACHABLE();
+ break;
+ case MV_LEOPARD:
+ basename = "Mac OS X Leopard (";
+ break;
+ case MV_SNOWLEOPARD:
+ basename = "Mac OS X Snow Leopard (";
+ break;
+ case MV_LION:
+ basename = "Mac OS X Lion (";
+ break;
+ case MV_MOUNTAINLION:
+ basename = "OS X Mountain Lion (";
+ break;
+ case MV_MAVERICKS:
+ basename = "OS X Mavericks (";
+ break;
+ case MV_YOSEMITE:
+ basename = "OS X Yosemite (";
+ break;
+ }
+ if (basename)
+ return QLatin1String(basename) + osVersion() + QLatin1Char(')');
+
+ // a future version of OS X
+ return QLatin1String("OS X ") + osVersion();
+#elif defined(Q_OS_WINPHONE)
+ return QLatin1String("Windows Phone ") + QLatin1String(winVer_helper());
+#elif defined(Q_OS_WIN)
+ return QLatin1String("Windows ") + QLatin1String(winVer_helper());
+#elif defined(Q_OS_ANDROID)
+ return QLatin1String("Android ") + osVersion();
+#elif defined(Q_OS_BLACKBERRY)
+ return QLatin1String("BlackBerry ") + osVersion();
+#elif defined(Q_OS_UNIX)
+ QUnixOSVersion unixOsVersion = detectUnixVersion();
+ if (unixOsVersion.versionText.isEmpty())
+ return unixOsVersion.sysName;
+ else
+ return unixOsVersion.sysName + QLatin1String(" (") + unixOsVersion.versionText + QLatin1Char(')');
+#else
+ return unknownText();
+#endif
+}
+
+/*!
+ \since 5.4
+
+ Returns the release version of the operating system. On Windows, it returns
+ the version of the kernel, which does not match the version number of the
+ OS (e.g., Windows 8 has NT kernel version 6.2). On Unix systems, including
+ Android, BlackBerry and OS X, it returns the same as the \c{uname -r}
+ command would return.
+
+ If the version could not be determined, this function may return an empty
+ string.
+
+ \sa osVersion(), prettyOsName()
+*/
+QString QSysInfo::osKernelVersion()
+{
+#ifdef Q_OS_WINRT
+ // TBD
+ return QString();
+#elif defined(Q_OS_WIN)
+ const OSVERSIONINFO osver = winOsVersion();
+ return QString::number(int(osver.dwMajorVersion)) + QLatin1Char('.') + QString::number(int(osver.dwMinorVersion))
+ + QLatin1Char('.') + QString::number(int(osver.dwBuildNumber));
+#else
+ return detectUnixVersion().sysRelease;
+#endif
+}
/*!
\macro void Q_ASSERT(bool test)
@@ -2815,17 +3366,31 @@ int qrand()
qPrintable() is used. This is because the array returned by
QString::toLocal8Bit() will fall out of scope.
+ \note qDebug(), qWarning(), qCritical(), qFatal() expect %s
+ arguments to be UTF-8 encoded, while qPrintable() converts to
+ local 8-bit encoding. Therefore qUtf8Printable() should be used
+ for logging strings instead of qPrintable().
+
+ \sa qUtf8Printable()
+*/
+
+/*!
+ \macro const char *qUtf8Printable(const QString &str)
+ \relates <QtGlobal>
+ \since 5.4
+
+ Returns \a str as a \c{const char *}. This is equivalent to
+ \a{str}.toUtf8().constData().
+
+ The char pointer will be invalid after the statement in which
+ qUtf8Printable() is used. This is because the array returned by
+ QString::toUtf8() will fall out of scope.
+
Example:
\snippet code/src_corelib_global_qglobal.cpp 37
- \note qDebug(), qWarning(), qCritical(), qFatal() expect %s
- arguments to be UTF-8 encoded, while qPrintable() converts to
- local 8-bit encoding. Therefore using qPrintable for logging
- strings is only safe if the argument contains only ASCII
- characters.
-
- \sa qDebug(), qWarning(), qCritical(), qFatal()
+ \sa qPrintable(), qDebug(), qWarning(), qCritical(), qFatal()
*/
/*!
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 255eb6c00b..5210d80953 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -45,11 +45,11 @@
#include <stddef.h>
-#define QT_VERSION_STR "5.3.2"
+#define QT_VERSION_STR "5.4.0"
/*
QT_VERSION is (major << 16) + (minor << 8) + patch.
*/
-#define QT_VERSION 0x050302
+#define QT_VERSION 0x050400
/*
can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0))
*/
@@ -649,6 +649,10 @@ inline void qUnused(T &x) { (void)x; }
# define qPrintable(string) QString(string).toLocal8Bit().constData()
#endif
+#ifndef qUtf8Printable
+# define qUtf8Printable(string) QString(string).toUtf8().constData()
+#endif
+
class QString;
Q_CORE_EXPORT QString qt_error_string(int errorCode = -1);
@@ -865,22 +869,37 @@ Q_CORE_EXPORT void qFreeAligned(void *ptr);
# endif
#endif
-#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_RVCT)
-/* make use of typeof-extension */
+#if defined(Q_COMPILER_DECLTYPE) || (defined(Q_CC_GNU) && !defined(Q_CC_RVCT))
+/* make use of decltype or GCC's __typeof__ extension */
template <typename T>
class QForeachContainer {
public:
- inline QForeachContainer(const T& t) : c(t), brk(0), i(c.begin()), e(c.end()) { }
+ inline QForeachContainer(const T& t) : c(t), i(c.begin()), e(c.end()), control(1) { }
const T c;
- int brk;
typename T::const_iterator i, e;
+ int control;
};
-#define Q_FOREACH(variable, container) \
-for (QForeachContainer<__typeof__((container))> _container_((container)); \
- !_container_.brk && _container_.i != _container_.e; \
- __extension__ ({ ++_container_.brk; ++_container_.i; })) \
- for (variable = *_container_.i;; __extension__ ({--_container_.brk; break;}))
+# ifdef Q_COMPILER_DECLTYPE
+# define QT_FOREACH_DECLTYPE(x) typename QtPrivate::remove_reference<decltype(x)>::type
+# else
+# define QT_FOREACH_DECLTYPE(x) __typeof__((x))
+# endif
+
+// Explanation of the control word:
+// - it's initialized to 1
+// - that means both the inner and outer loops start
+// - if there were no breaks, at the end of the inner loop, it's set to 0, which
+// causes it to exit (the inner loop is run exactly once)
+// - at the end of the outer loop, it's inverted, so it becomes 1 again, allowing
+// the outer loop to continue executing
+// - if there was a break inside the inner loop, it will exit with control still
+// set to 1; in that case, the outer loop will invert it to 0 and will exit too
+# define Q_FOREACH(variable, container) \
+for (QForeachContainer<QT_FOREACH_DECLTYPE(container)> _container_((container)); \
+ _container_.control && _container_.i != _container_.e; \
+ ++_container_.i, _container_.control ^= 1) \
+ for (variable = *_container_.i; _container_.control; _container_.control = 0)
#else
diff --git a/src/corelib/global/qglobalstatic.h b/src/corelib/global/qglobalstatic.h
index ad39452cf4..e9330a4b9e 100644
--- a/src/corelib/global/qglobalstatic.h
+++ b/src/corelib/global/qglobalstatic.h
@@ -57,7 +57,7 @@ enum GuardValues {
};
}
-#if defined(QT_NO_THREAD) || (defined(Q_CC_GNU) && !defined(Q_OS_MAC))
+#if defined(QT_NO_THREAD) || defined(Q_COMPILER_THREADSAFE_STATICS)
// some compilers support thread-safe statics
// The IA-64 C++ ABI requires this, so we know that all GCC versions since 3.4
// support it. C++11 also requires this behavior.
diff --git a/src/corelib/global/qhooks.cpp b/src/corelib/global/qhooks.cpp
new file mode 100644
index 0000000000..0032e87401
--- /dev/null
+++ b/src/corelib/global/qhooks.cpp
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Volker Krause <volker.krause@kdab.com>
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhooks_p.h"
+
+QT_BEGIN_NAMESPACE
+
+// Only add to the end, and bump version if you do.
+quintptr Q_CORE_EXPORT qtHookData[] = {
+ 1, // hook data version
+ QHooks::LastHookIndex, // size of qtHookData
+ QT_VERSION,
+
+ // AddQObject, void(*)(QObject*), called for every constructed QObject
+ // Note: this is called from the QObject constructor, ie. the sub-class
+ // constructors haven't run yet.
+ 0,
+
+ // RemoveQObject, void(*)(QObject*), called for every destructed QObject
+ // Note: this is called from the QObject destructor, ie. the object
+ // you get as an argument is already largely invalid.
+ 0,
+
+ // Startup, void(*)(), called once QCoreApplication is operational
+ 0
+};
+
+Q_STATIC_ASSERT(QHooks::LastHookIndex == sizeof(qtHookData) / sizeof(qtHookData[0]));
+
+QT_END_NAMESPACE
+
diff --git a/src/gui/kernel/qkeymapper_qpa.cpp b/src/corelib/global/qhooks_p.h
index 3966909db1..012f91fa66 100644
--- a/src/gui/kernel/qkeymapper_qpa.cpp
+++ b/src/corelib/global/qhooks_p.h
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Volker Krause <volker.krause@kdab.com>
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtGui module of the Qt Toolkit.
+** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,44 +39,36 @@
**
****************************************************************************/
-#include "qkeymapper_p.h"
-#include <qdebug.h>
-#include <private/qevent_p.h>
-#include <private/qlocale_p.h>
-#include <private/qguiapplication_p.h>
-#include <qpa/qplatformintegration.h>
-QT_BEGIN_NAMESPACE
+#ifndef QHOOKS_H
+#define QHOOKS_H
-QT_USE_NAMESPACE
+#include <QtCore/qglobal.h>
+QT_BEGIN_NAMESPACE
-QKeyMapperPrivate::QKeyMapperPrivate()
-{
- keyboardInputLocale = QLocale::system();
- keyboardInputDirection = keyboardInputLocale.textDirection();
-}
+class QObject;
-QKeyMapperPrivate::~QKeyMapperPrivate()
-{
- // clearMappings();
-}
+namespace QHooks {
-void QKeyMapperPrivate::clearMappings()
-{
-}
+enum HookIndex {
+ HookDataVersion = 0,
+ HookDataSize = 1,
+ QtVersion = 2,
+ AddQObject = 3,
+ RemoveQObject = 4,
+ Startup = 5,
+ LastHookIndex
+};
-QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent *e)
-{
- QList<int> result = QGuiApplicationPrivate::platformIntegration()->possibleKeys(e);
- if (!result.isEmpty())
- return result;
+typedef void(*AddQObjectCallback)(QObject*);
+typedef void(*RemoveQObjectCallback)(QObject*);
+typedef void(*StartupCallback)();
- if (e->key() && (e->key() != Qt::Key_unknown))
- result << int(e->key() + e->modifiers());
- else if (!e->text().isEmpty())
- result << int(e->text().at(0).unicode() + e->modifiers());
- return result;
}
+extern quintptr Q_CORE_EXPORT qtHookData[];
+
QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp
index 174c1d0d8d..f2ebeb6a03 100644
--- a/src/corelib/global/qlibraryinfo.cpp
+++ b/src/corelib/global/qlibraryinfo.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Intel Corporation
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -67,6 +68,7 @@ QString qt_libraryInfoFile()
#endif
#include "qconfig.cpp"
+#include "archdetect.cpp"
QT_BEGIN_NAMESPACE
@@ -255,7 +257,37 @@ QLibraryInfo::buildDate()
}
#endif //QT_NO_DATESTRING
-#if defined(Q_CC_CLANG) // must be before GNU, because clang claims to be GNU too
+#if defined(Q_CC_INTEL) // must be before GNU, Clang and MSVC because ICC/ICL claim to be them
+# ifdef __INTEL_CLANG_COMPILER
+# define ICC_COMPAT "Clang"
+# elif defined(__INTEL_MS_COMPAT_LEVEL)
+# define ICC_COMPAT "Microsoft"
+# elif defined(__GNUC__)
+# define ICC_COMPAT "GCC"
+# else
+# define ICC_COMPAT "no"
+# endif
+# if __INTEL_COMPILER == 1300
+# define ICC_VERSION "13.0"
+# elif __INTEL_COMPILER == 1310
+# define ICC_VERSION "13.1"
+# elif __INTEL_COMPILER == 1400
+# define ICC_VERSION "14.0"
+# elif __INTEL_COMPILER == 1500
+# define ICC_VERSION "15.0"
+# else
+# define ICC_VERSION QT_STRINGIFY(__INTEL_COMPILER)
+# endif
+# ifdef __INTEL_COMPILER_UPDATE
+# define COMPILER_STRING "Intel(R) C++ " ICC_VERSION "." QT_STRINGIFY(__INTEL_COMPILER_UPDATE) \
+ " build " QT_STRINGIFY(__INTEL_COMPILER_BUILD_DATE) " [" \
+ ICC_COMPAT " compatibility]"
+# else
+# define COMPILER_STRING "Intel(R) C++ " ICC_VERSION \
+ " build " QT_STRINGIFY(__INTEL_COMPILER_BUILD_DATE) " [" \
+ ICC_COMPAT " compatibility]"
+# endif
+#elif defined(Q_CC_CLANG) // must be before GNU, because clang claims to be GNU too
# ifdef __apple_build_version__ // Apple clang has other version numbers
# define COMPILER_STRING "Clang " __clang_version__ " (Apple)"
# else
@@ -273,11 +305,22 @@ QLibraryInfo::buildDate()
# elif _MSC_VER < 1900
# define COMPILER_STRING "MSVC 2013"
# else
-# define COMPILER_STRING "MSVC <unknown version>"
+# define COMPILER_STRING "MSVC _MSC_VER " QT_STRINGIFY(_MSC_VER)
# endif
#else
# define COMPILER_STRING "<unknown compiler>"
#endif
+#ifdef QT_NO_DEBUG
+# define DEBUG_STRING " release"
+#else
+# define DEBUG_STRING " debug"
+#endif
+#ifdef QT_SHARED
+# define SHARED_STRING " shared (dynamic)"
+#else
+# define SHARED_STRING " static"
+#endif
+#define QT_BUILD_STR "Qt " QT_VERSION_STR " (" ARCH_FULL SHARED_STRING DEBUG_STRING " build; by " COMPILER_STRING ")"
/*!
Returns a string describing how this version of Qt was built.
@@ -289,21 +332,7 @@ QLibraryInfo::buildDate()
const char *QLibraryInfo::build() Q_DECL_NOTHROW
{
- static const char data[] = "Qt " QT_VERSION_STR " (" __DATE__ ", "
- COMPILER_STRING ", "
-#if QT_POINTER_SIZE == 4
- "32"
-#else
- "64"
-#endif
- " bit, "
-#ifdef QT_NO_DEBUG
- "release"
-#else
- "debug"
-#endif
- " build)";
- return data;
+ return QT_BUILD_STR;
}
/*!
@@ -590,7 +619,7 @@ extern const char qt_core_interpreter[] __attribute__((section(".interp")))
extern "C" void qt_core_boilerplate();
void qt_core_boilerplate()
{
- printf("This is the QtCore library version " QT_VERSION_STR "\n"
+ printf("This is the QtCore library version " QT_BUILD_STR "\n"
"Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).\n"
"Contact: http://www.qt-project.org/legal\n"
"\n"
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index ca0fb1bb23..847b7cb4c0 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -48,6 +49,8 @@
#include "qmutex.h"
#include "qloggingcategory.h"
#ifndef QT_BOOTSTRAPPED
+#include "qelapsedtimer.h"
+#include "qdatetime.h"
#include "qcoreapplication.h"
#include "qthread.h"
#include "private/qloggingregistry_p.h"
@@ -70,6 +73,22 @@
# include <unistd.h>
#endif
+#if !defined QT_NO_REGULAREXPRESSION && !defined(QT_BOOTSTRAPPED)
+#ifdef __has_include
+#if __has_include(<cxxabi.h>) && __has_include(<execinfo.h>)
+#define QLOGGING_HAVE_BACKTRACE
+#endif
+#elif defined(__GLIBCXX__) && defined(__GLIBC__) // (because older version of gcc don't have __has_include)
+#define QLOGGING_HAVE_BACKTRACE
+#endif
+
+#ifdef QLOGGING_HAVE_BACKTRACE
+#include <qregularexpression.h>
+#include <cxxabi.h>
+#include <execinfo.h>
+#endif
+#endif
+
#include <stdio.h>
QT_BEGIN_NAMESPACE
@@ -171,89 +190,15 @@ static inline void convert_to_wchar_t_elided(wchar_t *d, size_t space, const cha
}
#endif
-#if !defined(QT_NO_EXCEPTIONS)
-/*!
- \internal
- Uses a local buffer to output the message. Not locale safe + cuts off
- everything after character 255, but will work in out of memory situations.
- Stop the execution afterwards.
-*/
-static void qEmergencyOut(QtMsgType msgType, const char *msg, va_list ap) Q_DECL_NOEXCEPT
-{
- char emergency_buf[256] = { '\0' };
- emergency_buf[sizeof emergency_buf - 1] = '\0';
-#if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB) && (defined(Q_OS_WINCE) || defined(Q_OS_WINRT)) \
- || defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)
- wchar_t emergency_bufL[sizeof emergency_buf];
-#endif
-
- if (msg)
- qvsnprintf(emergency_buf, sizeof emergency_buf - 1, msg, ap);
-
-#if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB)
-# if defined(Q_OS_WINCE) || defined(Q_OS_WINRT)
- convert_to_wchar_t_elided(emergency_bufL, sizeof emergency_buf, emergency_buf);
- OutputDebugStringW(emergency_bufL);
-# else
- if (qWinLogToStderr()) {
- fprintf(stderr, "%s\n", emergency_buf);
- fflush(stderr);
- } else {
- OutputDebugStringA(emergency_buf);
- }
-# endif
-#else
- fprintf(stderr, "%s\n", emergency_buf);
- fflush(stderr);
-#endif
-
- if (isFatal(msgType)) {
-#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)
- // get the current report mode
- int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);
- _CrtSetReportMode(_CRT_ERROR, reportMode);
-# ifndef Q_OS_WINCE // otherwise already converted to wchar_t above
- convert_to_wchar_t_elided(emergency_bufL, sizeof emergency_buf, emergency_buf);
-# endif
- int ret = _CrtDbgReportW(_CRT_ERROR, _CRT_WIDE(__FILE__), __LINE__,
- _CRT_WIDE(QT_VERSION_STR),
- emergency_bufL);
- if (ret == 1)
- _CrtDbgBreak();
-#endif
-
-#if (defined(Q_OS_UNIX) || defined(Q_CC_MINGW))
- abort(); // trap; generates core dump
-#else
- exit(1); // goodbye cruel world
-#endif
- }
-}
-#endif
-
/*!
\internal
*/
static void qt_message(QtMsgType msgType, const QMessageLogContext &context, const char *msg,
va_list ap, QString &buf)
{
-#if !defined(QT_NO_EXCEPTIONS)
- if (std::uncaught_exception()) {
- qEmergencyOut(msgType, msg, ap);
- return;
- }
-#endif
- if (msg) {
- QT_TRY {
- buf = QString().vsprintf(msg, ap);
- } QT_CATCH(const std::bad_alloc &) {
-#if !defined(QT_NO_EXCEPTIONS)
- qEmergencyOut(msgType, msg, ap);
- // don't rethrow - we use qWarning and friends in destructors.
- return;
-#endif
- }
- }
+
+ if (msg)
+ buf = QString().vsprintf(msg, ap);
qt_message_print(msgType, context, buf);
}
@@ -834,6 +779,8 @@ static const char functionTokenC[] = "%{function}";
static const char pidTokenC[] = "%{pid}";
static const char appnameTokenC[] = "%{appname}";
static const char threadidTokenC[] = "%{threadid}";
+static const char timeTokenC[] = "%{time"; //not a typo: this command has arguments
+static const char backtraceTokenC[] = "%{backtrace"; //ditto
static const char ifCategoryTokenC[] = "%{if-category}";
static const char ifDebugTokenC[] = "%{if-debug}";
static const char ifWarningTokenC[] = "%{if-warning}";
@@ -854,9 +801,18 @@ struct QMessagePattern {
// 0 terminated arrays of literal tokens / literal or placeholder tokens
const char **literals;
const char **tokens;
+ QString timeFormat;
+#ifdef QLOGGING_HAVE_BACKTRACE
+ int backtraceDepth;
+ QString backtraceSeparator;
+#endif
bool fromEnvironment;
static QBasicMutex mutex;
+#ifndef QT_BOOTSTRAPPED
+ QElapsedTimer timer;
+ QDateTime startTime;
+#endif
};
QBasicMutex QMessagePattern::mutex;
@@ -864,8 +820,18 @@ QBasicMutex QMessagePattern::mutex;
QMessagePattern::QMessagePattern()
: literals(0)
, tokens(0)
+#ifdef QLOGGING_HAVE_BACKTRACE
+ , backtraceDepth(5)
+ , backtraceSeparator(QLatin1Char('|'))
+#endif
, fromEnvironment(false)
+#ifndef QT_BOOTSTRAPPED
+ , startTime(QDateTime::currentDateTime())
+#endif
{
+#ifndef QT_BOOTSTRAPPED
+ timer.start();
+#endif
const QString envPattern = QString::fromLocal8Bit(qgetenv("QT_MESSAGE_PATTERN"));
if (envPattern.isEmpty()) {
setPattern(QLatin1String(defaultPattern));
@@ -953,6 +919,31 @@ void QMessagePattern::setPattern(const QString &pattern)
tokens[i] = appnameTokenC;
else if (lexeme == QLatin1String(threadidTokenC))
tokens[i] = threadidTokenC;
+ else if (lexeme.startsWith(QLatin1String(timeTokenC))) {
+ tokens[i] = timeTokenC;
+ int spaceIdx = lexeme.indexOf(QChar::fromLatin1(' '));
+ if (spaceIdx > 0)
+ timeFormat = lexeme.mid(spaceIdx + 1, lexeme.length() - spaceIdx - 2);
+ } else if (lexeme.startsWith(QLatin1String(backtraceTokenC))) {
+#ifdef QLOGGING_HAVE_BACKTRACE
+ tokens[i] = backtraceTokenC;
+ QRegularExpression depthRx(QStringLiteral(" depth=(?|\"([^\"]*)\"|([^ }]*))"));
+ QRegularExpression separatorRx(QStringLiteral(" separator=(?|\"([^\"]*)\"|([^ }]*))"));
+ QRegularExpressionMatch m = depthRx.match(lexeme);
+ if (m.hasMatch()) {
+ int depth = m.capturedRef(1).toInt();
+ if (depth <= 0)
+ error += QStringLiteral("QT_MESSAGE_PATTERN: %{backtrace} depth must be a number greater than 0\n");
+ else
+ backtraceDepth = depth;
+ }
+ m = separatorRx.match(lexeme);
+ if (m.hasMatch())
+ backtraceSeparator = m.captured(1);
+#else
+ error += QStringLiteral("QT_MESSAGE_PATTERN: %{backtrace} is not supported by this Qt build\n");
+#endif
+ }
#define IF_TOKEN(LEVEL) \
else if (lexeme == QLatin1String(LEVEL)) { \
@@ -1122,6 +1113,64 @@ Q_CORE_EXPORT QString qMessageFormatString(QtMsgType type, const QMessageLogCont
} else if (token == threadidTokenC) {
message.append(QLatin1String("0x"));
message.append(QString::number(qlonglong(QThread::currentThread()->currentThread()), 16));
+#ifdef QLOGGING_HAVE_BACKTRACE
+ } else if (token == backtraceTokenC) {
+ QVarLengthArray<void*, 32> buffer(15 + pattern->backtraceDepth);
+ int n = backtrace(buffer.data(), buffer.size());
+ if (n > 0) {
+ QScopedPointer<char*, QScopedPointerPodDeleter> strings(backtrace_symbols(buffer.data(), n));
+ int numberPrinted = 0;
+ for (int i = 0; i < n && numberPrinted < pattern->backtraceDepth; ++i) {
+ QString trace = QString::fromLatin1(strings.data()[i]);
+ // The results of backtrace_symbols looks like this:
+ // /lib/libc.so.6(__libc_start_main+0xf3) [0x4a937413]
+ // The offset and function name are optional.
+ // This regexp tries to extract the librry name (without the path) and the function name.
+ // This code is protected by QMessagePattern::mutex so it is thread safe on all compilers
+ static QRegularExpression rx(QStringLiteral("^(?:[^(]*/)?([^(/]+)\\(([^+]*)(?:[\\+[a-f0-9x]*)?\\) \\[[a-f0-9x]*\\]$"),
+ QRegularExpression::OptimizeOnFirstUsageOption);
+
+ QRegularExpressionMatch m = rx.match(trace);
+ if (m.hasMatch()) {
+ // skip the trace from QtCore that are because of the qDebug itself
+ QString library = m.captured(1);
+ QString function = m.captured(2);
+ if (!numberPrinted && library.contains(QLatin1String("Qt5Core"))
+ && (function.isEmpty() || function.contains(QLatin1String("Message"), Qt::CaseInsensitive)
+ || function.contains(QLatin1String("QDebug")))) {
+ continue;
+ }
+
+ if (function.startsWith(QLatin1String("_Z"))) {
+ QScopedPointer<char, QScopedPointerPodDeleter> demangled(
+ abi::__cxa_demangle(function.toUtf8(), 0, 0, 0));
+ if (demangled)
+ function = QString::fromUtf8(qCleanupFuncinfo(demangled.data()));
+ }
+
+ if (numberPrinted > 0)
+ message.append(pattern->backtraceSeparator);
+
+ if (function.isEmpty())
+ message += QLatin1Char('?') + library + QLatin1Char('?');
+ else
+ message += function;
+
+ } else {
+ if (numberPrinted == 0)
+ continue;
+ message += pattern->backtraceSeparator + QLatin1String("???");
+ }
+ numberPrinted++;
+ }
+ }
+#endif
+ } else if (token == timeTokenC) {
+ quint64 ms = pattern->timer.elapsed();
+ if (pattern->timeFormat.isEmpty())
+ message.append(QString().sprintf("%6d.%03d", uint(ms / 1000), uint(ms % 1000)));
+ else
+ message.append(pattern->startTime.addMSecs(ms).toString(pattern->timeFormat));
#endif
} else if (token == ifCategoryTokenC) {
if (!context.category || (strcmp(context.category, "default") == 0))
@@ -1503,6 +1552,17 @@ void qErrnoWarning(int code, const char *msg, ...)
\row \li \c %{pid} \li QCoreApplication::applicationPid()
\row \li \c %{threadid} \li ID of current thread
\row \li \c %{type} \li "debug", "warning", "critical" or "fatal"
+ \row \li \c %{time} \li time of the message, in seconds since the process started
+ \row \li \c %{time format} \li system time when the message occurred, formatted by
+ passing the \c format to \l QDateTime::toString()
+ \row \li \c{%{backtrace [depth=N] [separator="..."]}} \li A backtrace with the number of frames
+ specified by the optional \c depth parameter (defaults to 5), and separated by the optional
+ \c separator parameter (defaults to "|").
+ This expansion is available only on some platforms (currently only platfoms using glibc).
+ Names are only known for exported functions. If you want to see the name of every function
+ in your application, use \c{QMAKE_LFLAGS += -rdynamic}.
+ When reading backtraces, take into account that frames might be missing due to inlining or
+ tail call optimization.
\endtable
You can also use conditionals on the type of the message using \c %{if-debug},
@@ -1514,7 +1574,7 @@ void qErrnoWarning(int code, const char *msg, ...)
Example:
\code
- QT_MESSAGE_PATTERN="[%{if-debug}D%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{file}:%{line} - %{message}"
+ QT_MESSAGE_PATTERN="[%{time yyyyMMdd h:mm:ss.zzz t} %{if-debug}D%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{file}:%{line} - %{message}"
\endcode
The default \a pattern is "%{if-category}%{category}: %{endif}%{message}".
diff --git a/src/corelib/global/qlogging.h b/src/corelib/global/qlogging.h
index 6ebffa3ba1..043f799414 100644
--- a/src/corelib/global/qlogging.h
+++ b/src/corelib/global/qlogging.h
@@ -65,9 +65,9 @@ class QMessageLogContext
{
Q_DISABLE_COPY(QMessageLogContext)
public:
- Q_DECL_CONSTEXPR QMessageLogContext() : version(1), line(0), file(0), function(0), category(0) {}
+ Q_DECL_CONSTEXPR QMessageLogContext() : version(2), line(0), file(0), function(0), category(0) {}
Q_DECL_CONSTEXPR QMessageLogContext(const char *fileName, int lineNumber, const char *functionName, const char *categoryName)
- : version(1), line(lineNumber), file(fileName), function(functionName), category(categoryName) {}
+ : version(2), line(lineNumber), file(fileName), function(functionName), category(categoryName) {}
void copy(const QMessageLogContext &logContext);
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index 839d352d36..3ec859dbb7 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -521,6 +521,7 @@ public:
AA_ForceRasterWidgets = 14,
AA_UseDesktopOpenGL = 15,
AA_UseOpenGLES = 16,
+ AA_UseSoftwareOpenGL = 17,
// Add new attributes before this line
AA_AttributeCount
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index a47f2e2945..be569bcffe 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -168,14 +168,26 @@
\value AA_ForceRasterWidgets Make top-level widgets use pure raster surfaces,
and do not support non-native GL-based child widgets.
- \value AA_UseDesktopOpenGL Forces the usage of the desktop OpenGL on
- platforms that use dynamic loading of the OpenGL implementation.
+ \value AA_UseDesktopOpenGL Forces the usage of desktop OpenGL (for example,
+ \e opengl32.dll or \e libGL.so) on platforms that use dynamic loading
+ of the OpenGL implementation.
This value has been added in Qt 5.3.
- \value AA_UseOpenGLES Forces the usage of OpenGL ES 2.0 on platforms that
- use dynamic loading of the OpenGL implementation.
+ \value AA_UseOpenGLES Forces the usage of OpenGL ES 2.0 or higher on
+ platforms that use dynamic loading of the OpenGL implementation.
This value has been added in Qt 5.3.
+ \value AA_UseSoftwareOpenGL Forces the usage of a software based OpenGL
+ implementation on platforms that use dynamic loading of the OpenGL
+ implementation. This will typically be a patched build of
+ \l{http://www.mesa3d.org/llvmpipe.html}{Mesa llvmpipe}, providing
+ OpenGL 2.1. The value may have no effect if no such OpenGL
+ implementation is available. The default name of this library is
+ QtSoftwareOpenGL.dll and can be overridden by setting the environment
+ variable \e QT_OPENGL_DLL. See the platform-specific pages, for
+ instance \l{Qt for Windows}, for more information. This value has
+ been added in Qt 5.4.
+
The following values are obsolete:
\value AA_ImmediateWidgetCreation This attribute is no longer fully
diff --git a/src/corelib/global/qnumeric.cpp b/src/corelib/global/qnumeric.cpp
index 7d8bd8c3c6..21d0209dd7 100644
--- a/src/corelib/global/qnumeric.cpp
+++ b/src/corelib/global/qnumeric.cpp
@@ -140,6 +140,7 @@ static inline quint32 f2i(float f)
\endcode
\sa qFuzzyCompare()
+ \since 5.2
\relates <QtGlobal>
*/
Q_CORE_EXPORT quint32 qFloatDistance(float a, float b)
@@ -197,6 +198,7 @@ static inline quint64 d2i(double d)
\sa qFuzzyCompare()
+ \since 5.2
\relates <QtGlobal>
*/
Q_CORE_EXPORT quint64 qFloatDistance(double a, double b)
diff --git a/src/corelib/global/qsysinfo.h b/src/corelib/global/qsysinfo.h
index 38735c12de..45d54c3873 100644
--- a/src/corelib/global/qsysinfo.h
+++ b/src/corelib/global/qsysinfo.h
@@ -136,6 +136,7 @@ public:
MV_10_7 = 0x0009,
MV_10_8 = 0x000A,
MV_10_9 = 0x000B,
+ MV_10_10 = 0x000C,
/* codenames */
MV_CHEETAH = MV_10_0,
@@ -148,6 +149,7 @@ public:
MV_LION = MV_10_7,
MV_MOUNTAINLION = MV_10_8,
MV_MAVERICKS = MV_10_9,
+ MV_YOSEMITE = MV_10_10,
/* iOS */
MV_IOS = 1 << 8,
@@ -157,11 +159,19 @@ public:
MV_IOS_6_0 = Q_MV_IOS(6, 0),
MV_IOS_6_1 = Q_MV_IOS(6, 1),
MV_IOS_7_0 = Q_MV_IOS(7, 0),
- MV_IOS_7_1 = Q_MV_IOS(7, 1)
+ MV_IOS_7_1 = Q_MV_IOS(7, 1),
+ MV_IOS_8_0 = Q_MV_IOS(8, 0)
};
static const MacVersion MacintoshVersion;
static MacVersion macVersion();
#endif
+
+ static QString buildCpuArchitecture();
+ static QString buildAbi();
+ static QString osType();
+ static QString osKernelVersion();
+ static QString osVersion();
+ static QString prettyOsName();
};
QT_END_NAMESPACE
diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h
index 0431e10133..b2e99ac259 100644
--- a/src/corelib/global/qsystemdetection.h
+++ b/src/corelib/global/qsystemdetection.h
@@ -235,6 +235,9 @@
# if !defined(__MAC_10_9)
# define __MAC_10_9 1090
# endif
+# if !defined(__MAC_10_10)
+# define __MAC_10_10 101000
+# endif
# if !defined(MAC_OS_X_VERSION_10_7)
# define MAC_OS_X_VERSION_10_7 1070
# endif
@@ -244,6 +247,9 @@
# if !defined(MAC_OS_X_VERSION_10_9)
# define MAC_OS_X_VERSION_10_9 1090
# endif
+# if !defined(MAC_OS_X_VERSION_10_10)
+# define MAC_OS_X_VERSION_10_10 101000
+# endif
#
# if !defined(__IPHONE_4_3)
# define __IPHONE_4_3 40300
@@ -263,6 +269,12 @@
# if !defined(__IPHONE_7_0)
# define __IPHONE_7_0 70000
# endif
+# if !defined(__IPHONE_7_1)
+# define __IPHONE_7_1 70100
+# endif
+# if !defined(__IPHONE_8_0)
+# define __IPHONE_8_0 80000
+# endif
#endif
#ifdef __LSB_VERSION__
diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h
index 8478e08416..70dc623e0c 100644
--- a/src/corelib/global/qtypeinfo.h
+++ b/src/corelib/global/qtypeinfo.h
@@ -64,7 +64,7 @@ public:
isComplex = true,
isStatic = true,
isLarge = (sizeof(T)>sizeof(void*)),
- isDummy = false,
+ isDummy = false, //### Qt6: remove
sizeOf = sizeof(T)
};
};
diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp
index a6fbffee7e..127244e994 100644
--- a/src/corelib/io/qdatastream.cpp
+++ b/src/corelib/io/qdatastream.cpp
@@ -250,10 +250,6 @@ QT_BEGIN_NAMESPACE
if (q_status != Ok) \
return retVal;
-enum {
- DefaultStreamVersion = QDataStream::Qt_5_3
-};
-
/*!
Constructs a data stream that has no I/O device.
@@ -265,7 +261,7 @@ QDataStream::QDataStream()
dev = 0;
owndev = false;
byteorder = BigEndian;
- ver = DefaultStreamVersion;
+ ver = Qt_DefaultCompiledVersion;
noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
q_status = Ok;
}
@@ -287,7 +283,7 @@ QDataStream::QDataStream(QIODevice *d)
dev = d; // set device
owndev = false;
byteorder = BigEndian; // default byte order
- ver = DefaultStreamVersion;
+ ver = Qt_DefaultCompiledVersion;
noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
q_status = Ok;
}
@@ -315,7 +311,7 @@ QDataStream::QDataStream(QByteArray *a, QIODevice::OpenMode flags)
dev = buf;
owndev = true;
byteorder = BigEndian;
- ver = DefaultStreamVersion;
+ ver = Qt_DefaultCompiledVersion;
noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
q_status = Ok;
}
@@ -339,7 +335,7 @@ QDataStream::QDataStream(const QByteArray &a)
dev = buf;
owndev = true;
byteorder = BigEndian;
- ver = DefaultStreamVersion;
+ ver = Qt_DefaultCompiledVersion;
noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
q_status = Ok;
}
@@ -542,6 +538,8 @@ void QDataStream::setByteOrder(ByteOrder bo)
\value Qt_5_1 Version 14 (Qt 5.1)
\value Qt_5_2 Version 15 (Qt 5.2)
\value Qt_5_3 Same as Qt_5_2
+ \value Qt_5_4 Version 16 (Qt 5.4)
+ \omitvalue Qt_DefaultCompiledVersion
\sa setVersion(), version()
*/
@@ -557,7 +555,8 @@ void QDataStream::setByteOrder(ByteOrder bo)
/*!
\fn void QDataStream::setVersion(int v)
- Sets the version number of the data serialization format to \a v.
+ Sets the version number of the data serialization format to \a v,
+ a value of the \l Version enum.
You don't \e have to set a version if you are using the current
version of Qt, but for your own custom binary formats we
@@ -571,25 +570,6 @@ void QDataStream::setByteOrder(ByteOrder bo)
with an earlier version of Qt, use this function to modify the
serialization format used by QDataStream.
- \table
- \header \li Qt Version \li QDataStream Version
- \row \li Qt 5.2 \li 15
- \row \li Qt 5.1 \li 14
- \row \li Qt 5.0 \li 13
- \row \li Qt 4.6 \li 12
- \row \li Qt 4.5 \li 11
- \row \li Qt 4.4 \li 10
- \row \li Qt 4.3 \li 9
- \row \li Qt 4.2 \li 8
- \row \li Qt 4.0, 4.1 \li 7
- \row \li Qt 3.3 \li 6
- \row \li Qt 3.1, 3.2 \li 5
- \row \li Qt 3.0 \li 4
- \row \li Qt 2.1, 2.2, 2.3 \li 3
- \row \li Qt 2.0 \li 2
- \row \li Qt 1.x \li 1
- \endtable
-
The \l Version enum provides symbolic constants for the different
versions of Qt. For example:
diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h
index 28f1d51a12..808fbe73f6 100644
--- a/src/corelib/io/qdatastream.h
+++ b/src/corelib/io/qdatastream.h
@@ -88,10 +88,12 @@ public:
Qt_5_0 = 13,
Qt_5_1 = 14,
Qt_5_2 = 15,
- Qt_5_3 = Qt_5_2
-#if QT_VERSION >= 0x050400
-#error Add the datastream version for this Qt version
+ Qt_5_3 = Qt_5_2,
+ Qt_5_4 = 16,
+#if QT_VERSION >= 0x050500
+#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
#endif
+ Qt_DefaultCompiledVersion = Qt_5_4
};
enum ByteOrder {
diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp
index 3370cce6d5..b0411f9dd9 100644
--- a/src/corelib/io/qdebug.cpp
+++ b/src/corelib/io/qdebug.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -79,6 +79,18 @@ QT_BEGIN_NAMESPACE
used to write debugging information to files and other devices. The constructor
that accepts a QString is used to write to a string for display or serialization.
+ \section1 Formatting Options
+
+ QDebug formats output so that it's easily readable. It automatically adds spaces
+ between arguments, and adds quotes around QString, QByteArray, QChar arguments.
+
+ You can tweak these options through the space(), nospace() and quote(), noquote()
+ methods. Furthermore, \l{QTextStream manipulators} can be piped into a QDebug
+ stream.
+
+ QDebugStateSaver limits changes to the formatting to the current scope.
+ resetFormat() resets the options to the default ones.
+
\section1 Writing Custom Types to a Stream
Many standard types can be written to QDebug objects, and Qt provides support for
@@ -128,6 +140,20 @@ QT_BEGIN_NAMESPACE
Flushes any pending data to be written and destroys the debug stream.
*/
+// Has been defined in the header / inlined before Qt 5.4
+QDebug::~QDebug()
+{
+ if (!--stream->ref) {
+ if (stream->space && stream->buffer.endsWith(QLatin1Char(' ')))
+ stream->buffer.chop(1);
+ if (stream->message_output) {
+ qt_message_output(stream->type,
+ stream->context,
+ stream->buffer);
+ }
+ delete stream;
+ }
+}
/*!
\fn QDebug::swap(QDebug &other)
@@ -138,6 +164,21 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ Resets the stream formatting options, bringing it back to its original constructed state.
+
+ \sa space(), quote()
+ \since 5.4
+*/
+QDebug &QDebug::resetFormat()
+{
+ stream->ts.reset();
+ stream->space = true;
+ if (stream->context.version > 1)
+ stream->flags = 0;
+ return *this;
+}
+
+/*!
\fn QDebug &QDebug::space()
Writes a space character to the debug stream and returns a reference to
@@ -188,6 +229,41 @@ QT_BEGIN_NAMESPACE
\sa QDebugStateSaver
*/
+
+/*!
+ \fn QDebug &QDebug::quote()
+ \since 5.4
+
+ Enables automatic insertion of quotation characters around QChar, QString and QByteArray
+ contents and returns a reference to the stream.
+
+ Quoting is enabled by default.
+
+ \sa noquote(), maybeQuote()
+*/
+
+/*!
+ \fn QDebug &QDebug::noquote()
+ \since 5.4
+
+ Disables automatic insertion of quotation characters around QChar, QString and QByteArray
+ contents and returns a reference to the stream.
+
+ \sa quote(), maybeQuote()
+*/
+
+/*!
+ \fn QDebug &QDebug::maybeQuote(char c)
+ \since 5.4
+
+ Writes a character \a c to the debug stream, depending on the
+ current setting for automatic insertion of quotes, and returns a reference to the stream.
+
+ The default character is a double quote \c{"}.
+
+ \sa quote(), noquote()
+*/
+
/*!
\fn QDebug &QDebug::operator<<(QChar t)
@@ -334,7 +410,9 @@ QT_BEGIN_NAMESPACE
\brief Convenience class for custom QDebug operators
- Saves the settings used by QDebug, and restores them upon destruction.
+ Saves the settings used by QDebug, and restores them upon destruction,
+ then calls maybeSpace(), to separate arguments with a space if
+ autoInsertSpaces() was true at the time of constructing the QDebugStateSaver.
The automatic insertion of spaces between writes is one of the settings
that QDebugStateSaver stores for the duration of the current block.
@@ -352,19 +430,33 @@ public:
QDebugStateSaverPrivate(QDebug &dbg)
: m_dbg(dbg),
m_spaces(dbg.autoInsertSpaces()),
+ m_flags(0),
m_streamParams(dbg.stream->ts.d_ptr->params)
{
+ if (m_dbg.stream->context.version > 1)
+ m_flags = m_dbg.stream->flags;
}
void restoreState()
{
+ const bool currentSpaces = m_dbg.autoInsertSpaces();
+ if (currentSpaces && !m_spaces)
+ if (m_dbg.stream->buffer.endsWith(QLatin1Char(' ')))
+ m_dbg.stream->buffer.chop(1);
+
m_dbg.setAutoInsertSpaces(m_spaces);
m_dbg.stream->ts.d_ptr->params = m_streamParams;
+ if (m_dbg.stream->context.version > 1)
+ m_dbg.stream->flags = m_flags;
+
+ if (!currentSpaces && m_spaces)
+ m_dbg.stream->ts << ' ';
}
QDebug &m_dbg;
// QDebug state
const bool m_spaces;
+ int m_flags;
// QTextStream state
const QTextStreamPrivate::Params m_streamParams;
diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h
index bdaaa05768..d224359724 100644
--- a/src/corelib/io/qdebug.h
+++ b/src/corelib/io/qdebug.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -61,9 +61,9 @@ class Q_CORE_EXPORT QDebug
friend class QMessageLogger;
friend class QDebugStateSaverPrivate;
struct Stream {
- Stream(QIODevice *device) : ts(device), ref(1), type(QtDebugMsg), space(true), message_output(false) {}
- Stream(QString *string) : ts(string, QIODevice::WriteOnly), ref(1), type(QtDebugMsg), space(true), message_output(false) {}
- Stream(QtMsgType t) : ts(&buffer, QIODevice::WriteOnly), ref(1), type(t), space(true), message_output(true) {}
+ Stream(QIODevice *device) : ts(device), ref(1), type(QtDebugMsg), space(true), message_output(false), flags(0) {}
+ Stream(QString *string) : ts(string, QIODevice::WriteOnly), ref(1), type(QtDebugMsg), space(true), message_output(false), flags(0) {}
+ Stream(QtMsgType t) : ts(&buffer, QIODevice::WriteOnly), ref(1), type(t), space(true), message_output(true), flags(0) {}
QTextStream ts;
QString buffer;
int ref;
@@ -71,6 +71,18 @@ class Q_CORE_EXPORT QDebug
bool space;
bool message_output;
QMessageLogContext context;
+
+ enum FormatFlag {
+ NoQuotes = 0x1
+ };
+
+ // ### Qt 6: unify with space, introduce own version member
+ bool testFlag(FormatFlag flag) const { return (context.version > 1) ? (flags & flag) : false; }
+ void setFlag(FormatFlag flag) { if (context.version > 1) { flags |= flag; } }
+ void unsetFlag(FormatFlag flag) { if (context.version > 1) { flags &= ~flag; } }
+
+ // added in 5.4
+ int flags;
} *stream;
public:
inline QDebug(QIODevice *device) : stream(new Stream(device)) {}
@@ -78,22 +90,11 @@ public:
inline QDebug(QtMsgType t) : stream(new Stream(t)) {}
inline QDebug(const QDebug &o):stream(o.stream) { ++stream->ref; }
inline QDebug &operator=(const QDebug &other);
- inline ~QDebug() {
- if (!--stream->ref) {
- if (stream->space && stream->buffer.endsWith(QLatin1Char(' ')))
- stream->buffer.chop(1);
- if (stream->message_output) {
- QT_TRY {
- qt_message_output(stream->type,
- stream->context,
- stream->buffer);
- } QT_CATCH(std::bad_alloc&) { /* We're out of memory - give up. */ }
- }
- delete stream;
- }
- }
+ ~QDebug();
inline void swap(QDebug &other) { qSwap(stream, other.stream); }
+ QDebug &resetFormat();
+
inline QDebug &space() { stream->space = true; stream->ts << ' '; return *this; }
inline QDebug &nospace() { stream->space = false; return *this; }
inline QDebug &maybeSpace() { if (stream->space) stream->ts << ' '; return *this; }
@@ -101,7 +102,11 @@ public:
bool autoInsertSpaces() const { return stream->space; }
void setAutoInsertSpaces(bool b) { stream->space = b; }
- inline QDebug &operator<<(QChar t) { stream->ts << '\'' << t << '\''; return maybeSpace(); }
+ inline QDebug &quote() { stream->unsetFlag(Stream::NoQuotes); return *this; }
+ inline QDebug &noquote() { stream->setFlag(Stream::NoQuotes); return *this; }
+ inline QDebug &maybeQuote(char c = '"') { if (!(stream->testFlag(Stream::NoQuotes))) stream->ts << c; return *this; }
+
+ inline QDebug &operator<<(QChar t) { maybeQuote('\''); stream->ts << t; maybeQuote('\''); return maybeSpace(); }
inline QDebug &operator<<(bool t) { stream->ts << (t ? "true" : "false"); return maybeSpace(); }
inline QDebug &operator<<(char t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(signed short t) { stream->ts << t; return maybeSpace(); }
@@ -115,10 +120,10 @@ 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(); }
- inline QDebug &operator<<(const QString & t) { stream->ts << '\"' << t << '\"'; return maybeSpace(); }
+ inline QDebug &operator<<(const QString & t) { maybeQuote(); stream->ts << t; maybeQuote(); return maybeSpace(); }
inline QDebug &operator<<(const QStringRef & t) { return operator<<(t.toString()); }
- inline QDebug &operator<<(QLatin1String t) { stream->ts << '\"' << t << '\"'; return maybeSpace(); }
- inline QDebug &operator<<(const QByteArray & t) { stream->ts << '\"' << t << '\"'; return maybeSpace(); }
+ inline QDebug &operator<<(QLatin1String t) { maybeQuote(); stream->ts << t; maybeQuote(); return maybeSpace(); }
+ inline QDebug &operator<<(const QByteArray & t) { maybeQuote(); stream->ts << t; maybeQuote(); return maybeSpace(); }
inline QDebug &operator<<(const void * t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(QTextStreamFunction f) {
stream->ts << f;
@@ -150,6 +155,9 @@ public:
inline QNoDebug &space() { return *this; }
inline QNoDebug &nospace() { return *this; }
inline QNoDebug &maybeSpace() { return *this; }
+ inline QNoDebug &quote() { return *this; }
+ inline QNoDebug &noquote() { return *this; }
+ inline QNoDebug &maybeQuote(const char = '"') { return *this; }
template<typename T>
inline QNoDebug &operator<<(const T &) { return *this; }
@@ -164,13 +172,8 @@ inline QDebug &QDebug::operator=(const QDebug &other)
return *this;
}
-#if defined(FORCE_UREF)
-template <class T>
-inline QDebug &operator<<(QDebug debug, const QList<T> &list)
-#else
template <class T>
inline QDebug operator<<(QDebug debug, const QList<T> &list)
-#endif
{
const bool oldSetting = debug.autoInsertSpaces();
debug.nospace() << '(';
@@ -184,13 +187,8 @@ inline QDebug operator<<(QDebug debug, const QList<T> &list)
return debug.maybeSpace();
}
-#if defined(FORCE_UREF)
-template <typename T>
-inline QDebug &operator<<(QDebug debug, const QVector<T> &vec)
-#else
template <typename T>
inline QDebug operator<<(QDebug debug, const QVector<T> &vec)
-#endif
{
const bool oldSetting = debug.autoInsertSpaces();
debug.nospace() << "QVector";
@@ -198,13 +196,8 @@ inline QDebug operator<<(QDebug debug, const QVector<T> &vec)
return operator<<(debug, vec.toList());
}
-#if defined(FORCE_UREF)
-template <class aKey, class aT>
-inline QDebug &operator<<(QDebug debug, const QMap<aKey, aT> &map)
-#else
template <class aKey, class aT>
inline QDebug operator<<(QDebug debug, const QMap<aKey, aT> &map)
-#endif
{
const bool oldSetting = debug.autoInsertSpaces();
debug.nospace() << "QMap(";
@@ -217,13 +210,8 @@ inline QDebug operator<<(QDebug debug, const QMap<aKey, aT> &map)
return debug.maybeSpace();
}
-#if defined(FORCE_UREF)
-template <class aKey, class aT>
-inline QDebug &operator<<(QDebug debug, const QHash<aKey, aT> &hash)
-#else
template <class aKey, class aT>
inline QDebug operator<<(QDebug debug, const QHash<aKey, aT> &hash)
-#endif
{
const bool oldSetting = debug.autoInsertSpaces();
debug.nospace() << "QHash(";
@@ -235,13 +223,8 @@ inline QDebug operator<<(QDebug debug, const QHash<aKey, aT> &hash)
return debug.maybeSpace();
}
-#if defined(FORCE_UREF)
-template <class T1, class T2>
-inline QDebug &operator<<(QDebug debug, const QPair<T1, T2> &pair)
-#else
template <class T1, class T2>
inline QDebug operator<<(QDebug debug, const QPair<T1, T2> &pair)
-#endif
{
const bool oldSetting = debug.autoInsertSpaces();
debug.nospace() << "QPair(" << pair.first << ',' << pair.second << ')';
@@ -258,13 +241,8 @@ inline QDebug operator<<(QDebug debug, const QSet<T> &set)
return operator<<(debug, set.toList());
}
-#if defined(FORCE_UREF)
-template <class T>
-inline QDebug &operator<<(QDebug debug, const QContiguousCache<T> &cache)
-#else
template <class T>
inline QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache)
-#endif
{
const bool oldSetting = debug.autoInsertSpaces();
debug.nospace() << "QContiguousCache(";
@@ -278,13 +256,8 @@ inline QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache)
return debug.maybeSpace();
}
-#if defined(FORCE_UREF)
-template <class T>
-inline QDebug &operator<<(QDebug debug, const QFlags<T> &flags)
-#else
template <class T>
inline QDebug operator<<(QDebug debug, const QFlags<T> &flags)
-#endif
{
const bool oldSetting = debug.autoInsertSpaces();
debug.nospace() << "QFlags(";
diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp
index f7e58a7bed..33cb6037f5 100644
--- a/src/corelib/io/qfiledevice.cpp
+++ b/src/corelib/io/qfiledevice.cpp
@@ -680,6 +680,13 @@ bool QFileDevice::setPermissions(Permissions permissions)
function.
\value NoOptions No options.
+ \value MapPrivateOption The mapped memory will be private, so any
+ modifications will not be visible to other processes and will not
+ be written to disk. Any such modifications will be lost when the
+ memory is unmapped. It is unspecified whether modifications made
+ to the file made after the mapping is created will be visible through
+ the mapped memory. This flag is not supported on Windows CE.
+ This enum value was introduced in Qt 5.4.
*/
/*!
@@ -689,6 +696,10 @@ bool QFileDevice::setPermissions(Permissions permissions)
or a new file is opened with this object, any maps that have not been
unmapped will automatically be unmapped.
+ The mapping will have the same open mode as the file (read and/or write),
+ except when using MapPrivateOption, in which case it is always possible
+ to write to the mapped memory.
+
Any mapping options can be passed through \a flags.
Returns a pointer to the memory or 0 if there is an error.
diff --git a/src/corelib/io/qfiledevice.h b/src/corelib/io/qfiledevice.h
index fc2779086a..4b13ffe589 100644
--- a/src/corelib/io/qfiledevice.h
+++ b/src/corelib/io/qfiledevice.h
@@ -112,8 +112,10 @@ public:
virtual Permissions permissions() const;
virtual bool setPermissions(Permissions permissionSpec);
+ // ### Qt 6: rename to MemoryMapFlag & make it a QFlags
enum MemoryMapFlags {
- NoOptions = 0
+ NoOptions = 0,
+ MapPrivateOption = 0x0001
};
uchar *map(qint64 offset, qint64 size, MemoryMapFlags flags = NoOptions);
diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp
index 0fa1f02f5c..4301536cf7 100644
--- a/src/corelib/io/qfileselector.cpp
+++ b/src/corelib/io/qfileselector.cpp
@@ -51,10 +51,6 @@
#include <QtCore/QLocale>
#include <QtCore/QDebug>
-#ifdef Q_OS_UNIX
-#include <sys/utsname.h>
-#endif
-
QT_BEGIN_NAMESPACE
//Environment variable to allow tooling full control of file selectors
@@ -360,6 +356,7 @@ void QFileSelectorPrivate::updateSelectors()
QStringList QFileSelectorPrivate::platformSelectors()
{
+ // similar, but not identical to QSysInfo::osType
QStringList ret;
#if defined(Q_OS_WIN)
ret << QStringLiteral("windows");
@@ -390,9 +387,7 @@ QStringList QFileSelectorPrivate::platformSelectors()
ret << QStringLiteral("osx");
# endif
# else
- struct utsname u;
- if (uname(&u) != -1)
- ret << QString::fromLatin1(u.sysname).toLower();
+ ret << QSysInfo::osType();
# endif
#endif
return ret;
diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp
index 998a3334c9..3c4a2fac0b 100644
--- a/src/corelib/io/qfsfileengine.cpp
+++ b/src/corelib/io/qfsfileengine.cpp
@@ -179,9 +179,7 @@ QFSFileEngine::~QFSFileEngine()
} while (ret == -1 && errno == EINTR);
}
}
- QList<uchar*> keys = d->maps.keys();
- for (int i = 0; i < keys.count(); ++i)
- unmap(keys.at(i));
+ d->unmapAll();
}
/*!
@@ -463,6 +461,18 @@ qint64 QFSFileEngine::size() const
return d->nativeSize();
}
+/*!
+ \internal
+*/
+void QFSFileEnginePrivate::unmapAll()
+{
+ if (!maps.isEmpty()) {
+ const QList<uchar*> keys = maps.keys(); // Make a copy since unmap() modifies the map.
+ for (int i = 0; i < keys.count(); ++i)
+ unmap(keys.at(i));
+ }
+}
+
#ifndef Q_OS_WIN
/*!
\internal
diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h
index 21f38fea1d..b0610b1459 100644
--- a/src/corelib/io/qfsfileengine_p.h
+++ b/src/corelib/io/qfsfileengine_p.h
@@ -175,6 +175,7 @@ public:
uchar *map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags);
bool unmap(uchar *ptr);
+ void unmapAll();
mutable QFileSystemMetaData metaData;
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
index 064a1a511f..f9c6c8ab98 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -713,6 +713,12 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla
if (openMode & QIODevice::ReadOnly) access |= PROT_READ;
if (openMode & QIODevice::WriteOnly) access |= PROT_WRITE;
+ int sharemode = MAP_SHARED;
+ if (flags & QFileDevice::MapPrivateOption) {
+ sharemode = MAP_PRIVATE;
+ access |= PROT_WRITE;
+ }
+
#if defined(Q_OS_INTEGRITY)
int pageSize = sysconf(_SC_PAGESIZE);
#else
@@ -730,7 +736,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla
realOffset &= ~(QT_OFF_T(pageSize - 1));
void *mapAddress = QT_MMAP((void*)0, realSize,
- access, MAP_SHARED, nativeHandle(), realOffset);
+ access, sharemode, nativeHandle(), realOffset);
if (MAP_FAILED != mapAddress) {
uchar *address = extra + static_cast<uchar*>(mapAddress);
maps[address] = QPair<int,size_t>(extra, realSize);
diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp
index fb4107b95d..81aed5f7b4 100644
--- a/src/corelib/io/qfsfileengine_win.cpp
+++ b/src/corelib/io/qfsfileengine_win.cpp
@@ -965,6 +965,21 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size,
return 0;
}
+ // check/setup args to map
+ DWORD access = 0;
+ if (flags & QFileDevice::MapPrivateOption) {
+#ifdef FILE_MAP_COPY
+ access = FILE_MAP_COPY;
+#else
+ q->setError(QFile::UnspecifiedError, "MapPrivateOption unsupported");
+ return 0;
+#endif
+ } else if (openMode & QIODevice::WriteOnly) {
+ access = FILE_MAP_WRITE;
+ } else if (openMode & QIODevice::ReadOnly) {
+ access = FILE_MAP_READ;
+ }
+
if (mapHandle == NULL) {
// get handle to the file
HANDLE handle = fileHandle;
@@ -1011,11 +1026,6 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size,
}
}
- // setup args to map
- DWORD access = 0;
- if (openMode & QIODevice::ReadOnly) access = FILE_MAP_READ;
- if (openMode & QIODevice::WriteOnly) access = FILE_MAP_WRITE;
-
DWORD offsetHi = offset >> 32;
DWORD offsetLo = offset & Q_UINT64_C(0xffffffff);
SYSTEM_INFO sysinfo;
diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp
index 28f6b02a64..00c8a85bcc 100644
--- a/src/corelib/io/qlockfile_win.cpp
+++ b/src/corelib/io/qlockfile_win.cpp
@@ -50,6 +50,11 @@
QT_BEGIN_NAMESPACE
+static inline QByteArray localHostName()
+{
+ return qgetenv("COMPUTERNAME");
+}
+
QLockFile::LockError QLockFilePrivate::tryLock_sys()
{
const QFileSystemEntry fileEntry(fileName);
@@ -98,7 +103,7 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys()
fileData += '\n';
fileData += qAppName().toUtf8();
fileData += '\n';
- //fileData += localHostname(); // gethostname requires winsock init, see QHostInfo...
+ fileData += localHostName();
fileData += '\n';
DWORD bytesWritten = 0;
QLockFile::LockError error = QLockFile::NoError;
@@ -123,14 +128,16 @@ bool QLockFilePrivate::isApparentlyStale() const
// On WinRT there seems to be no way of obtaining information about other
// processes due to sandboxing
#ifndef Q_OS_WINRT
- HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
- if (!procHandle)
- return true;
- // We got a handle but check if process is still alive
- DWORD dwR = ::WaitForSingleObject(procHandle, 0);
- ::CloseHandle(procHandle);
- if (dwR == WAIT_TIMEOUT)
- return true;
+ if (hostname == QString::fromLocal8Bit(localHostName())) {
+ HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
+ if (!procHandle)
+ return true;
+ // We got a handle but check if process is still alive
+ DWORD dwR = ::WaitForSingleObject(procHandle, 0);
+ ::CloseHandle(procHandle);
+ if (dwR == WAIT_TIMEOUT)
+ return true;
+ }
#endif // !Q_OS_WINRT
const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
return staleLockTime > 0 && age > staleLockTime;
diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp
index 07245ddea2..63241f6698 100644
--- a/src/corelib/io/qloggingcategory.cpp
+++ b/src/corelib/io/qloggingcategory.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -82,7 +82,7 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
\section1 Creating category objects
- The Q_LOGGING_CATEGORY() and the Q_DECLARE_LOGGING_CATEGORY() macros
+ The Q_DECLARE_LOGGING_CATEGORY() and Q_LOGGING_CATEGORY() macros
conveniently declare and create QLoggingCategory objects:
\snippet qloggingcategory/main.cpp 1
@@ -101,13 +101,21 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
\section1 Default category configuration
- In the default configuration \l isWarningEnabled() , \l isDebugEnabled() and
- \l isCriticalEnabled() will return \c true.
+ Both the QLoggingCategory constructor and the Q_LOGGING_CATEGORY() macro
+ accept an optional QtMsgType argument, which disables all message types with
+ a lower severity. That is, a category declared with
+
+ \snippet qloggingcategory/main.cpp 5
+
+ will log messages of type \c QtWarningMsg, \c QtCriticalMsg, \c QtFatalMsg, but will
+ ignore messages of type \c QtDebugMsg.
+
+ If no argument is passed, all messages will be logged.
\section1 Configuring Categories
- Categories can be centrally configured by either setting logging rules,
- or by installing a custom filter.
+ The default configuration of categories can be overridden either by setting logging
+ rules, or by installing a custom filter.
\section2 Logging Rules
@@ -131,7 +139,13 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
are automatically loaded from the \c [Rules] section of a logging
configuration file. Such configuration files are looked up in the QtProject
configuration directory, or explicitly set in a \c QT_LOGGING_CONF
- environment variable.
+ environment variable:
+
+ \code
+ [Rules]
+ *.debug=false
+ driver.usb.debug=true
+ \endcode
Rules set by \l setFilterRules() take precedence over rules specified
in the QtProject configuration directory, and can, in turn, be
@@ -177,7 +191,7 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
/*!
Constructs a QLoggingCategory object with the provided \a category name.
- The object becomes the local identifier for the category.
+ All message types for this category are enabled by default.
If \a category is \c{0}, the category name is changed to \c "default".
*/
@@ -185,8 +199,26 @@ QLoggingCategory::QLoggingCategory(const char *category)
: d(0),
name(0)
{
- Q_UNUSED(d);
- Q_UNUSED(placeholder);
+ init(category, QtDebugMsg);
+}
+
+/*!
+ Constructs a QLoggingCategory object with the provided \a category name,
+ and enables all messages with types more severe or equal than \a enableForLevel.
+
+ If \a category is \c{0}, the category name is changed to \c "default".
+
+ \since 5.4
+*/
+QLoggingCategory::QLoggingCategory(const char *category, QtMsgType enableForLevel)
+ : d(0),
+ name(0)
+{
+ init(category, enableForLevel);
+}
+
+void QLoggingCategory::init(const char *category, QtMsgType severityLevel)
+{
enabled.store(0x01010101); // enabledDebug = enabledWarning = enabledCritical = true;
const bool isDefaultCategory
@@ -194,14 +226,13 @@ QLoggingCategory::QLoggingCategory(const char *category)
// normalize "default" category name, so that we can just do
// pointer comparison in QLoggingRegistry::updateCategory
- if (isDefaultCategory) {
+ if (isDefaultCategory)
name = qtDefaultCategoryName;
- } else {
+ else
name = category;
- }
if (QLoggingRegistry *reg = QLoggingRegistry::instance())
- reg->registerCategory(this);
+ reg->registerCategory(this, severityLevel);
}
/*!
@@ -501,6 +532,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
*/
/*!
\macro Q_DECLARE_LOGGING_CATEGORY(name)
+ \sa Q_LOGGING_CATEGORY()
\relates QLoggingCategory
\since 5.2
@@ -512,11 +544,12 @@ void QLoggingCategory::setFilterRules(const QString &rules)
/*!
\macro Q_LOGGING_CATEGORY(name, string)
+ \sa Q_DECLARE_LOGGING_CATEGORY()
\relates QLoggingCategory
\since 5.2
Defines a logging category \a name, and makes it configurable under the
- \a string identifier.
+ \a string identifier. By default, all message types are enabled.
Only one translation unit in a library or executable can define a category
with a specific name.
@@ -524,4 +557,21 @@ void QLoggingCategory::setFilterRules(const QString &rules)
This macro must be used outside of a class or method.
*/
+/*!
+ \macro Q_LOGGING_CATEGORY(name, string, msgType)
+ \sa Q_DECLARE_LOGGING_CATEGORY()
+ \relates QLoggingCategory
+ \since 5.4
+
+ Defines a logging category \a name, and makes it configurable under the
+ \a string identifier. By default, messages of QtMsgType \a msgType
+ and more severe are enabled, types with a lower severity are disabled.
+
+ Only one translation unit in a library or executable can define a category
+ with a specific name.
+
+ This macro must be used outside of a class or method. It is only defined
+ if variadic macros are supported.
+*/
+
QT_END_NAMESPACE
diff --git a/src/corelib/io/qloggingcategory.h b/src/corelib/io/qloggingcategory.h
index 573af2105c..cca2031108 100644
--- a/src/corelib/io/qloggingcategory.h
+++ b/src/corelib/io/qloggingcategory.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -51,7 +51,9 @@ class Q_CORE_EXPORT QLoggingCategory
{
Q_DISABLE_COPY(QLoggingCategory)
public:
+ // ### Qt 6: Merge constructors
explicit QLoggingCategory(const char *category);
+ QLoggingCategory(const char *category, QtMsgType severityLevel);
~QLoggingCategory();
bool isEnabled(QtMsgType type) const;
@@ -80,7 +82,9 @@ public:
static void setFilterRules(const QString &rules);
private:
- void *d; // reserved for future use
+ void init(const char *category, QtMsgType severityLevel);
+
+ Q_DECL_UNUSED_MEMBER void *d; // reserved for future use
const char *name;
#ifdef Q_BIG_ENDIAN
@@ -100,22 +104,20 @@ private:
AtomicBools bools;
QBasicAtomicInt enabled;
};
- bool placeholder[4]; // reserve for future use
+ Q_DECL_UNUSED_MEMBER bool placeholder[4]; // reserved for future use
};
#define Q_DECLARE_LOGGING_CATEGORY(name) \
extern const QLoggingCategory &name();
-// relies on QLoggingCategory(QString) being thread safe!
-#define Q_LOGGING_CATEGORY(name, string) \
+#if defined(Q_COMPILER_VARIADIC_MACROS) || defined(Q_MOC_RUN)
+
+#define Q_LOGGING_CATEGORY(name, ...) \
const QLoggingCategory &name() \
{ \
- static const QLoggingCategory category(string); \
+ static const QLoggingCategory category(__VA_ARGS__); \
return category; \
}
-
-#ifdef Q_COMPILER_VARIADIC_MACROS
-
#define qCDebug(category, ...) \
for (bool qt_category_enabled = category().isDebugEnabled(); qt_category_enabled; qt_category_enabled = false) \
QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO, category().categoryName()).debug(__VA_ARGS__)
@@ -126,14 +128,22 @@ private:
for (bool qt_category_enabled = category().isCriticalEnabled(); qt_category_enabled; qt_category_enabled = false) \
QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO, category().categoryName()).critical(__VA_ARGS__)
-#else
+#else // defined(Q_COMPILER_VARIADIC_MACROS) || defined(Q_MOC_RUN)
+
+// Optional msgType argument not supported
+#define Q_LOGGING_CATEGORY(name, string) \
+ const QLoggingCategory &name() \
+ { \
+ static const QLoggingCategory category(string); \
+ return category; \
+ }
// check for enabled category inside QMessageLogger.
#define qCDebug qDebug
#define qCWarning qWarning
#define qCCritical qCritical
-#endif // Q_COMPILER_VARIADIC_MACROS
+#endif // Q_COMPILER_VARIADIC_MACROS || defined(Q_MOC_RUN)
#if defined(QT_NO_DEBUG_OUTPUT)
# undef qCDebug
diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp
index 575150f148..dd1612c6b4 100644
--- a/src/corelib/io/qloggingregistry.cpp
+++ b/src/corelib/io/qloggingregistry.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -131,15 +131,15 @@ void QLoggingRule::parse(const QStringRef &pattern)
// strip trailing ".messagetype"
if (pattern.endsWith(QLatin1String(".debug"))) {
p = QStringRef(pattern.string(), pattern.position(),
- pattern.length() - strlen(".debug"));
+ pattern.length() - 6); // strlen(".debug")
messageType = QtDebugMsg;
} else if (pattern.endsWith(QLatin1String(".warning"))) {
p = QStringRef(pattern.string(), pattern.position(),
- pattern.length() - strlen(".warning"));
+ pattern.length() - 8); // strlen(".warning")
messageType = QtWarningMsg;
} else if (pattern.endsWith(QLatin1String(".critical"))) {
p = QStringRef(pattern.string(), pattern.position(),
- pattern.length() - strlen(".critical"));
+ pattern.length() - 9); // strlen(".critical")
messageType = QtCriticalMsg;
} else {
p = pattern;
@@ -261,12 +261,12 @@ void QLoggingRegistry::init()
if (!rulesFilePath.isEmpty()) {
QFile file(QFile::decodeName(rulesFilePath));
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- QTextStream stream(&file);
- QLoggingSettingsParser parser;
- parser.setContent(stream);
if (qtLoggingDebug())
debugMsg("Loading \"%s\" ...",
QDir::toNativeSeparators(file.fileName()).toUtf8().constData());
+ QTextStream stream(&file);
+ QLoggingSettingsParser parser;
+ parser.setContent(stream);
envRules = parser.rules();
}
}
@@ -285,12 +285,12 @@ void QLoggingRegistry::init()
if (!envPath.isEmpty()) {
QFile file(envPath);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- QTextStream stream(&file);
- QLoggingSettingsParser parser;
- parser.setContent(stream);
if (qtLoggingDebug())
debugMsg("Loading \"%s\" ...",
QDir::toNativeSeparators(envPath).toUtf8().constData());
+ QTextStream stream(&file);
+ QLoggingSettingsParser parser;
+ parser.setContent(stream);
configRules = parser.rules();
}
}
@@ -307,12 +307,12 @@ void QLoggingRegistry::init()
This method might be called concurrently for the same category object.
*/
-void QLoggingRegistry::registerCategory(QLoggingCategory *cat)
+void QLoggingRegistry::registerCategory(QLoggingCategory *cat, QtMsgType enableForLevel)
{
QMutexLocker locker(&registryMutex);
if (!categories.contains(cat)) {
- categories.append(cat);
+ categories.insert(cat, enableForLevel);
(*categoryFilter)(cat);
}
}
@@ -324,8 +324,7 @@ void QLoggingRegistry::registerCategory(QLoggingCategory *cat)
void QLoggingRegistry::unregisterCategory(QLoggingCategory *cat)
{
QMutexLocker locker(&registryMutex);
-
- categories.removeOne(cat);
+ categories.remove(cat);
}
/*!
@@ -341,7 +340,7 @@ void QLoggingRegistry::setApiRules(const QString &content)
QMutexLocker locker(&registryMutex);
if (qtLoggingDebug())
- debugMsg("Loading logging rules set by Qt API ...");
+ debugMsg("Loading logging rules set by QLoggingCategory::setFilterRules ...");
apiRules = parser.rules();
@@ -361,7 +360,7 @@ void QLoggingRegistry::updateRules()
rules = configRules + apiRules + envRules;
- foreach (QLoggingCategory *cat, categories)
+ foreach (QLoggingCategory *cat, categories.keys())
(*categoryFilter)(cat);
}
@@ -380,7 +379,7 @@ QLoggingRegistry::installFilter(QLoggingCategory::CategoryFilter filter)
QLoggingCategory::CategoryFilter old = categoryFilter;
categoryFilter = filter;
- foreach (QLoggingCategory *cat, categories)
+ foreach (QLoggingCategory *cat, categories.keys())
(*categoryFilter)(cat);
return old;
@@ -397,18 +396,22 @@ QLoggingRegistry *QLoggingRegistry::instance()
*/
void QLoggingRegistry::defaultCategoryFilter(QLoggingCategory *cat)
{
- // QLoggingCategory() normalizes "default" strings
- // to qtDefaultCategoryName
- bool debug = true;
+ QLoggingRegistry *reg = QLoggingRegistry::instance();
+ Q_ASSERT(reg->categories.contains(cat));
+ QtMsgType enableForLevel = reg->categories.value(cat);
+
+ bool debug = (enableForLevel == QtDebugMsg) ? true : false;
+ bool warning = (enableForLevel <= QtWarningMsg) ? true : false;
+ bool critical = (enableForLevel <= QtCriticalMsg) ? true : false;
+
+ // hard-wired implementation of
+ // qt.*.debug=false
+ // qt.debug=false
char c;
if (!memcmp(cat->categoryName(), "qt", 2) && (!(c = cat->categoryName()[2]) || c == '.'))
debug = false;
- bool warning = true;
- bool critical = true;
-
QString categoryName = QLatin1String(cat->categoryName());
- QLoggingRegistry *reg = QLoggingRegistry::instance();
foreach (const QLoggingRule &item, reg->rules) {
int filterpass = item.pass(categoryName, QtDebugMsg);
if (filterpass != 0)
diff --git a/src/corelib/io/qloggingregistry_p.h b/src/corelib/io/qloggingregistry_p.h
index 48804cfc2b..ce2503b32c 100644
--- a/src/corelib/io/qloggingregistry_p.h
+++ b/src/corelib/io/qloggingregistry_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -113,7 +113,7 @@ public:
void init();
- void registerCategory(QLoggingCategory *category);
+ void registerCategory(QLoggingCategory *category, QtMsgType enableForLevel);
void unregisterCategory(QLoggingCategory *category);
void setApiRules(const QString &content);
@@ -134,7 +134,7 @@ private:
QVector<QLoggingRule> envRules;
QVector<QLoggingRule> apiRules;
QVector<QLoggingRule> rules;
- QList<QLoggingCategory*> categories;
+ QHash<QLoggingCategory*,QtMsgType> categories;
QLoggingCategory::CategoryFilter categoryFilter;
friend class ::tst_QLoggingRegistry;
diff --git a/src/corelib/io/qnoncontiguousbytedevice.cpp b/src/corelib/io/qnoncontiguousbytedevice.cpp
index b1e4dd7584..4c5fb38c67 100644
--- a/src/corelib/io/qnoncontiguousbytedevice.cpp
+++ b/src/corelib/io/qnoncontiguousbytedevice.cpp
@@ -506,6 +506,25 @@ QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QIODevice *dev
}
/*!
+ Create a QNonContiguousByteDevice out of a QIODevice, return it in a QSharedPointer.
+ For QFile, QBuffer and all other QIODevice, sequential or not.
+
+ \internal
+*/
+QSharedPointer<QNonContiguousByteDevice> QNonContiguousByteDeviceFactory::createShared(QIODevice *device)
+{
+ // shortcut if it is a QBuffer
+ if (QBuffer *buffer = qobject_cast<QBuffer*>(device))
+ return QSharedPointer<QNonContiguousByteDeviceBufferImpl>::create(buffer);
+
+ // ### FIXME special case if device is a QFile that supports map()
+ // then we can actually deal with the file without using read/peek
+
+ // generic QIODevice
+ return QSharedPointer<QNonContiguousByteDeviceIoDeviceImpl>::create(device); // FIXME
+}
+
+/*!
\fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QSharedPointer<QRingBuffer> ringBuffer)
Create a QNonContiguousByteDevice out of a QRingBuffer.
@@ -518,6 +537,16 @@ QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QSharedPointer
}
/*!
+ Create a QNonContiguousByteDevice out of a QRingBuffer, return it in a QSharedPointer.
+
+ \internal
+*/
+QSharedPointer<QNonContiguousByteDevice> QNonContiguousByteDeviceFactory::createShared(QSharedPointer<QRingBuffer> ringBuffer)
+{
+ return QSharedPointer<QNonContiguousByteDeviceRingBufferImpl>::create(qMove(ringBuffer));
+}
+
+/*!
\fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QByteArray *byteArray)
Create a QNonContiguousByteDevice out of a QByteArray.
@@ -530,6 +559,16 @@ QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QByteArray *by
}
/*!
+ Create a QNonContiguousByteDevice out of a QByteArray.
+
+ \internal
+*/
+QSharedPointer<QNonContiguousByteDevice> QNonContiguousByteDeviceFactory::createShared(QByteArray *byteArray)
+{
+ return QSharedPointer<QNonContiguousByteDeviceByteArrayImpl>::create(byteArray);
+}
+
+/*!
\fn static QIODevice* QNonContiguousByteDeviceFactory::wrap(QNonContiguousByteDevice* byteDevice)
Wrap the \a byteDevice (possibly again) into a QIODevice.
diff --git a/src/corelib/io/qnoncontiguousbytedevice_p.h b/src/corelib/io/qnoncontiguousbytedevice_p.h
index 4606ac2686..1e746db80f 100644
--- a/src/corelib/io/qnoncontiguousbytedevice_p.h
+++ b/src/corelib/io/qnoncontiguousbytedevice_p.h
@@ -90,8 +90,14 @@ class Q_CORE_EXPORT QNonContiguousByteDeviceFactory
{
public:
static QNonContiguousByteDevice* create(QIODevice *device);
+ static QSharedPointer<QNonContiguousByteDevice> createShared(QIODevice *device);
+
static QNonContiguousByteDevice* create(QByteArray *byteArray);
+ static QSharedPointer<QNonContiguousByteDevice> createShared(QByteArray *byteArray);
+
static QNonContiguousByteDevice* create(QSharedPointer<QRingBuffer> ringBuffer);
+ static QSharedPointer<QNonContiguousByteDevice> createShared(QSharedPointer<QRingBuffer> ringBuffer);
+
static QIODevice* wrap(QNonContiguousByteDevice* byteDevice);
};
diff --git a/src/corelib/io/qsavefile.cpp b/src/corelib/io/qsavefile.cpp
index 2b901c7ccd..8be4125ef5 100644
--- a/src/corelib/io/qsavefile.cpp
+++ b/src/corelib/io/qsavefile.cpp
@@ -205,14 +205,32 @@ bool QSaveFile::open(OpenMode mode)
d->writeError = QFileDevice::WriteError;
return false;
}
- d->fileEngine = new QTemporaryFileEngine(d->fileName);
+
+ if (existingFile.isDir()) {
+ d->setError(QFileDevice::WriteError, QSaveFile::tr("Filename refers to a directory"));
+ d->writeError = QFileDevice::WriteError;
+ return false;
+ }
+
+ // Resolve symlinks. Don't use QFileInfo::canonicalFilePath so it still give the expected
+ // target even if the file does not exist
+ d->finalFileName = d->fileName;
+ if (existingFile.isSymLink()) {
+ int maxDepth = 128;
+ while (--maxDepth && existingFile.isSymLink())
+ existingFile.setFile(existingFile.symLinkTarget());
+ if (maxDepth > 0)
+ d->finalFileName = existingFile.filePath();
+ }
+
+ d->fileEngine = new QTemporaryFileEngine(d->finalFileName);
// Same as in QFile: QIODevice provides the buffering, so there's no need to request it from the file engine.
if (!d->fileEngine->open(mode | QIODevice::Unbuffered)) {
QFileDevice::FileError err = d->fileEngine->error();
#ifdef Q_OS_UNIX
if (d->directWriteFallback && err == QFileDevice::OpenError && errno == EACCES) {
delete d->fileEngine;
- d->fileEngine = QAbstractFileEngine::create(d->fileName);
+ d->fileEngine = QAbstractFileEngine::create(d->finalFileName);
if (d->fileEngine->open(mode | QIODevice::Unbuffered)) {
d->useTemporaryFile = false;
QFileDevice::open(mode);
@@ -285,7 +303,7 @@ bool QSaveFile::commit()
// atomically replace old file with new file
// Can't use QFile::rename for that, must use the file engine directly
Q_ASSERT(d->fileEngine);
- if (!d->fileEngine->renameOverwrite(d->fileName)) {
+ if (!d->fileEngine->renameOverwrite(d->finalFileName)) {
d->setError(d->fileEngine->error(), d->fileEngine->errorString());
d->fileEngine->remove();
delete d->fileEngine;
diff --git a/src/corelib/io/qsavefile_p.h b/src/corelib/io/qsavefile_p.h
index b9efd1ee7c..2134c4c9bc 100644
--- a/src/corelib/io/qsavefile_p.h
+++ b/src/corelib/io/qsavefile_p.h
@@ -70,6 +70,7 @@ protected:
~QSaveFilePrivate();
QString fileName;
+ QString finalFileName; // fileName with symbolic links resolved
QFileDevice::FileError writeError;
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index 1748170324..663ad3cc1b 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -53,6 +53,7 @@
#include "qmutex.h"
#include "qlibraryinfo.h"
#include "qtemporaryfile.h"
+#include "qstandardpaths.h"
#ifndef QT_NO_TEXTCODEC
# include "qtextcodec.h"
@@ -68,6 +69,11 @@
#include "qcoreapplication.h"
#endif
+#ifndef QT_BOOTSTRAPPED
+#include "qsavefile.h"
+#include "qlockfile.h"
+#endif
+
#ifdef Q_OS_VXWORKS
# include <ioLib.h>
#endif
@@ -101,12 +107,6 @@ using namespace ABI::Windows::Storage;
#define CSIDL_APPDATA 0x001a // <username>\Application Data
#endif
-#ifdef Q_AUTOTEST_EXPORT
-# define Q_AUTOTEST_EXPORT_HELPER Q_AUTOTEST_EXPORT
-#else
-# define Q_AUTOTEST_EXPORT_HELPER static
-#endif
-
// ************************************************************************
// QConfFile
@@ -141,101 +141,6 @@ static QBasicMutex settingsGlobalMutex;
static QSettings::Format globalDefaultFormat = QSettings::NativeFormat;
-#ifndef Q_OS_WIN
-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)
-QT_BEGIN_INCLUDE_NAMESPACE
-# include <sys/param.h>
-# include <sys/mount.h>
-QT_END_INCLUDE_NAMESPACE
-
-Q_AUTOTEST_EXPORT_HELPER 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)
-QT_BEGIN_INCLUDE_NAMESPACE
-# 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
-QT_END_INCLUDE_NAMESPACE
-# 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
-
-Q_AUTOTEST_EXPORT_HELPER bool qIsLikelyToBeNfs(int handle)
-{
- 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;
-}
-
-#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)
-QT_BEGIN_INCLUDE_NAMESPACE
-# include <sys/statvfs.h>
-QT_END_INCLUDE_NAMESPACE
-
-Q_AUTOTEST_EXPORT_HELPER bool qIsLikelyToBeNfs(int handle)
-{
- struct statvfs buf;
- if (fstatvfs(handle, &buf) != 0)
- return false;
-#if defined(Q_OS_NETBSD)
- return qt_isEvilFsTypeName(buf.f_fstypename);
-#else
- return qt_isEvilFsTypeName(buf.f_basetype);
-#endif
-}
-#else
-Q_AUTOTEST_EXPORT_HELPER inline bool qIsLikelyToBeNfs(int /* handle */)
-{
- return true;
-}
-#endif
-
-static bool unixLock(int handle, int lockType)
-{
- /*
- NFS hangs on the fcntl() call below when statd or lockd isn't
- running. There's no way to detect this. Our work-around for
- now is to disable locking when we detect NFS (or AutoFS or
- CacheFS, which are probably wrapping NFS).
- */
- if (qIsLikelyToBeNfs(handle))
- return false;
-
- struct flock fl;
- fl.l_whence = SEEK_SET;
- fl.l_start = 0;
- fl.l_len = 0;
- fl.l_type = lockType;
- return fcntl(handle, F_SETLKW, &fl) == 0;
-}
-#endif
-
QConfFile::QConfFile(const QString &fileName, bool _userPerms)
: name(fileName), size(0), ref(1), userPerms(_userPerms)
{
@@ -1140,6 +1045,8 @@ static void initDefaultPaths(QMutexLocker *locker)
pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope),
windowsConfigPath(CSIDL_COMMON_APPDATA) + QDir::separator());
#else
+
+#ifdef QT_NO_STANDARDPATHS
QString userPath;
char *env = getenv("XDG_CONFIG_HOME");
if (env == 0) {
@@ -1153,6 +1060,9 @@ static void initDefaultPaths(QMutexLocker *locker)
userPath += QLatin1Char('/');
userPath += QFile::decodeName(env);
}
+#else
+ QString userPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
+#endif
userPath += QLatin1Char('/');
pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope), userPath);
@@ -1457,105 +1367,30 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo)
return;
}
+#ifndef QT_BOOTSTRAPPED
/*
- Open the configuration file and try to use it using a named
- semaphore on Windows and an advisory lock on Unix-based
- systems. This protect us against other QSettings instances
- trying to access the same file from other threads or
- processes.
-
- As it stands now, the locking mechanism doesn't work for
- .plist files.
- */
- QFile file(confFile->name);
- bool createFile = !file.exists();
- if (!readOnly && confFile->isWritable())
- file.open(QFile::ReadWrite);
- if (!file.isOpen())
- file.open(QFile::ReadOnly);
-
- if (!createFile && !file.isOpen())
- setStatus(QSettings::AccessError);
-
-#ifdef Q_OS_WIN
- HANDLE readSemaphore = 0;
- HANDLE writeSemaphore = 0;
- static const int FileLockSemMax = 50;
- int numReadLocks = readOnly ? 1 : FileLockSemMax;
-
- if (file.isOpen()) {
- // Acquire the write lock if we will be writing
- if (!readOnly) {
- QString writeSemName = QLatin1String("QSettingsWriteSem ");
- writeSemName.append(file.fileName());
-
-#ifndef Q_OS_WINRT
- writeSemaphore = CreateSemaphore(0, 1, 1, reinterpret_cast<const wchar_t *>(writeSemName.utf16()));
-#else
- writeSemaphore = CreateSemaphoreEx(0, 1, 1, reinterpret_cast<const wchar_t *>(writeSemName.utf16()), 0, SEMAPHORE_ALL_ACCESS);
-#endif
+ Use a lockfile in order to protect us against other QSettings instances
+ trying to write the same settings at the same time.
- if (writeSemaphore) {
-#ifndef Q_OS_WINRT
- WaitForSingleObject(writeSemaphore, INFINITE);
-#else
- WaitForSingleObjectEx(writeSemaphore, INFINITE, FALSE);
-#endif
- } else {
- setStatus(QSettings::AccessError);
- return;
- }
- }
-
- // Acquire all the read locks if we will be writing, to make sure nobody
- // reads while we're writing. If we are only reading, acquire a single
- // read lock.
- QString readSemName(QLatin1String("QSettingsReadSem "));
- readSemName.append(file.fileName());
-
-#ifndef Q_OS_WINRT
- readSemaphore = CreateSemaphore(0, FileLockSemMax, FileLockSemMax, reinterpret_cast<const wchar_t *>(readSemName.utf16()));
-#else
- readSemaphore = CreateSemaphoreEx(0, FileLockSemMax, FileLockSemMax, reinterpret_cast<const wchar_t *>(readSemName.utf16()), 0, SEMAPHORE_ALL_ACCESS);
-#endif
-
- if (readSemaphore) {
- for (int i = 0; i < numReadLocks; ++i)
-#ifndef Q_OS_WINRT
- WaitForSingleObject(readSemaphore, INFINITE);
-#else
- WaitForSingleObjectEx(readSemaphore, INFINITE, FALSE);
-#endif
- } else {
+ We only need to lock if we are actually writing as only concurrent writes are a problem.
+ Concurrent read and write are not a problem because the writing operation is atomic.
+ */
+ QLockFile lockFile(confFile->name + QLatin1String(".lock"));
+ if (!readOnly) {
+ if (!confFile->isWritable() || !lockFile.lock() ) {
setStatus(QSettings::AccessError);
- if (writeSemaphore != 0) {
- ReleaseSemaphore(writeSemaphore, 1, 0);
- CloseHandle(writeSemaphore);
- }
return;
}
}
-#else
- if (file.isOpen())
- unixLock(file.handle(), readOnly ? F_RDLCK : F_WRLCK);
#endif
- // If we have created the file, apply the file perms
- if (file.isOpen()) {
- if (createFile) {
- QFile::Permissions perms = file.permissions() | QFile::ReadOwner | QFile::WriteOwner;
- if (!confFile->userPerms)
- perms |= QFile::ReadGroup | QFile::ReadOther;
- file.setPermissions(perms);
- }
- }
-
/*
We hold the lock. Let's reread the file if it has changed
since last time we read it.
*/
QFileInfo fileInfo(confFile->name);
bool mustReadFile = true;
+ bool createFile = !fileInfo.exists();
if (!readOnly)
mustReadFile = (confFile->size != fileInfo.size()
@@ -1565,6 +1400,12 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo)
confFile->unparsedIniSections.clear();
confFile->originalKeys.clear();
+ QFile file(confFile->name);
+ if (!createFile && !file.open(QFile::ReadOnly)) {
+ setStatus(QSettings::AccessError);
+ return;
+ }
+
/*
Files that we can't read (because of permissions or
because they don't exist) are treated as empty files.
@@ -1615,42 +1456,40 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo)
ensureAllSectionsParsed(confFile);
ParsedSettingsMap mergedKeys = confFile->mergedKeyMap();
- if (file.isWritable()) {
#ifdef Q_OS_MAC
- if (format == QSettings::NativeFormat) {
- ok = writePlistFile(confFile->name, mergedKeys);
- } else
+ if (format == QSettings::NativeFormat) {
+ ok = writePlistFile(confFile->name, mergedKeys);
+ } else
#endif
- {
- file.seek(0);
- file.resize(0);
+ {
+#ifndef QT_BOOTSTRAPPED
+ QSaveFile sf(confFile->name);
+#else
+ QFile sf(confFile->name);
+#endif
+ if (!sf.open(QIODevice::WriteOnly)) {
+ setStatus(QSettings::AccessError);
+ ok = false;
+ } else if (format <= QSettings::IniFormat) {
+ ok = writeIniFile(sf, mergedKeys);
+ } else {
+ if (writeFunc) {
+ QSettings::SettingsMap tempOriginalKeys;
- if (format <= QSettings::IniFormat) {
- ok = writeIniFile(file, mergedKeys);
- if (!ok) {
- // try to restore old data; might work if the disk was full and the new data
- // was larger than the old data
- file.seek(0);
- file.resize(0);
- writeIniFile(file, confFile->originalKeys);
+ ParsedSettingsMap::const_iterator i = mergedKeys.constBegin();
+ while (i != mergedKeys.constEnd()) {
+ tempOriginalKeys.insert(i.key(), i.value());
+ ++i;
}
+ ok = writeFunc(sf, tempOriginalKeys);
} else {
- if (writeFunc) {
- QSettings::SettingsMap tempOriginalKeys;
-
- ParsedSettingsMap::const_iterator i = mergedKeys.constBegin();
- while (i != mergedKeys.constEnd()) {
- tempOriginalKeys.insert(i.key(), i.value());
- ++i;
- }
- ok = writeFunc(file, tempOriginalKeys);
- } else {
- ok = false;
- }
+ ok = false;
}
}
- } else {
- ok = false;
+#ifndef QT_BOOTSTRAPPED
+ if (ok)
+ ok = sf.commit();
+#endif
}
if (ok) {
@@ -1662,24 +1501,18 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo)
QFileInfo fileInfo(confFile->name);
confFile->size = fileInfo.size();
confFile->timeStamp = fileInfo.lastModified();
+
+ // If we have created the file, apply the file perms
+ if (createFile) {
+ QFile::Permissions perms = fileInfo.permissions() | QFile::ReadOwner | QFile::WriteOwner;
+ if (!confFile->userPerms)
+ perms |= QFile::ReadGroup | QFile::ReadOther;
+ QFile(confFile->name).setPermissions(perms);
+ }
} else {
setStatus(QSettings::AccessError);
}
}
-
- /*
- Release the file lock.
- */
-#ifdef Q_OS_WIN
- if (readSemaphore != 0) {
- ReleaseSemaphore(readSemaphore, numReadLocks, 0);
- CloseHandle(readSemaphore);
- }
- if (writeSemaphore != 0) {
- ReleaseSemaphore(writeSemaphore, 1, 0);
- CloseHandle(writeSemaphore);
- }
-#endif
}
enum { Space = 0x1, Special = 0x2 };
@@ -2505,12 +2338,6 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
10.8 (Mountain Lion), only root can. However, 10.9 (Mavericks) changes
that rule again but only for the native format (plist files).
- \li On Unix and Mac OS X systems, the advisory file locking is disabled
- if NFS (or AutoFS or CacheFS) is detected to work around a bug in the
- NFS fcntl() implementation, which hangs forever if statd or lockd aren't
- running. Also, the locking isn't performed when accessing \c .plist
- files.
-
\li On the BlackBerry platform, applications run in a sandbox. They are not
allowed to read or write outside of this sandbox. This involves the
following limitations:
diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp
index bd9fa68d93..8c47ad1391 100644
--- a/src/corelib/io/qstandardpaths.cpp
+++ b/src/corelib/io/qstandardpaths.cpp
@@ -117,10 +117,9 @@ QT_BEGIN_NAMESPACE
\value HomeLocation Returns the user's home directory (the same as QDir::homePath()). On Unix
systems, this is equal to the HOME environment variable. This value might be
generic or application-specific, but the returned path is never empty.
- \value DataLocation Returns a directory location where persistent
- application data can be stored. This is an application-specific directory. To obtain a
- path to store data to be shared with other applications, use
- QStandardPaths::GenericDataLocation. The returned path is never empty.
+ \value DataLocation Returns the same value as AppLocalDataLocation. This enumeration value
+ is deprecated. Using AppDataLocation is preferable since on Windows, the roaming path is
+ recommended.
\value CacheLocation Returns a directory location where user-specific
non-essential (cached) data should be written. This is an application-specific directory.
The returned path is never empty.
@@ -142,6 +141,15 @@ QT_BEGIN_NAMESPACE
\value GenericConfigLocation Returns a directory location where user-specific
configuration files shared between multiple applications should be written.
This is a generic value and the returned path is never empty.
+ \value AppDataLocation Returns a directory location where persistent
+ application data can be stored. This is an application-specific directory.
+ To obtain a path to store data to be shared with other applications, use
+ QStandardPaths::GenericDataLocation. The returned path is never empty.
+ On the Windows operating system, this returns the roaming path.
+ This enum value was added in Qt 5.4.
+ \value AppLocalDataLocation Returns the local settings path on the Windows operating
+ system. On all other platforms, it returns the same value as AppDataLocation.
+ This enum value was added in Qt 5.4.
The following table gives examples of paths on different operating systems.
The first path is the writable path (unless noted). Other, additional
@@ -200,6 +208,12 @@ QT_BEGIN_NAMESPACE
\row \li GenericCacheLocation
\li "~/Library/Caches", "/Library/Caches"
\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"
+ \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"
\endtable
\table
@@ -255,6 +269,12 @@ QT_BEGIN_NAMESPACE
\row \li GenericCacheLocation
\li "<APPROOT>/data/Cache" (there is no shared cache)
\li "~/.cache"
+ \row \li AppDataLocation
+ \li "<APPROOT>/data", "<APPROOT>/app/native/assets"
+ \li "~/.local/share/<APPNAME>", "/usr/local/share/<APPNAME>", "/usr/share/<APPNAME>"
+ \row \li AppLocalDataLocation
+ \li "<APPROOT>/data", "<APPROOT>/app/native/assets"
+ \li "~/.local/share/<APPNAME>", "/usr/local/share/<APPNAME>", "/usr/share/<APPNAME>"
\endtable
\table
@@ -293,6 +313,8 @@ QT_BEGIN_NAMESPACE
\li "<USER>/Downloads", "<USER>/<APPNAME>/Downloads"
\row \li GenericCacheLocation
\li "<APPROOT>/cache" (there is no shared cache)
+ \row \li AppDataLocation
+ \li "<APPROOT>/files", "<USER>/<APPNAME>/files"
\endtable
In the table above, \c <APPNAME> is usually the organization name, the
@@ -534,8 +556,6 @@ QString QStandardPaths::displayName(StandardLocation type)
return QCoreApplication::translate("QStandardPaths", "Temporary Directory");
case HomeLocation:
return QCoreApplication::translate("QStandardPaths", "Home");
- case DataLocation:
- return QCoreApplication::translate("QStandardPaths", "Application Data");
case CacheLocation:
return QCoreApplication::translate("QStandardPaths", "Cache");
case GenericDataLocation:
@@ -550,6 +570,9 @@ QString QStandardPaths::displayName(StandardLocation type)
return QCoreApplication::translate("QStandardPaths", "Shared Cache");
case DownloadLocation:
return QCoreApplication::translate("QStandardPaths", "Download");
+ case AppDataLocation:
+ case AppLocalDataLocation:
+ return QCoreApplication::translate("QStandardPaths", "Application Data");
}
// not reached
return QString();
diff --git a/src/corelib/io/qstandardpaths.h b/src/corelib/io/qstandardpaths.h
index 08d6d7b50c..b93adbf156 100644
--- a/src/corelib/io/qstandardpaths.h
+++ b/src/corelib/io/qstandardpaths.h
@@ -70,7 +70,9 @@ public:
ConfigLocation,
DownloadLocation,
GenericCacheLocation,
- GenericConfigLocation
+ GenericConfigLocation,
+ AppDataLocation,
+ AppLocalDataLocation = DataLocation
};
static QString writableLocation(StandardLocation type);
diff --git a/src/corelib/io/qstandardpaths_android.cpp b/src/corelib/io/qstandardpaths_android.cpp
index 60b285a3d6..9bd4b4b428 100644
--- a/src/corelib/io/qstandardpaths_android.cpp
+++ b/src/corelib/io/qstandardpaths_android.cpp
@@ -244,7 +244,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
return getFilesDir() + testDir() + QLatin1String("/settings");
case QStandardPaths::GenericDataLocation:
return getExternalStorageDirectory() + testDir();
- case QStandardPaths::DataLocation:
+ case QStandardPaths::AppDataLocation:
+ case QStandardPaths::AppLocalDataLocation:
return getFilesDir() + testDir();
case QStandardPaths::GenericCacheLocation:
case QStandardPaths::RuntimeLocation:
@@ -301,7 +302,7 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
<< getExternalFilesDir("DIRECTORY_DOWNLOADS");
}
- if (type == DataLocation) {
+ if (type == AppDataLocation || type == AppLocalDataLocation) {
return QStringList() << writableLocation(type)
<< getExternalFilesDir();
}
diff --git a/src/corelib/io/qstandardpaths_blackberry.cpp b/src/corelib/io/qstandardpaths_blackberry.cpp
index ec2e61bd15..2e9d62cd05 100644
--- a/src/corelib/io/qstandardpaths_blackberry.cpp
+++ b/src/corelib/io/qstandardpaths_blackberry.cpp
@@ -63,7 +63,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
const QString sharedRoot = sharedDir.absolutePath();
switch (type) {
- case DataLocation:
+ case AppDataLocation:
+ case AppLocalDataLocation:
return QDir::homePath() + testModeInsert();
case DesktopLocation:
case HomeLocation:
@@ -108,7 +109,7 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
if (type == FontsLocation)
return QStringList(QLatin1String("/base/usr/fonts"));
- if (type == DataLocation)
+ if (type == AppDataLocation || type == AppLocalDataLocation)
dirs.append(QDir::homePath() + testModeInsert() + QLatin1String("native/assets"));
const QString localDir = writableLocation(type);
diff --git a/src/corelib/io/qstandardpaths_ios.mm b/src/corelib/io/qstandardpaths_ios.mm
index e2100045a6..cdca28b8b5 100644
--- a/src/corelib/io/qstandardpaths_ios.mm
+++ b/src/corelib/io/qstandardpaths_ios.mm
@@ -90,7 +90,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
case HomeLocation:
location = bundlePath();
break;
- case DataLocation:
+ case AppDataLocation:
+ case AppLocalDataLocation:
case GenericDataLocation:
location = pathForDirectory(NSDocumentDirectory);
break;
diff --git a/src/corelib/io/qstandardpaths_mac.cpp b/src/corelib/io/qstandardpaths_mac.cpp
index aff9112fb7..a27920899c 100644
--- a/src/corelib/io/qstandardpaths_mac.cpp
+++ b/src/corelib/io/qstandardpaths_mac.cpp
@@ -83,7 +83,8 @@ OSType translateLocation(QStandardPaths::StandardLocation type)
return kTemporaryFolderType;
case QStandardPaths::GenericDataLocation:
case QStandardPaths::RuntimeLocation:
- case QStandardPaths::DataLocation:
+ case QStandardPaths::AppDataLocation:
+ case QStandardPaths::AppLocalDataLocation:
return kApplicationSupportFolderType;
case QStandardPaths::GenericCacheLocation:
case QStandardPaths::CacheLocation:
@@ -128,7 +129,7 @@ static QString macLocation(QStandardPaths::StandardLocation type, short domain)
QString path = getFullPath(ref);
- if (type == QStandardPaths::DataLocation || type == QStandardPaths::CacheLocation)
+ if (type == QStandardPaths::AppDataLocation || type == QStandardPaths::AppLocalDataLocation || type == QStandardPaths::CacheLocation)
appendOrganizationAndApp(path);
return path;
}
@@ -140,9 +141,10 @@ QString QStandardPaths::writableLocation(StandardLocation type)
QString path;
switch (type) {
case GenericDataLocation:
- case DataLocation:
+ case AppDataLocation:
+ case AppLocalDataLocation:
path = qttestDir + QLatin1String("/Application Support");
- if (type == DataLocation)
+ if (type != GenericDataLocation)
appendOrganizationAndApp(path);
return path;
case GenericCacheLocation:
@@ -165,7 +167,7 @@ QString QStandardPaths::writableLocation(StandardLocation type)
case TempLocation:
return QDir::tempPath();
case GenericDataLocation:
- case DataLocation:
+ case AppLocalDataLocation:
case GenericCacheLocation:
case CacheLocation:
case RuntimeLocation:
@@ -179,13 +181,13 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
{
QStringList dirs;
- if (type == GenericDataLocation || type == DataLocation || type == GenericCacheLocation || type == CacheLocation) {
+ if (type == GenericDataLocation || type == AppDataLocation || type == AppLocalDataLocation || type == GenericCacheLocation || type == CacheLocation) {
const QString path = macLocation(type, kOnAppropriateDisk);
if (!path.isEmpty())
dirs.append(path);
}
- if (type == DataLocation) {
+ if (type == AppDataLocation || type == AppLocalDataLocation) {
CFBundleRef mainBundle = CFBundleGetMainBundle();
if (mainBundle) {
CFURLRef bundleUrl = CFBundleCopyBundleURL(mainBundle);
diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp
index e2ed7c3766..cde1e4bc72 100644
--- a/src/corelib/io/qstandardpaths_unix.cpp
+++ b/src/corelib/io/qstandardpaths_unix.cpp
@@ -90,7 +90,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
appendOrganizationAndApp(xdgCacheHome);
return xdgCacheHome;
}
- case DataLocation:
+ case AppDataLocation:
+ case AppLocalDataLocation:
case GenericDataLocation:
{
QString xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME"));
@@ -98,7 +99,7 @@ QString QStandardPaths::writableLocation(StandardLocation type)
xdgDataHome = QDir::homePath() + QLatin1String("/.qttest/share");
if (xdgDataHome.isEmpty())
xdgDataHome = QDir::homePath() + QLatin1String("/.local/share");
- if (type == QStandardPaths::DataLocation)
+ if (type == AppDataLocation || type == AppLocalDataLocation)
appendOrganizationAndApp(xdgDataHome);
return xdgDataHome;
}
@@ -305,7 +306,8 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
for (int i = 0; i < dirs.count(); ++i)
dirs[i].append(QLatin1String("/applications"));
break;
- case DataLocation:
+ case AppDataLocation:
+ case AppLocalDataLocation:
dirs = xdgDataDirs();
for (int i = 0; i < dirs.count(); ++i)
appendOrganizationAndApp(dirs[i]);
diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp
index 062ab49207..aaa390ac34 100644
--- a/src/corelib/io/qstandardpaths_win.cpp
+++ b/src/corelib/io/qstandardpaths_win.cpp
@@ -81,6 +81,18 @@ static QString convertCharArray(const wchar_t *path)
return QDir::fromNativeSeparators(QString::fromWCharArray(path));
}
+static inline int clsidForAppDataLocation(QStandardPaths::StandardLocation type)
+{
+#ifndef Q_OS_WINCE
+ return type == QStandardPaths::AppDataLocation ?
+ CSIDL_APPDATA : // "Roaming" path
+ CSIDL_LOCAL_APPDATA; // Local path
+#else
+ Q_UNUSED(type)
+ return CSIDL_APPDATA;
+#endif
+}
+
QString QStandardPaths::writableLocation(StandardLocation type)
{
QString result;
@@ -92,15 +104,12 @@ QString QStandardPaths::writableLocation(StandardLocation type)
wchar_t path[MAX_PATH];
switch (type) {
- case ConfigLocation: // same as DataLocation, on Windows (oversight, but too late to fix it)
- case GenericConfigLocation: // same as GenericDataLocation, on Windows
- case DataLocation:
+ case ConfigLocation: // same as AppLocalDataLocation, on Windows
+ case GenericConfigLocation: // same as GenericDataLocation on Windows
+ case AppDataLocation:
+ case AppLocalDataLocation:
case GenericDataLocation:
-#if defined Q_OS_WINCE
- if (SHGetSpecialFolderPath(0, path, CSIDL_APPDATA, FALSE))
-#else
- if (SHGetSpecialFolderPath(0, path, CSIDL_LOCAL_APPDATA, FALSE))
-#endif
+ if (SHGetSpecialFolderPath(0, path, clsidForAppDataLocation(type), FALSE))
result = convertCharArray(path);
if (isTestModeEnabled())
result += QLatin1String("/qttest");
@@ -165,7 +174,7 @@ QString QStandardPaths::writableLocation(StandardLocation type)
// Although Microsoft has a Cache key it is a pointer to IE's cache, not a cache
// location for everyone. Most applications seem to be using a
// cache directory located in their AppData directory
- return writableLocation(DataLocation) + QLatin1String("/cache");
+ return writableLocation(AppLocalDataLocation) + QLatin1String("/cache");
case GenericCacheLocation:
return writableLocation(GenericDataLocation) + QLatin1String("/cache");
@@ -192,11 +201,12 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
{
wchar_t path[MAX_PATH];
switch (type) {
- case ConfigLocation: // same as DataLocation, on Windows (oversight, but too late to fix it)
+ case ConfigLocation: // same as AppLocalDataLocation, on Windows (oversight, but too late to fix it)
case GenericConfigLocation: // same as GenericDataLocation, on Windows
- case DataLocation:
+ case AppDataLocation:
+ case AppLocalDataLocation:
case GenericDataLocation:
- if (SHGetSpecialFolderPath(0, path, CSIDL_COMMON_APPDATA, FALSE)) {
+ if (SHGetSpecialFolderPath(0, path, clsidForAppDataLocation(type), FALSE)) {
QString result = convertCharArray(path);
if (type != GenericDataLocation && type != GenericConfigLocation) {
#ifndef QT_BOOTSTRAPPED
diff --git a/src/corelib/io/qstandardpaths_winrt.cpp b/src/corelib/io/qstandardpaths_winrt.cpp
index feafdf2e7c..81b9d10baf 100644
--- a/src/corelib/io/qstandardpaths_winrt.cpp
+++ b/src/corelib/io/qstandardpaths_winrt.cpp
@@ -73,9 +73,10 @@ QString QStandardPaths::writableLocation(StandardLocation type)
QString result;
switch (type) {
- case ConfigLocation: // same as DataLocation, on Windows
+ case ConfigLocation: // same as AppLocalDataLocation, on Windows
case GenericConfigLocation: // same as GenericDataLocation, on Windows
- case DataLocation:
+ case AppDataLocation:
+ case AppLocalDataLocation:
case GenericDataLocation: {
ComPtr<IApplicationDataStatics> applicationDataStatics;
if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_ApplicationData).Get(), &applicationDataStatics)))
@@ -98,7 +99,7 @@ QString QStandardPaths::writableLocation(StandardLocation type)
break;
}
case CacheLocation:
- return writableLocation(DataLocation) + QLatin1String("/cache");
+ return writableLocation(AppLocalDataLocation) + QLatin1String("/cache");
case GenericCacheLocation:
return writableLocation(GenericDataLocation) + QLatin1String("/cache");
diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
index 3cade0ed25..bc6c2f1f06 100644
--- a/src/corelib/io/qtemporaryfile.cpp
+++ b/src/corelib/io/qtemporaryfile.cpp
@@ -235,6 +235,8 @@ static bool createFileFromTemplate(NativeFileHandle &file,
//************* QTemporaryFileEngine
QTemporaryFileEngine::~QTemporaryFileEngine()
{
+ Q_D(QFSFileEngine);
+ d->unmapAll();
QFSFileEngine::close();
}
@@ -363,6 +365,7 @@ bool QTemporaryFileEngine::remove()
Q_D(QFSFileEngine);
// Since the QTemporaryFileEngine::close() does not really close the file,
// we must explicitly call QFSFileEngine::close() before we remove it.
+ d->unmapAll();
QFSFileEngine::close();
if (QFSFileEngine::remove()) {
d->fileEntry.clear();
diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp
index 288a939ab2..4002ce8694 100644
--- a/src/corelib/io/qtextstream.cpp
+++ b/src/corelib/io/qtextstream.cpp
@@ -2203,7 +2203,7 @@ void QTextStreamPrivate::putNumber(qulonglong number, bool negative)
// add thousands group separators. For backward compatibility we
// don't add a group separator for C locale.
- if (locale != QLocale::c())
+ if (locale != QLocale::c() && !locale.numberOptions().testFlag(QLocale::OmitGroupSeparator))
flags |= QLocaleData::ThousandsGroup;
const QLocaleData *dd = locale.d->m_data;
@@ -2414,6 +2414,8 @@ QTextStream &QTextStream::operator<<(double f)
flags |= QLocaleData::CapitalEorX;
if (numberFlags() & ForcePoint)
flags |= QLocaleData::Alternate;
+ if (locale() != QLocale::c() && !(locale().numberOptions() & QLocale::OmitGroupSeparator))
+ flags |= QLocaleData::ThousandsGroup;
const QLocaleData *dd = d->locale.d->m_data;
QString num = dd->doubleToString(f, d->params.realNumberPrecision, form, -1, flags);
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index 7018b333f2..51c48b88d7 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -364,6 +364,29 @@
*/
/*!
+ \enum QUrl::UserInputResolutionOption
+ \since 5.4
+
+ The user input resolution options define how fromUserInput() should
+ interpret strings that could either be a relative path or the short
+ form of a HTTP URL. For instance \c{file.pl} can be either a local file
+ or the URL \c{http://file.pl}.
+
+ \value DefaultResolution The default resolution mechanism is to check
+ whether a local file exists, in the working
+ directory given to fromUserInput, and only
+ return a local path in that case. Otherwise a URL
+ is assumed.
+ \value AssumeLocalFile This option makes fromUserInput() always return
+ a local path unless the input contains a scheme, such as
+ \c{http://file.pl}. This is useful for applications
+ such as text editors, which are able to create
+ the file if it doesn't exist.
+
+ \sa fromUserInput()
+*/
+
+/*!
\fn QUrl::QUrl(QUrl &&other)
Move-constructs a QUrl instance, making it point at the same
@@ -3715,11 +3738,15 @@ bool QUrl::isDetached() const
"//servername/path/to/file.txt". Note that only certain platforms can
actually open this file using QFile::open().
+ An empty \a localFile leads to an empty URL (since Qt 5.4).
+
\sa toLocalFile(), isLocalFile(), QDir::toNativeSeparators()
*/
QUrl QUrl::fromLocalFile(const QString &localFile)
{
QUrl url;
+ if (localFile.isEmpty())
+ return url;
url.setScheme(fileScheme());
QString deslashified = QDir::fromNativeSeparators(localFile);
@@ -4095,6 +4122,43 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Returns a valid URL from a user supplied \a userInput string if one can be
deducted. In the case that is not possible, an invalid QUrl() is returned.
+ This overload takes a \a workingDirectory path, in order to be able to
+ handle relative paths. This is especially useful when handling command
+ line arguments.
+ If \a workingDirectory is empty, no handling of relative paths will be done,
+ so this method will behave like its one argument overload.
+
+ By default, an input string that looks like a relative path will only be treated
+ as such if the file actually exists in the given working directory.
+
+ If the application can handle files that don't exist yet, it should pass the
+ flag AssumeLocalFile in \a options.
+
+ \since 5.4
+*/
+QUrl QUrl::fromUserInput(const QString &userInput, const QString &workingDirectory,
+ UserInputResolutionOptions options)
+{
+ QString trimmedString = userInput.trimmed();
+
+ if (trimmedString.isEmpty())
+ return QUrl();
+
+ // Check both QUrl::isRelative (to detect full URLs) and QDir::isAbsolutePath (since on Windows drive letters can be interpreted as schemes)
+ QUrl url = QUrl(trimmedString, QUrl::TolerantMode);
+ if (url.isRelative() && !QDir::isAbsolutePath(trimmedString)) {
+ QFileInfo fileInfo(QDir(workingDirectory), trimmedString);
+ if ((options & AssumeLocalFile) || fileInfo.exists())
+ return QUrl::fromLocalFile(fileInfo.absoluteFilePath());
+ }
+
+ return fromUserInput(trimmedString);
+}
+
+/*!
+ Returns a valid URL from a user supplied \a userInput string if one can be
+ deducted. In the case that is not possible, an invalid QUrl() is returned.
+
\since 4.6
Most applications that can browse the web, allow the user to input a URL
diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h
index 602e91ce30..d621d7ef03 100644
--- a/src/corelib/io/qurl.h
+++ b/src/corelib/io/qurl.h
@@ -199,7 +199,16 @@ public:
QByteArray toEncoded(FormattingOptions options = FullyEncoded) const;
static QUrl fromEncoded(const QByteArray &url, ParsingMode mode = TolerantMode);
+ enum UserInputResolutionOption {
+ DefaultResolution,
+ AssumeLocalFile
+ };
+ Q_DECLARE_FLAGS(UserInputResolutionOptions, UserInputResolutionOption)
+
static QUrl fromUserInput(const QString &userInput);
+ // ### Qt6 merge with fromUserInput(QString), by adding = QString()
+ static QUrl fromUserInput(const QString &userInput, const QString &workingDirectory,
+ UserInputResolutionOptions options = DefaultResolution);
bool isValid() const;
QString errorString() const;
diff --git a/src/corelib/io/qwinoverlappedionotifier.cpp b/src/corelib/io/qwinoverlappedionotifier.cpp
index 33583afb78..06746c0597 100644
--- a/src/corelib/io/qwinoverlappedionotifier.cpp
+++ b/src/corelib/io/qwinoverlappedionotifier.cpp
@@ -41,6 +41,7 @@
#include "qwinoverlappedionotifier_p.h"
#include <qdebug.h>
+#include <qelapsedtimer.h>
#include <qmutex.h>
#include <qpointer.h>
#include <qqueue.h>
@@ -293,35 +294,58 @@ void QWinOverlappedIoNotifier::setEnabled(bool enabled)
}
/*!
- * Wait synchronously for the notified signal.
+ * Wait synchronously for any notified signal.
*
- * The function returns true if the notified signal was emitted for
- * the I/O operation that corresponds to the OVERLAPPED object.
+ * 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.
*/
-bool QWinOverlappedIoNotifier::waitForNotified(int msecs, OVERLAPPED *overlapped)
+OVERLAPPED *QWinOverlappedIoNotifier::waitForAnyNotified(int msecs)
{
Q_D(QWinOverlappedIoNotifier);
if (!d->iocp->isRunning()) {
- qWarning("Called QWinOverlappedIoNotifier::waitForNotified on inactive notifier.");
- return false;
+ qWarning("Called QWinOverlappedIoNotifier::waitForAnyNotified on inactive notifier.");
+ return 0;
}
+ if (msecs == 0)
+ d->iocp->drainQueue();
+
+ switch (WaitForSingleObject(d->hSemaphore, msecs == -1 ? INFINITE : DWORD(msecs))) {
+ case WAIT_OBJECT_0:
+ ReleaseSemaphore(d->hSemaphore, 1, NULL);
+ return d->_q_notified();
+ case WAIT_TIMEOUT:
+ return 0;
+ default:
+ qErrnoWarning("QWinOverlappedIoNotifier::waitForAnyNotified: WaitForSingleObject failed.");
+ return 0;
+ }
+}
+
+/*!
+ * 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)
+{
+ int t = msecs;
+ QElapsedTimer stopWatch;
+ stopWatch.start();
forever {
- if (msecs == 0)
- d->iocp->drainQueue();
- DWORD result = WaitForSingleObject(d->hSemaphore, msecs == -1 ? INFINITE : DWORD(msecs));
- if (result == WAIT_OBJECT_0) {
- ReleaseSemaphore(d->hSemaphore, 1, NULL);
- if (d->_q_notified() == overlapped)
- return true;
- continue;
- } else if (result == WAIT_TIMEOUT) {
+ OVERLAPPED *triggeredOverlapped = waitForAnyNotified(t);
+ if (!triggeredOverlapped)
return false;
+ if (triggeredOverlapped == overlapped)
+ return true;
+ if (msecs != -1) {
+ t = msecs - stopWatch.elapsed();
+ if (t < 0)
+ return false;
}
}
-
- qErrnoWarning("QWinOverlappedIoNotifier::waitForNotified: WaitForSingleObject failed.");
- return false;
}
/*!
diff --git a/src/corelib/io/qwinoverlappedionotifier_p.h b/src/corelib/io/qwinoverlappedionotifier_p.h
index f90fd2e615..25c0f3a081 100644
--- a/src/corelib/io/qwinoverlappedionotifier_p.h
+++ b/src/corelib/io/qwinoverlappedionotifier_p.h
@@ -76,6 +76,7 @@ public:
Qt::HANDLE handle() const;
void setEnabled(bool enabled);
+ OVERLAPPED *waitForAnyNotified(int msecs);
bool waitForNotified(int msecs, OVERLAPPED *overlapped);
Q_SIGNALS:
diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp
index ad5722626e..fd70bcddce 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.cpp
+++ b/src/corelib/itemmodels/qabstractitemmodel.cpp
@@ -990,9 +990,9 @@ void QAbstractItemModel::resetInternalData()
*/
/*!
- \fn void *QModelIndex::internalId() const
+ \fn quintptr QModelIndex::internalId() const
- Returns a \c{qint64} used by the model to associate
+ Returns a \c{quintptr} used by the model to associate
the index with the internal data structure.
\sa QAbstractItemModel::createIndex()
diff --git a/src/corelib/itemmodels/qabstractproxymodel.cpp b/src/corelib/itemmodels/qabstractproxymodel.cpp
index 2f1f4921f7..5250e2bf15 100644
--- a/src/corelib/itemmodels/qabstractproxymodel.cpp
+++ b/src/corelib/itemmodels/qabstractproxymodel.cpp
@@ -394,6 +394,30 @@ QMimeData* QAbstractProxyModel::mimeData(const QModelIndexList &indexes) const
/*!
\reimp
+ \since 5.4
+ */
+bool QAbstractProxyModel::canDropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent) const
+{
+ Q_D(const QAbstractProxyModel);
+ const QModelIndex source = mapToSource(index(row, column, parent));
+ return d->model->canDropMimeData(data, action, source.row(), source.column(), source.parent());
+}
+
+/*!
+ \reimp
+ \since 5.4
+ */
+bool QAbstractProxyModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent)
+{
+ Q_D(QAbstractProxyModel);
+ const QModelIndex source = mapToSource(index(row, column, parent));
+ return d->model->dropMimeData(data, action, source.row(), source.column(), source.parent());
+}
+
+/*!
+ \reimp
*/
QStringList QAbstractProxyModel::mimeTypes() const
{
diff --git a/src/corelib/itemmodels/qabstractproxymodel.h b/src/corelib/itemmodels/qabstractproxymodel.h
index 9b26d6cead..f1d3d0b07c 100644
--- a/src/corelib/itemmodels/qabstractproxymodel.h
+++ b/src/corelib/itemmodels/qabstractproxymodel.h
@@ -91,6 +91,10 @@ public:
QModelIndex sibling(int row, int column, const QModelIndex &idx) const;
QMimeData* mimeData(const QModelIndexList &indexes) const;
+ bool canDropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent) const Q_DECL_OVERRIDE;
+ bool dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent) Q_DECL_OVERRIDE;
QStringList mimeTypes() const;
Qt::DropActions supportedDropActions() const;
diff --git a/src/corelib/itemmodels/qitemselectionmodel.cpp b/src/corelib/itemmodels/qitemselectionmodel.cpp
index 883aa5b982..0a75d5998a 100644
--- a/src/corelib/itemmodels/qitemselectionmodel.cpp
+++ b/src/corelib/itemmodels/qitemselectionmodel.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -979,6 +979,22 @@ static QItemSelection mergeIndexes(const QVector<QPersistentModelIndex> &indexes
/*!
\internal
+ Sort predicate function for QItemSelectionModelPrivate::_q_layoutChanged(),
+ sorting by parent first in addition to operator<(). This is to prevent
+ fragmentation of the selection by grouping indexes with the same row, column
+ of different parents next to each other, which may happen when a selection
+ spans sub-trees.
+*/
+static bool qt_PersistentModelIndexLessThan(const QPersistentModelIndex &i1, const QPersistentModelIndex &i2)
+{
+ const QModelIndex parent1 = i1.parent();
+ const QModelIndex parent2 = i2.parent();
+ return parent1 == parent2 ? i1 < i2 : parent1 < parent2;
+}
+
+/*!
+ \internal
+
Merge the selected indexes into selection ranges again.
*/
void QItemSelectionModelPrivate::_q_layoutChanged(const QList<QPersistentModelIndex> &, QAbstractItemModel::LayoutChangeHint hint)
@@ -1011,8 +1027,10 @@ void QItemSelectionModelPrivate::_q_layoutChanged(const QList<QPersistentModelIn
if (hint != QAbstractItemModel::VerticalSortHint) {
// sort the "new" selection, as preparation for merging
- std::stable_sort(savedPersistentIndexes.begin(), savedPersistentIndexes.end());
- std::stable_sort(savedPersistentCurrentIndexes.begin(), savedPersistentCurrentIndexes.end());
+ std::stable_sort(savedPersistentIndexes.begin(), savedPersistentIndexes.end(),
+ qt_PersistentModelIndexLessThan);
+ std::stable_sort(savedPersistentCurrentIndexes.begin(), savedPersistentCurrentIndexes.end(),
+ qt_PersistentModelIndexLessThan);
// update the selection by merging the individual indexes
ranges = mergeIndexes(savedPersistentIndexes);
diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h
index 7d0162938d..92330175ba 100644
--- a/src/corelib/json/qjson_p.h
+++ b/src/corelib/json/qjson_p.h
@@ -61,6 +61,8 @@
#include <qstring.h>
#include <qendian.h>
#include <qnumeric.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qmutex.h>
#include <limits.h>
#include <limits>
@@ -776,6 +778,75 @@ private:
Q_DISABLE_COPY(Data)
};
+struct ObjectUndefinedKeys
+{
+ static void insertKey(const QJsonObject *object, int index, const QString &key)
+ {
+ QMutexLocker lock(&mutex);
+ keys()[object][index] = key;
+ }
+ static QString takeKey(const QJsonObject *object, int index)
+ {
+ QMutexLocker lock(&mutex);
+ return keys()[object].take(index);
+ }
+ static void removeKeys(const QJsonObject *object)
+ {
+ QMutexLocker lock(&mutex);
+ keys().remove(object);
+ }
+private:
+ typedef QHash<const QJsonObject*, QHash<int, QString> > KeysHash;
+ static KeysHash &keys()
+ {
+ static KeysHash keys;
+ return keys;
+ }
+ static QBasicMutex mutex;
+};
+
+} // namespace QJsonPrivate
+
+struct QJsonValueRef::UnionHelper
+{
+ static inline QJsonObject *untaggedPointer(QJsonObject *object)
+ {
+ const quintptr Mask = ~quintptr(0) << 2;
+ return reinterpret_cast<QJsonObject*>(quintptr(object) & Mask);
+ }
+ static inline QJsonObject *taggedPointer(QJsonObject *object)
+ {
+ const quintptr Mask = 1;
+ return reinterpret_cast<QJsonObject*>(quintptr(object) | Mask);
+ }
+
+ static void setValueAt(QJsonValueRef *ref, QJsonValue value)
+ {
+ using namespace QJsonPrivate;
+ QJsonObject *object = untaggedPointer(ref->o);
+ if (ref->o != object)
+ object->insert(ObjectUndefinedKeys::takeKey(object, ref->index), value);
+ else
+ object->setValueAt(ref->index, value);
+ }
+
+ static QJsonValue valueAt(const QJsonValueRef *ref)
+ {
+ QJsonObject *object = untaggedPointer(ref->o);
+ if (ref->o != object)
+ return QJsonValue::Undefined;
+ return ref->o->valueAt(ref->index);
+ }
+};
+
+/*!
+ \internal
+ Constructor that creates reference to an undefined value in \a object.
+*/
+inline QJsonValueRef::QJsonValueRef(QJsonObject *object, const QString &key)
+ : o(UnionHelper::taggedPointer(object)), is_object(true), index(qHash(key))
+{
+ QJsonPrivate::ObjectUndefinedKeys::insertKey(object, index, key);
}
QT_END_NAMESPACE
diff --git a/src/corelib/json/qjsonarray.cpp b/src/corelib/json/qjsonarray.cpp
index 61bb158ff5..c1e831192a 100644
--- a/src/corelib/json/qjsonarray.cpp
+++ b/src/corelib/json/qjsonarray.cpp
@@ -138,6 +138,18 @@ QJsonArray::QJsonArray()
}
/*!
+ \fn QJsonArray::QJsonArray(std::initializer_list<QJsonValue> args)
+ \since 5.4
+ Creates an array initialized from \a args initialization list.
+
+ QJsonArray can be constructed in a way similar to JSON notation,
+ for example:
+ \code
+ QJsonArray array = { 1, 2.2, QString() };
+ \endcode
+ */
+
+/*!
\internal
*/
QJsonArray::QJsonArray(QJsonPrivate::Data *data, QJsonPrivate::Array *array)
@@ -149,6 +161,19 @@ QJsonArray::QJsonArray(QJsonPrivate::Data *data, QJsonPrivate::Array *array)
}
/*!
+ This method replaces part of QJsonArray(std::initializer_list<QJsonValue> args) .
+ The constructor needs to be inline, but we do not want to leak implementation details
+ of this class.
+ \note this method is called for an uninitialized object
+ \internal
+ */
+void QJsonArray::initialize()
+{
+ d = 0;
+ a = 0;
+}
+
+/*!
Deletes the array.
*/
QJsonArray::~QJsonArray()
diff --git a/src/corelib/json/qjsonarray.h b/src/corelib/json/qjsonarray.h
index 84c162f0a0..4cada7cec1 100644
--- a/src/corelib/json/qjsonarray.h
+++ b/src/corelib/json/qjsonarray.h
@@ -44,6 +44,9 @@
#include <QtCore/qjsonvalue.h>
#include <QtCore/qiterator.h>
+#if defined(Q_COMPILER_INITIALIZER_LISTS)
+#include <initializer_list>
+#endif
QT_BEGIN_NAMESPACE
@@ -56,6 +59,16 @@ class Q_CORE_EXPORT QJsonArray
{
public:
QJsonArray();
+
+#if defined(Q_COMPILER_INITIALIZER_LISTS) || defined(Q_QDOC)
+ QJsonArray(std::initializer_list<QJsonValue> args)
+ {
+ initialize();
+ for (std::initializer_list<QJsonValue>::const_iterator i = args.begin(); i != args.end(); ++i)
+ append(*i);
+ }
+#endif
+
~QJsonArray();
QJsonArray(const QJsonArray &other);
@@ -212,6 +225,7 @@ private:
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonArray &);
QJsonArray(QJsonPrivate::Data *data, QJsonPrivate::Array *array);
+ void initialize();
void compact();
void detach(uint reserve = 0);
diff --git a/src/corelib/json/qjsondocument.cpp b/src/corelib/json/qjsondocument.cpp
index 90ce8c63a5..097e665b68 100644
--- a/src/corelib/json/qjsondocument.cpp
+++ b/src/corelib/json/qjsondocument.cpp
@@ -331,7 +331,7 @@ QByteArray QJsonDocument::toJson() const
\value Compact Defines a compact output as follows:
\code
- {"Array": [true,999,"string"],"Key": "Value","null": null}
+ {"Array":[true,999,"string"],"Key":"Value","null":null}
\endcode
*/
diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/json/qjsonobject.cpp
index 27e51cf4ac..94ec9a2818 100644
--- a/src/corelib/json/qjsonobject.cpp
+++ b/src/corelib/json/qjsonobject.cpp
@@ -134,6 +134,7 @@ QJsonObject::~QJsonObject()
{
if (d && !d->ref.deref())
delete d;
+ QJsonPrivate::ObjectUndefinedKeys::removeKeys(this); // ### Qt6 move it to ~QJsonValueRef
}
/*!
@@ -254,7 +255,7 @@ bool QJsonObject::isEmpty() const
QJsonValue QJsonObject::value(const QString &key) const
{
if (!d)
- return QJsonValue();
+ return QJsonValue(QJsonValue::Undefined);
bool keyExists;
int i = o->indexOf(key, &keyExists);
@@ -290,14 +291,9 @@ QJsonValue QJsonObject::operator [](const QString &key) const
*/
QJsonValueRef QJsonObject::operator [](const QString &key)
{
- // ### somewhat inefficient, as we lookup the key twice if it doesn't yet exist
bool keyExists = false;
int index = o ? o->indexOf(key, &keyExists) : -1;
- if (!keyExists) {
- iterator i = insert(key, QJsonValue());
- index = i.i;
- }
- return QJsonValueRef(this, index);
+ return keyExists ? QJsonValueRef(this, index) : QJsonValueRef(this, key);
}
/*!
@@ -1001,7 +997,9 @@ void QJsonObject::compact()
detach();
d->compact();
- o = static_cast<QJsonPrivate::Object *>(d->header->root());
+ using namespace QJsonPrivate;
+ o = static_cast<Object *>(d->header->root());
+ ObjectUndefinedKeys::removeKeys(this); // ### Qt6 move it to ~QJsonValueRef
}
/*!
@@ -1038,6 +1036,8 @@ void QJsonObject::setValueAt(int i, const QJsonValue &val)
insert(e->key(), val);
}
+QBasicMutex QJsonPrivate::ObjectUndefinedKeys::mutex;
+
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
QDebug operator<<(QDebug dbg, const QJsonObject &o)
{
diff --git a/src/corelib/json/qjsonvalue.cpp b/src/corelib/json/qjsonvalue.cpp
index 4c4838d314..6e40308de3 100644
--- a/src/corelib/json/qjsonvalue.cpp
+++ b/src/corelib/json/qjsonvalue.cpp
@@ -606,15 +606,19 @@ bool QJsonValue::operator==(const QJsonValue &other) const
case Array:
if (base == other.base)
return true;
- if (!base || !other.base)
- return false;
+ if (!base)
+ return !other.base->length;
+ if (!other.base)
+ return !base->length;
return QJsonArray(d, static_cast<QJsonPrivate::Array *>(base))
== QJsonArray(other.d, static_cast<QJsonPrivate::Array *>(other.base));
case Object:
if (base == other.base)
return true;
- if (!base || !other.base)
- return false;
+ if (!base)
+ return !other.base->length;
+ if (!other.base)
+ return !base->length;
return QJsonObject(d, static_cast<QJsonPrivate::Object *>(base))
== QJsonObject(other.d, static_cast<QJsonPrivate::Object *>(other.base));
}
@@ -669,11 +673,10 @@ void QJsonValue::detach()
However, they are not explicitly documented here.
*/
-
QJsonValueRef &QJsonValueRef::operator =(const QJsonValue &val)
{
if (is_object)
- o->setValueAt(index, val);
+ UnionHelper::setValueAt(this, val);
else
a->replace(index, val);
@@ -683,7 +686,7 @@ QJsonValueRef &QJsonValueRef::operator =(const QJsonValue &val)
QJsonValueRef &QJsonValueRef::operator =(const QJsonValueRef &ref)
{
if (is_object)
- o->setValueAt(index, ref);
+ UnionHelper::setValueAt(this, ref);
else
a->replace(index, ref);
@@ -704,7 +707,7 @@ QJsonValue QJsonValueRef::toValue() const
{
if (!is_object)
return a->at(index);
- return o->valueAt(index);
+ return UnionHelper::valueAt(this);
}
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
diff --git a/src/corelib/json/qjsonvalue.h b/src/corelib/json/qjsonvalue.h
index fe028990c0..a00bc0b72f 100644
--- a/src/corelib/json/qjsonvalue.h
+++ b/src/corelib/json/qjsonvalue.h
@@ -149,6 +149,7 @@ public:
: a(array), is_object(false), index(idx) {}
QJsonValueRef(QJsonObject *object, int idx)
: o(object), is_object(true), index(idx) {}
+ inline QJsonValueRef(QJsonObject *object, const QString &key);
inline operator QJsonValue() const { return toValue(); }
QJsonValueRef &operator = (const QJsonValue &val);
@@ -170,6 +171,12 @@ public:
QJsonArray toArray() const;
QJsonObject toObject() const;
+ // ### Qt 6: Add default values
+ inline bool toBool(bool defaultValue) const { return toValue().toBool(defaultValue); }
+ inline int toInt(int defaultValue) const { return toValue().toInt(defaultValue); }
+ inline double toDouble(double defaultValue) const { return toValue().toDouble(defaultValue); }
+ inline QString toString(const QString &defaultValue) const { return toValue().toString(defaultValue); }
+
inline bool operator==(const QJsonValue &other) const { return toValue() == other; }
inline bool operator!=(const QJsonValue &other) const { return toValue() != other; }
@@ -182,6 +189,7 @@ private:
};
uint is_object : 1;
uint index : 31;
+ struct UnionHelper;
};
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 6868eb6a1e..7f2e28e800 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -71,6 +71,7 @@
#include <private/qfactoryloader_p.h>
#include <private/qfunctions_p.h>
#include <private/qlocale_p.h>
+#include <private/qhooks_p.h>
#ifndef QT_NO_QOBJECT
#if defined(Q_OS_UNIX)
@@ -564,8 +565,8 @@ void QCoreApplicationPrivate::initLocale()
/*!
\class QCoreApplication
\inmodule QtCore
- \brief The QCoreApplication class provides an event loop for console Qt
- applications.
+ \brief The QCoreApplication class provides an event loop for Qt
+ applications without UI.
This class is used by non-GUI applications to provide their event
loop. For non-GUI application that uses Qt, there should be exactly
@@ -765,6 +766,10 @@ void QCoreApplication::init()
qt_call_pre_routines();
qt_startup_hook();
+#ifndef QT_BOOTSTRAPPED
+ if (Q_UNLIKELY(qtHookData[QHooks::Startup]))
+ reinterpret_cast<QHooks::StartupCallback>(qtHookData[QHooks::Startup])();
+#endif
#ifndef QT_NO_QOBJECT
QCoreApplicationPrivate::is_app_running = true; // No longer starting up.
diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h
index d8c52fbf1d..195c8da43f 100644
--- a/src/corelib/kernel/qcoreapplication.h
+++ b/src/corelib/kernel/qcoreapplication.h
@@ -219,7 +219,6 @@ private:
friend class QApplicationPrivate;
friend class QGuiApplication;
friend class QGuiApplicationPrivate;
- friend class QETWidget;
friend class QWidget;
friend class QWidgetWindow;
friend class QWidgetPrivate;
diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h
index d784267a65..f0c9e4e1c2 100644
--- a/src/corelib/kernel/qcoreapplication_p.h
+++ b/src/corelib/kernel/qcoreapplication_p.h
@@ -96,6 +96,7 @@ public:
bool sendThroughApplicationEventFilters(QObject *, QEvent *);
bool sendThroughObjectEventFilters(QObject *, QEvent *);
bool notify_helper(QObject *, QEvent *);
+ static inline void setEventSpontaneous(QEvent *e, bool spontaneous) { e->spont = spontaneous; }
virtual void createEventDispatcher();
virtual void eventDispatcherReady();
diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp
index 65ca6b0dcb..0ce3f00472 100644
--- a/src/corelib/kernel/qcoreapplication_win.cpp
+++ b/src/corelib/kernel/qcoreapplication_win.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -145,14 +145,30 @@ QString QCoreApplicationPrivate::appName() const
qWinMain() - Initializes Windows. Called from WinMain() in qtmain_win.cpp
*****************************************************************************/
-#if defined(Q_OS_WINCE)
-Q_CORE_EXPORT void __cdecl qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
- int cmdShow, int &argc, QVector<char *> &argv)
-#else
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+
+// ### Qt6: FIXME: Remove this function. It is only there since for binary
+// compatibility for applications built with Qt 5.3 using qtmain.lib which calls it.
+// In Qt 5.4, qtmain.lib was changed to use CommandLineToArgvW() without calling into Qt5Core.
Q_CORE_EXPORT
void qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
+ int cmdShow, int &argc, QVector<char *> &argv)
+{
+ Q_UNUSED(instance)
+ Q_UNUSED(prevInstance)
+ Q_UNUSED(cmdShow)
+
+ const QStringList wArgv = qWinCmdArgs(QString::fromLocal8Bit(cmdParam));
+ argv.clear();
+ argc = wArgv.size();
+ foreach (const QString &wArg, wArgv)
+ argv.append(_strdup(wArg.toLocal8Bit().constData()));
+}
+
+#elif defined(Q_OS_WINCE)
+
+Q_CORE_EXPORT void __cdecl qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
int cmdShow, int &argc, QVector<char *> &argv)
-#endif
{
static bool already_called = false;
@@ -172,6 +188,8 @@ void qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
Q_UNUSED(prevInstance);
}
+#endif // Q_OS_WINCE
+
#ifndef QT_NO_QOBJECT
void QCoreApplicationPrivate::removePostedTimerEvent(QObject *object, int timerId)
diff --git a/src/corelib/kernel/qcorecmdlineargs_p.h b/src/corelib/kernel/qcorecmdlineargs_p.h
index 93c80205ab..84d9be20e5 100644
--- a/src/corelib/kernel/qcorecmdlineargs_p.h
+++ b/src/corelib/kernel/qcorecmdlineargs_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -56,14 +56,34 @@
#include "QtCore/qstring.h"
#include "QtCore/qstringlist.h"
+#if defined(Q_OS_WIN)
+# ifdef Q_OS_WIN32
+# include <qt_windows.h> // first to suppress min, max macros.
+# include <shlobj.h>
+# else
+# include "QtCore/qvector.h"
+# include <qt_windows.h>
+# endif
+
QT_BEGIN_NAMESPACE
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+#if defined(Q_OS_WIN32)
+
+static inline QStringList qWinCmdArgs(const QString &cmdLine)
+{
+ QStringList result;
+ int size;
+ if (wchar_t **argv = CommandLineToArgvW((const wchar_t *)cmdLine.utf16(), &size)) {
+ result.reserve(size);
+ wchar_t **argvEnd = argv + size;
+ for (wchar_t **a = argv; a < argvEnd; ++a)
+ result.append(QString::fromWCharArray(*a));
+ LocalFree(argv);
+ }
+ return result;
+}
-QT_BEGIN_INCLUDE_NAMESPACE
-# include "QtCore/qvector.h"
-# include <qt_windows.h>
-QT_END_INCLUDE_NAMESPACE
+#elif defined(Q_OS_WINCE) // Q_OS_WIN32
// template implementation of the parsing algorithm
// this is used from qcoreapplication_win.cpp and the tools (rcc, uic...)
@@ -149,7 +169,7 @@ static inline QStringList qCmdLineArgs(int argc, char *argv[])
return qWinCmdArgs(cmdLine);
}
-#else // Q_OS_WIN && !Q_OS_WINRT
+#elif defined(Q_OS_WINRT) // Q_OS_WINCE
static inline QStringList qCmdLineArgs(int argc, char *argv[])
{
@@ -159,8 +179,10 @@ static inline QStringList qCmdLineArgs(int argc, char *argv[])
return args;
}
-#endif // !Q_OS_WIN || Q_OS_WINRT
+#endif // Q_OS_WINRT
QT_END_NAMESPACE
+#endif // Q_OS_WIN
+
#endif // QCORECMDLINEARGS_WIN_P_H
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
index edf262b8af..8d5a39115a 100644
--- a/src/corelib/kernel/qcoreevent.cpp
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -43,8 +43,9 @@
#include "qcoreapplication.h"
#include "qcoreapplication_p.h"
-#include "qmutex.h"
-#include "qset.h"
+#include "qbasicatomic.h"
+
+#include <limits>
QT_BEGIN_NAMESPACE
@@ -192,6 +193,7 @@ QT_BEGIN_NAMESPACE
\value Polish The widget is polished.
\value PolishRequest The widget should be polished.
\value QueryWhatsThis The widget should accept the event if it has "What's This?" help.
+ \value ReadOnlyChange Widget's read-only state has changed (since Qt 5.4).
\value RequestSoftwareInputPanel A widget wants to open a software input panel (SIP).
\value Resize Widget's size changed (QResizeEvent).
\value ScrollPrepare The object needs to fill in its geometry information (QScrollPrepareEvent).
@@ -389,13 +391,71 @@ QEvent::~QEvent()
The return value of this function is not defined for paint events.
*/
-class QEventUserEventRegistration
-{
-public:
- QMutex mutex;
- QSet<int> set;
+namespace {
+template <size_t N>
+struct QBasicAtomicBitField {
+ enum {
+ BitsPerInt = std::numeric_limits<uint>::digits,
+ NumInts = (N + BitsPerInt - 1) / BitsPerInt,
+ NumBits = N
+ };
+
+ // This atomic int points to the next (possibly) free ID saving
+ // the otherwise necessary scan through 'data':
+ QBasicAtomicInteger<uint> next;
+ QBasicAtomicInteger<uint> data[NumInts];
+
+ bool allocateSpecific(int which) Q_DECL_NOTHROW
+ {
+ QBasicAtomicInteger<uint> &entry = data[which / BitsPerInt];
+ const uint old = entry.load();
+ const uint bit = 1U << (which % BitsPerInt);
+ return !(old & bit) // wasn't taken
+ && entry.testAndSetRelaxed(old, old | bit); // still wasn't taken
+
+ // don't update 'next' here - it's unlikely that it will need
+ // to be updated, in the general case, and having 'next'
+ // trailing a bit is not a problem, as it is just a starting
+ // hint for allocateNext(), which, when wrong, will just
+ // result in a few more rounds through the allocateNext()
+ // loop.
+ }
+
+ int allocateNext() Q_DECL_NOTHROW
+ {
+ // Unroll loop to iterate over ints, then bits? Would save
+ // potentially a lot of cmpxchgs, because we can scan the
+ // whole int before having to load it again.
+
+ // Then again, this should never execute many iterations, so
+ // leave like this for now:
+ for (uint i = next.load(); i < NumBits; ++i) {
+ if (allocateSpecific(i)) {
+ // remember next (possibly) free id:
+ const uint oldNext = next.load();
+ next.testAndSetRelaxed(oldNext, qMax(i + 1, oldNext));
+ return i;
+ }
+ }
+ return -1;
+ }
};
-Q_GLOBAL_STATIC(QEventUserEventRegistration, userEventRegistrationHelper)
+
+} // unnamed namespace
+
+typedef QBasicAtomicBitField<QEvent::MaxUser - QEvent::User + 1> UserEventTypeRegistry;
+
+static UserEventTypeRegistry userEventTypeRegistry;
+
+static inline int registerEventTypeZeroBased(int id) Q_DECL_NOTHROW
+{
+ // if the type hint hasn't been registered yet, take it:
+ if (id < UserEventTypeRegistry::NumBits && id >= 0 && userEventTypeRegistry.allocateSpecific(id))
+ return id;
+
+ // otherwise, ignore hint:
+ return userEventTypeRegistry.allocateNext();
+}
/*!
\since 4.4
@@ -410,30 +470,10 @@ Q_GLOBAL_STATIC(QEventUserEventRegistration, userEventRegistrationHelper)
Returns -1 if all available values are already taken or the
program is shutting down.
*/
-int QEvent::registerEventType(int hint)
+int QEvent::registerEventType(int hint) Q_DECL_NOTHROW
{
- QEventUserEventRegistration *userEventRegistration
- = userEventRegistrationHelper();
- if (!userEventRegistration)
- return -1;
-
- QMutexLocker locker(&userEventRegistration->mutex);
-
- // if the type hint hasn't been registered yet, take it
- if (hint >= QEvent::User && hint <= QEvent::MaxUser && !userEventRegistration->set.contains(hint)) {
- userEventRegistration->set.insert(hint);
- return hint;
- }
-
- // find a free event type, starting at MaxUser and decreasing
- int id = QEvent::MaxUser;
- while (userEventRegistration->set.contains(id) && id >= QEvent::User)
- --id;
- if (id >= QEvent::User) {
- userEventRegistration->set.insert(id);
- return id;
- }
- return -1;
+ const int result = registerEventTypeZeroBased(QEvent::MaxUser - hint);
+ return result < 0 ? -1 : QEvent::MaxUser - result ;
}
/*!
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
index 8b58fdf55f..cd7689f842 100644
--- a/src/corelib/kernel/qcoreevent.h
+++ b/src/corelib/kernel/qcoreevent.h
@@ -150,6 +150,8 @@ public:
WindowUnblocked = 104, // windows modal blocking has ended
WindowStateChange = 105,
+ ReadOnlyChange = 106, // readonly state has changed
+
ToolTip = 110,
WhatsThis = 111,
StatusTip = 112,
@@ -300,7 +302,7 @@ public:
inline void accept() { m_accept = true; }
inline void ignore() { m_accept = false; }
- static int registerEventType(int hint = -1);
+ static int registerEventType(int hint = -1) Q_DECL_NOTHROW;
protected:
QEventPrivate *d;
@@ -316,17 +318,10 @@ private:
friend class QCoreApplicationPrivate;
friend class QThreadData;
friend class QApplication;
- friend class QApplicationPrivate;
friend class QShortcutMap;
- friend class QETWidget;
friend class QGraphicsView;
- friend class QGraphicsViewPrivate;
friend class QGraphicsScene;
friend class QGraphicsScenePrivate;
- friend class QWidgetWindow;
-#ifndef QT_NO_GESTURES
- friend class QGestureManager;
-#endif
};
class Q_CORE_EXPORT QTimerEvent : public QEvent
diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp
index 1d4b57642c..91a97885ee 100644
--- a/src/corelib/kernel/qeventdispatcher_winrt.cpp
+++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp
@@ -44,6 +44,7 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QThread>
#include <QtCore/QHash>
+#include <QtCore/qfunctions_winrt.h>
#include <private/qabstracteventdispatcher_p.h>
#include <private/qcoreapplication_p.h>
@@ -71,8 +72,44 @@ public:
struct WinRTTimerInfo // internal timer info
{
- WinRTTimerInfo() : timer(0) {}
+ WinRTTimerInfo(int timerId, int timerInterval, Qt::TimerType timerType, QObject *object, QEventDispatcherWinRT *dispatcher)
+ : isFinished(false), id(timerId), interval(timerInterval), timerType(timerType), obj(object), inTimerEvent(false), dispatcher(dispatcher)
+ {
+ }
+
+ void cancel()
+ {
+ if (isFinished) {
+ delete this;
+ return;
+ }
+ isFinished = true;
+ if (!timer)
+ return;
+
+ HRESULT hr = timer->Cancel();
+ RETURN_VOID_IF_FAILED("Failed to cancel timer");
+ }
+
+ HRESULT timerExpired(IThreadPoolTimer *)
+ {
+ if (isFinished)
+ return S_OK;
+ if (dispatcher)
+ QCoreApplication::postEvent(dispatcher, new QTimerEvent(id));
+ return S_OK;
+ }
+ HRESULT timerDestroyed(IThreadPoolTimer *)
+ {
+ if (isFinished)
+ delete this;
+ else
+ isFinished = true;
+ return S_OK;
+ }
+
+ bool isFinished;
int id;
int interval;
Qt::TimerType timerType;
@@ -80,6 +117,7 @@ struct WinRTTimerInfo // internal timer info
QObject *obj; // - object to receive events
bool inTimerEvent;
ComPtr<IThreadPoolTimer> timer;
+ QPointer<QEventDispatcherWinRT> dispatcher;
};
class QEventDispatcherWinRTPrivate : public QAbstractEventDispatcherPrivate
@@ -90,15 +128,8 @@ public:
QEventDispatcherWinRTPrivate();
~QEventDispatcherWinRTPrivate();
- void registerTimer(WinRTTimerInfo *t);
- void unregisterTimer(WinRTTimerInfo *t);
- void sendTimerEvent(int timerId);
-
private:
- static HRESULT timerExpiredCallback(IThreadPoolTimer *timer);
-
QHash<int, WinRTTimerInfo*> timerDict;
- QHash<IThreadPoolTimer *, int> timerIds;
ComPtr<IThreadPoolTimerStatics> timerFactory;
ComPtr<ICoreDispatcher> coreDispatcher;
@@ -111,28 +142,22 @@ QEventDispatcherWinRT::QEventDispatcherWinRT(QObject *parent)
{
Q_D(QEventDispatcherWinRT);
- // Only look up the event dispatcher in the main thread
- if (QThread::currentThread() != QCoreApplicationPrivate::theMainThread)
- return;
-
- ComPtr<ICoreApplication> application;
+ // Obtain the WinRT Application, view, and window
+ ComPtr<ICoreImmersiveApplication> application;
HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
IID_PPV_ARGS(&application));
- if (SUCCEEDED(hr)) {
- ComPtr<ICoreApplicationView> view;
- hr = application->GetCurrentView(&view);
- if (SUCCEEDED(hr)) {
- ComPtr<ICoreWindow> window;
- hr = view->get_CoreWindow(&window);
- if (SUCCEEDED(hr)) {
- hr = window->get_Dispatcher(&d->coreDispatcher);
- if (SUCCEEDED(hr))
- return;
- }
- }
- }
- qCritical("QEventDispatcherWinRT: Unable to capture the core dispatcher. %s",
- qPrintable(qt_error_string(hr)));
+ RETURN_VOID_IF_FAILED("Failed to activate the application factory");
+
+ ComPtr<ICoreApplicationView> view;
+ hr = application->get_MainView(&view);
+ RETURN_VOID_IF_FAILED("Failed to get the main view");
+
+ ComPtr<ICoreWindow> window;
+ hr = view->get_CoreWindow(&window);
+ RETURN_VOID_IF_FAILED("Failed to get the core window");
+
+ hr = window->get_Dispatcher(&d->coreDispatcher);
+ RETURN_VOID_IF_FAILED("Failed to get the core dispatcher");
}
QEventDispatcherWinRT::QEventDispatcherWinRT(QEventDispatcherWinRTPrivate &dd, QObject *parent)
@@ -150,8 +175,15 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
bool didProcess = false;
forever {
// Process native events
- if (d->coreDispatcher)
- d->coreDispatcher->ProcessEvents(CoreProcessEventsOption_ProcessAllIfPresent);
+ if (d->coreDispatcher) {
+ boolean hasThreadAccess;
+ HRESULT hr = d->coreDispatcher->get_HasThreadAccess(&hasThreadAccess);
+ if (SUCCEEDED(hr) && hasThreadAccess) {
+ hr = d->coreDispatcher->ProcessEvents(CoreProcessEventsOption_ProcessAllIfPresent);
+ if (FAILED(hr))
+ qErrnoWarning(hr, "Failed to process events");
+ }
+ }
// Dispatch accumulated user events
didProcess = sendPostedEvents(flags);
@@ -162,13 +194,12 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
break;
// Short sleep if there is nothing to do
- if (flags & QEventLoop::WaitForMoreEvents) {
- emit aboutToBlock();
- WaitForSingleObjectEx(GetCurrentThread(), 1, FALSE);
- emit awake();
- } else {
+ if (!(flags & QEventLoop::WaitForMoreEvents))
break;
- }
+
+ emit aboutToBlock();
+ WaitForSingleObjectEx(GetCurrentThread(), 1, FALSE);
+ emit awake();
}
d->interrupt = false;
return didProcess;
@@ -213,15 +244,28 @@ void QEventDispatcherWinRT::registerTimer(int timerId, int interval, Qt::TimerTy
}
Q_D(QEventDispatcherWinRT);
- WinRTTimerInfo *t = new WinRTTimerInfo();
- t->id = timerId;
- t->interval = interval;
- t->timerType = timerType;
- t->obj = object;
- t->inTimerEvent = false;
-
- d->registerTimer(t);
+
+ WinRTTimerInfo *t = new WinRTTimerInfo(timerId, interval, timerType, object, this);
+ t->timeout = qt_msectime() + interval;
d->timerDict.insert(t->id, t);
+
+ // Don't use timer factory for zero-delay timers
+ if (interval == 0u) {
+ QCoreApplication::postEvent(this, new QZeroTimerEvent(timerId));
+ return;
+ }
+
+ TimeSpan period;
+ period.Duration = interval ? (interval * 10000) : 1; // TimeSpan is based on 100-nanosecond units
+ HRESULT hr = d->timerFactory->CreatePeriodicTimerWithCompletion(
+ Callback<ITimerElapsedHandler>(t, &WinRTTimerInfo::timerExpired).Get(), period,
+ Callback<ITimerDestroyedHandler>(t, &WinRTTimerInfo::timerDestroyed).Get(), &t->timer);
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Failed to create periodic timer");
+ delete t;
+ d->timerDict.remove(t->id);
+ return;
+ }
}
bool QEventDispatcherWinRT::unregisterTimer(int timerId)
@@ -237,11 +281,11 @@ bool QEventDispatcherWinRT::unregisterTimer(int timerId)
Q_D(QEventDispatcherWinRT);
- WinRTTimerInfo *t = d->timerDict.value(timerId);
+ WinRTTimerInfo *t = d->timerDict.take(timerId);
if (!t)
return false;
- d->unregisterTimer(t);
+ t->cancel();
return true;
}
@@ -258,9 +302,13 @@ bool QEventDispatcherWinRT::unregisterTimers(QObject *object)
}
Q_D(QEventDispatcherWinRT);
- foreach (WinRTTimerInfo *t, d->timerDict) {
- if (t->obj == object)
- d->unregisterTimer(t);
+ for (QHash<int, WinRTTimerInfo *>::iterator it = d->timerDict.begin(); it != d->timerDict.end();) {
+ if (it.value()->obj == object) {
+ it.value()->cancel();
+ it = d->timerDict.erase(it);
+ continue;
+ }
+ ++it;
}
return true;
}
@@ -341,40 +389,41 @@ void QEventDispatcherWinRT::startingUp()
void QEventDispatcherWinRT::closingDown()
{
Q_D(QEventDispatcherWinRT);
- foreach (WinRTTimerInfo *t, d->timerDict)
- d->unregisterTimer(t);
d->timerDict.clear();
- d->timerIds.clear();
}
bool QEventDispatcherWinRT::event(QEvent *e)
{
Q_D(QEventDispatcherWinRT);
- if (e->type() == QEvent::ZeroTimerEvent) {
- QZeroTimerEvent *zte = static_cast<QZeroTimerEvent*>(e);
- WinRTTimerInfo *t = d->timerDict.value(zte->timerId());
- if (t) {
+ bool ret = false;
+ switch (e->type()) {
+ case QEvent::ZeroTimerEvent:
+ ret = true;
+ // fall through
+ case QEvent::Timer: {
+ QTimerEvent *timerEvent = static_cast<QTimerEvent *>(e);
+ const int id = timerEvent->timerId();
+ if (WinRTTimerInfo *t = d->timerDict.value(id)) {
+ if (t->inTimerEvent) // but don't allow event to recurse
+ break;
t->inTimerEvent = true;
- QTimerEvent te(zte->timerId());
+ QTimerEvent te(id);
QCoreApplication::sendEvent(t->obj, &te);
- t = d->timerDict.value(zte->timerId());
- if (t) {
+ if (t = d->timerDict.value(id)) {
if (t->interval == 0 && t->inTimerEvent) {
// post the next zero timer event as long as the timer was not restarted
- QCoreApplication::postEvent(this, new QZeroTimerEvent(zte->timerId()));
+ QCoreApplication::postEvent(this, new QZeroTimerEvent(id));
}
-
t->inTimerEvent = false;
}
}
- return true;
- } else if (e->type() == QEvent::Timer) {
- QTimerEvent *te = static_cast<QTimerEvent*>(e);
- d->sendTimerEvent(te->timerId());
}
- return QAbstractEventDispatcher::event(e);
+ default:
+ break;
+ }
+ return ret ? true : QAbstractEventDispatcher::event(e);
}
QEventDispatcherWinRTPrivate::QEventDispatcherWinRTPrivate()
@@ -391,73 +440,4 @@ QEventDispatcherWinRTPrivate::~QEventDispatcherWinRTPrivate()
CoUninitialize();
}
-void QEventDispatcherWinRTPrivate::registerTimer(WinRTTimerInfo *t)
-{
- Q_Q(QEventDispatcherWinRT);
-
- bool ok = false;
- uint interval = t->interval;
- if (interval == 0u) {
- // optimization for single-shot-zero-timer
- QCoreApplication::postEvent(q, new QZeroTimerEvent(t->id));
- ok = true;
- } else {
- TimeSpan period;
- period.Duration = interval * 10000; // TimeSpan is based on 100-nanosecond units
- ok = SUCCEEDED(timerFactory->CreatePeriodicTimer(
- Callback<ITimerElapsedHandler>(&QEventDispatcherWinRTPrivate::timerExpiredCallback).Get(), period, &t->timer));
- if (ok)
- timerIds.insert(t->timer.Get(), t->id);
- }
- t->timeout = qt_msectime() + interval;
- if (!ok)
- qErrnoWarning("QEventDispatcherWinRT::registerTimer: Failed to create a timer");
-}
-
-void QEventDispatcherWinRTPrivate::unregisterTimer(WinRTTimerInfo *t)
-{
- if (t->timer) {
- timerIds.remove(t->timer.Get());
- t->timer->Cancel();
- }
- timerDict.remove(t->id);
- delete t;
-}
-
-void QEventDispatcherWinRTPrivate::sendTimerEvent(int timerId)
-{
- WinRTTimerInfo *t = timerDict.value(timerId);
- if (t && !t->inTimerEvent) {
- // send event, but don't allow it to recurse
- t->inTimerEvent = true;
-
- QTimerEvent e(t->id);
- QCoreApplication::sendEvent(t->obj, &e);
-
- // timer could have been removed
- t = timerDict.value(timerId);
- if (t)
- t->inTimerEvent = false;
- }
-}
-
-HRESULT QEventDispatcherWinRTPrivate::timerExpiredCallback(IThreadPoolTimer *timer)
-{
- QThread *thread = QThread::currentThread();
- if (!thread)
- return E_FAIL;
-
- QAbstractEventDispatcher *eventDispatcher = thread->eventDispatcher();
- if (!eventDispatcher)
- return E_FAIL;
-
- QEventDispatcherWinRTPrivate *d = static_cast<QEventDispatcherWinRTPrivate *>(get(eventDispatcher));
- int timerId = d->timerIds.value(timer, -1);
- if (timerId < 0)
- return E_FAIL; // A callback was received after the timer was canceled
-
- QCoreApplication::postEvent(eventDispatcher, new QTimerEvent(timerId));
- return S_OK;
-}
-
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qfunctions_winrt.h b/src/corelib/kernel/qfunctions_winrt.h
index fa2b2e12ff..5f051c3ea6 100644
--- a/src/corelib/kernel/qfunctions_winrt.h
+++ b/src/corelib/kernel/qfunctions_winrt.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -46,6 +46,10 @@
#ifdef Q_OS_WINRT
+#include <QtCore/QThread>
+#include <QtCore/QAbstractEventDispatcher>
+#include <QtCore/qt_windows.h>
+
QT_BEGIN_NAMESPACE
#ifdef QT_BUILD_CORE_LIB
@@ -118,5 +122,94 @@ generate_inline_return_func2(_putenv_s, errno_t, const char *, const char *)
generate_inline_return_func0(tzset, void)
generate_inline_return_func0(_tzset, void)
+// Convenience macros for handling HRESULT values
+#define RETURN_IF_FAILED(msg, ret) \
+ if (FAILED(hr)) { \
+ qErrnoWarning(hr, msg); \
+ ret; \
+ }
+
+#define RETURN_HR_IF_FAILED(msg) RETURN_IF_FAILED(msg, return hr)
+#define RETURN_OK_IF_FAILED(msg) RETURN_IF_FAILED(msg, return S_OK)
+#define RETURN_FALSE_IF_FAILED(msg) RETURN_IF_FAILED(msg, return false)
+#define RETURN_VOID_IF_FAILED(msg) RETURN_IF_FAILED(msg, return)
+
+#define Q_ASSERT_SUCCEEDED(hr) \
+ Q_ASSERT_X(SUCCEEDED(hr), Q_FUNC_INFO, qPrintable(qt_error_string(hr)));
+
+
+namespace Microsoft { namespace WRL { template <typename T> class ComPtr; } }
+
+namespace QWinRTFunctions {
+
+// Synchronization methods
+enum AwaitStyle
+{
+ YieldThread = 0,
+ ProcessThreadEvents = 1,
+ ProcessMainThreadEvents = 2
+};
+
+template <typename T>
+static inline HRESULT _await_impl(const Microsoft::WRL::ComPtr<T> &asyncOp, AwaitStyle awaitStyle)
+{
+ Microsoft::WRL::ComPtr<IAsyncInfo> asyncInfo;
+ HRESULT hr = asyncOp.As(&asyncInfo);
+ if (FAILED(hr))
+ return hr;
+
+ AsyncStatus status;
+ switch (awaitStyle) {
+ case ProcessMainThreadEvents:
+ while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == Started)
+ QCoreApplication::processEvents();
+ break;
+ case ProcessThreadEvents:
+ if (QAbstractEventDispatcher *dispatcher = QThread::currentThread()->eventDispatcher()) {
+ while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == Started)
+ dispatcher->processEvents(QEventLoop::AllEvents);
+ break;
+ }
+ // fall through
+ default:
+ case YieldThread:
+ while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == Started)
+ QThread::yieldCurrentThread();
+ break;
+ }
+
+ if (FAILED(hr) || status != Completed) {
+ HRESULT ec;
+ hr = asyncInfo->get_ErrorCode(&ec);
+ if (FAILED(hr))
+ return hr;
+ return ec;
+ }
+
+ return hr;
+}
+
+template <typename T>
+static inline HRESULT await(const Microsoft::WRL::ComPtr<T> &asyncOp, AwaitStyle awaitStyle = YieldThread)
+{
+ HRESULT hr = _await_impl(asyncOp, awaitStyle);
+ if (FAILED(hr))
+ return hr;
+
+ return asyncOp->GetResults();
+}
+
+template <typename T, typename U>
+static inline HRESULT await(const Microsoft::WRL::ComPtr<T> &asyncOp, U *results, AwaitStyle awaitStyle = YieldThread)
+{
+ HRESULT hr = _await_impl(asyncOp, awaitStyle);
+ if (FAILED(hr))
+ return hr;
+
+ return asyncOp->GetResults(results);
+}
+
+} // QWinRTFunctions
+
#endif // Q_OS_WINRT
#endif // QFUNCTIONS_WINRT_H
diff --git a/src/corelib/kernel/qmath.h b/src/corelib/kernel/qmath.h
index 21e23b9eb0..e29285a0d7 100644
--- a/src/corelib/kernel/qmath.h
+++ b/src/corelib/kernel/qmath.h
@@ -49,6 +49,7 @@
#include <math.h>
#include <QtCore/qglobal.h>
+#include <QtCore/qcompilerdetection.h>
QT_BEGIN_NAMESPACE
@@ -286,6 +287,57 @@ Q_DECL_CONSTEXPR inline double qRadiansToDegrees(double radians)
return radians * (180 / M_PI);
}
+
+#if defined(Q_CC_GNU)
+// clz instructions exist in at least MIPS, ARM, PowerPC and X86, so we can assume this builtin always maps to an efficient instruction.
+inline quint32 qNextPowerOfTwo(quint32 v)
+{
+ if (v == 0)
+ return 1;
+ return 2U << (31 ^ __builtin_clz(v));
+}
+
+inline quint64 qNextPowerOfTwo(quint64 v)
+{
+ if (v == 0)
+ return 1;
+ return Q_UINT64_C(2) << (63 ^ __builtin_clzll(v));
+}
+#else
+inline quint32 qNextPowerOfTwo(quint32 v)
+{
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ ++v;
+ return v;
+}
+
+inline quint64 qNextPowerOfTwo(quint64 v)
+{
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v |= v >> 32;
+ ++v;
+ return v;
+}
+#endif
+
+inline quint32 qNextPowerOfTwo(qint32 v)
+{
+ return qNextPowerOfTwo(quint32(v));
+}
+
+inline quint64 qNextPowerOfTwo(qint64 v)
+{
+ return qNextPowerOfTwo(quint64(v));
+}
+
QT_END_NAMESPACE
#endif // QMATH_H
diff --git a/src/corelib/kernel/qmath.qdoc b/src/corelib/kernel/qmath.qdoc
index 04dbbb0a3b..430a420eeb 100644
--- a/src/corelib/kernel/qmath.qdoc
+++ b/src/corelib/kernel/qmath.qdoc
@@ -215,4 +215,37 @@
\snippet code/src_corelib_kernel_qmath.cpp 3
\sa qDegreesToRadians()
+
+/*!
+ \fn quint32 qNextPowerOfTwo(quint32 value)
+ \relates <QtMath>
+ \since 5.4
+
+ This function returns the nearest power of two greater than \a value. For 0 it returns 1, and for values larger than or equal to 2^31 it returns 0.
+*/
+
+/*!
+ \fn quint32 qNextPowerOfTwo(qint32 value)
+ \relates <QtMath>
+ \since 5.4
+ \overload
+
+ This function returns the nearest power of two greater than \a value. For negative values it returns 0.
+*/
+
+/*!
+ \fn quint64 qNextPowerOfTwo(quint64 value)
+ \relates <QtMath>
+ \since 5.4
+
+ This function returns the nearest power of two greater than \a value. For 0 it returns 1, and for values larger than or equal to 2^63 it returns 0.
+*/
+
+/*!
+ \fn quint64 qNextPowerOfTwo(qint64 value)
+ \relates <QtMath>
+ \since 5.4
+ \overload
+
+ This function returns the nearest power of two greater than \a value. For negative values it returns 0.
*/
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 5be94429b4..cb63718680 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -163,11 +163,6 @@ static inline const char *rawStringData(const QMetaObject *mo, int index)
return stringData(mo, index).data();
}
-static inline int stringSize(const QMetaObject *mo, int index)
-{
- return stringData(mo, index).size();
-}
-
static inline QByteArray typeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo)
{
if (typeInfo & IsUnresolvedType) {
@@ -308,6 +303,11 @@ int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv)
return object->qt_metacall(cl, idx, argv);
}
+static inline const char *objectClassName(const QMetaObject *m)
+{
+ return rawStringData(m, priv(m->d.data)->className);
+}
+
/*!
Returns the class name.
@@ -315,7 +315,7 @@ int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv)
*/
const char *QMetaObject::className() const
{
- return rawStringData(this, 0);
+ return objectClassName(this);
}
/*!
@@ -369,7 +369,7 @@ const QObject *QMetaObject::cast(const QObject *obj) const
*/
QString QMetaObject::tr(const char *s, const char *c, int n) const
{
- return QCoreApplication::translate(rawStringData(this, 0), s, c, n);
+ return QCoreApplication::translate(objectClassName(this), s, c, n);
}
#endif // QT_NO_TRANSLATION
@@ -728,7 +728,7 @@ int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject,
QMetaMethod conflictMethod = m->d.superdata->method(conflict);
qWarning("QMetaObject::indexOfSignal: signal %s from %s redefined in %s",
conflictMethod.methodSignature().constData(),
- rawStringData(m->d.superdata, 0), rawStringData(m, 0));
+ objectClassName(m->d.superdata), objectClassName(m));
}
}
#endif
@@ -938,7 +938,7 @@ bool QMetaObjectPrivate::checkConnectArgs(const QMetaMethodPrivate *signal,
static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, const char *name)
{
while (self) {
- if (strcmp(rawStringData(self, 0), name) == 0)
+ if (strcmp(objectClassName(self), name) == 0)
return self;
if (self->d.relatedMetaObjects) {
Q_ASSERT(priv(self->d.data)->revision >= 2);
@@ -1117,7 +1117,7 @@ QMetaProperty QMetaObject::property(int index) const
result.menum = enumerator(indexOfEnumerator(type));
if (!result.menum.isValid()) {
const char *enum_name = type;
- const char *scope_name = rawStringData(this, 0);
+ const char *scope_name = objectClassName(this);
char *scope_buffer = 0;
const char *colon = strrchr(enum_name, ':');
@@ -1339,6 +1339,27 @@ QByteArray QMetaObject::normalizedSignature(const char *method)
enum { MaximumParamCount = 11 }; // up to 10 arguments + 1 return value
/*!
+ Returns the signatures of all methods whose name matches \a nonExistentMember,
+ or an empty QByteArray if there are no matches.
+*/
+static inline QByteArray findMethodCandidates(const QMetaObject *metaObject, const char *nonExistentMember)
+{
+ QByteArray candidateMessage;
+ // Prevent full string comparison in every iteration.
+ const QByteArray memberByteArray = nonExistentMember;
+ for (int i = 0; i < metaObject->methodCount(); ++i) {
+ const QMetaMethod method = metaObject->method(i);
+ if (method.name() == memberByteArray)
+ candidateMessage.append(" " + method.methodSignature() + '\n');
+ }
+ if (!candidateMessage.isEmpty()) {
+ candidateMessage.prepend("\nCandidates are:\n");
+ candidateMessage.chop(1);
+ }
+ return candidateMessage;
+}
+
+/*!
Invokes the \a member (a signal or a slot name) on the object \a
obj. Returns \c true if the member could be invoked. Returns \c false
if there is no such member or the parameters did not match.
@@ -1455,8 +1476,9 @@ bool QMetaObject::invokeMethod(QObject *obj,
}
if (idx < 0 || idx >= meta->methodCount()) {
- qWarning("QMetaObject::invokeMethod: No such method %s::%s",
- meta->className(), sig.constData());
+ // This method doesn't belong to us; print out a nice warning with candidates.
+ qWarning("QMetaObject::invokeMethod: No such method %s::%s%s",
+ meta->className(), sig.constData(), findMethodCandidates(meta, member).constData());
return false;
}
QMetaMethod method = meta->method(idx);
@@ -2412,7 +2434,7 @@ bool QMetaEnum::isFlag() const
*/
const char *QMetaEnum::scope() const
{
- return mobj?rawStringData(mobj, 0) : 0;
+ return mobj ? objectClassName(mobj) : 0;
}
/*!
@@ -2444,7 +2466,8 @@ int QMetaEnum::keyToValue(const char *key, bool *ok) const
int count = mobj->d.data[handle + 2];
int data = mobj->d.data[handle + 3];
for (int i = 0; i < count; ++i) {
- if ((!scope || (stringSize(mobj, 0) == int(scope) && strncmp(qualified_key, rawStringData(mobj, 0), scope) == 0))
+ const QByteArray className = stringData(mobj, priv(mobj->d.data)->className);
+ if ((!scope || (className.size() == int(scope) && strncmp(qualified_key, className.constData(), scope) == 0))
&& strcmp(key, rawStringData(mobj, mobj->d.data[data + 2*i])) == 0) {
if (ok != 0)
*ok = true;
@@ -2512,12 +2535,14 @@ int QMetaEnum::keysToValue(const char *keys, bool *ok) const
key += scope + 2;
}
int i;
- for (i = count-1; i >= 0; --i)
- if ((!scope || (stringSize(mobj, 0) == int(scope) && strncmp(qualified_key.constData(), rawStringData(mobj, 0), scope) == 0))
+ for (i = count-1; i >= 0; --i) {
+ const QByteArray className = stringData(mobj, priv(mobj->d.data)->className);
+ if ((!scope || (className.size() == int(scope) && strncmp(qualified_key.constData(), className.constData(), scope) == 0))
&& strcmp(key, rawStringData(mobj, mobj->d.data[data + 2*i])) == 0) {
value |= mobj->d.data[data + 2*i + 1];
break;
}
+ }
if (i < 0) {
if (ok != 0)
*ok = false;
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index f74c592e8c..a5fd0c9102 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -2405,4 +2405,9 @@ const QMetaObject *metaObjectForQWidget()
}
}
+namespace QtMetaTypePrivate {
+const bool VectorBoolElements::true_element = true;
+const bool VectorBoolElements::false_element = false;
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 3b35a51e2c..32fd5bd153 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -782,7 +782,7 @@ private:
};
template<typename const_iterator>
-struct IteratorOwner
+struct IteratorOwnerCommon
{
static void assign(void **ptr, const_iterator iterator)
{
@@ -804,6 +804,15 @@ struct IteratorOwner
delete static_cast<const_iterator*>(*ptr);
}
+ static bool equal(void * const *it, void * const *other)
+ {
+ return *static_cast<const_iterator*>(*it) == *static_cast<const_iterator*>(*other);
+ }
+};
+
+template<typename const_iterator>
+struct IteratorOwner : IteratorOwnerCommon<const_iterator>
+{
static const void *getData(void * const *iterator)
{
return &**static_cast<const_iterator*>(*iterator);
@@ -813,16 +822,41 @@ struct IteratorOwner
{
return &*it;
}
+};
- static bool equal(void * const *it, void * const *other)
+struct Q_CORE_EXPORT VectorBoolElements
+{
+ static const bool true_element;
+ static const bool false_element;
+};
+
+template<>
+struct IteratorOwner<std::vector<bool>::const_iterator> : IteratorOwnerCommon<std::vector<bool>::const_iterator>
+{
+public:
+ static const void *getData(void * const *iterator)
{
- return *static_cast<const_iterator*>(*it) == *static_cast<const_iterator*>(*other);
+ return **static_cast<std::vector<bool>::const_iterator*>(*iterator) ?
+ &VectorBoolElements::true_element : &VectorBoolElements::false_element;
+ }
+
+ static const void *getData(const std::vector<bool>::const_iterator& it)
+ {
+ return *it ? &VectorBoolElements::true_element : &VectorBoolElements::false_element;
}
};
+
template<typename value_type>
struct IteratorOwner<const value_type*>
{
- static void assign(void **ptr, const value_type *iterator )
+private:
+ // We need to disable typed overloads of assign() and getData() if the value_type
+ // is void* to avoid overloads conflicts. We do it by injecting unaccessible Dummy
+ // type as part of the overload signature.
+ struct Dummy {};
+ typedef typename QtPrivate::if_<QtPrivate::is_same<value_type, void*>::value, Dummy, value_type>::type value_type_OR_Dummy;
+public:
+ static void assign(void **ptr, const value_type_OR_Dummy *iterator )
{
*ptr = const_cast<value_type*>(iterator);
}
@@ -847,7 +881,7 @@ struct IteratorOwner<const value_type*>
return *iterator;
}
- static const void *getData(const value_type *it)
+ static const void *getData(const value_type_OR_Dummy *it)
{
return it;
}
@@ -894,11 +928,11 @@ struct ContainerAPI<QVector<T> > : CapabilitiesImpl<QVector<T> >
template<typename T>
struct ContainerAPI<std::vector<T> > : CapabilitiesImpl<std::vector<T> >
-{ static int size(const std::vector<T> *t) { return t->size(); } };
+{ static int size(const std::vector<T> *t) { return int(t->size()); } };
template<typename T>
struct ContainerAPI<std::list<T> > : CapabilitiesImpl<std::list<T> >
-{ static int size(const std::list<T> *t) { return t->size(); } };
+{ static int size(const std::list<T> *t) { return int(t->size()); } };
class QSequentialIterableImpl
{
@@ -1278,6 +1312,11 @@ namespace QtPrivate
enum { Value = false };
};
template<>
+ struct IsPointerToTypeDerivedFromQObject<const void*>
+ {
+ enum { Value = false };
+ };
+ template<>
struct IsPointerToTypeDerivedFromQObject<QObject*>
{
enum { Value = true };
diff --git a/src/corelib/kernel/qmimedata.cpp b/src/corelib/kernel/qmimedata.cpp
index 5d2adb0561..3f2cd5a36a 100644
--- a/src/corelib/kernel/qmimedata.cpp
+++ b/src/corelib/kernel/qmimedata.cpp
@@ -294,7 +294,7 @@ QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QVariant::Ty
data is encoded.
On Windows, the MIME format does not always map directly to the
- clipboard formats. Qt provides QWindowsMime to map clipboard
+ clipboard formats. Qt provides QWinMime to map clipboard
formats to open-standard MIME formats. Similarly, the
QMacPasteboardMime maps MIME to Mac flavors.
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 5e8a97cdc0..fb01df3099 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -63,6 +63,7 @@
#include <qsharedpointer.h>
#include <private/qorderedmutexlocker_p.h>
+#include <private/qhooks_p.h>
#include <new>
@@ -138,6 +139,7 @@ static inline QMutex *signalSlotLock(const QObject *o)
uint(quintptr(o)) % sizeof(_q_ObjectMutexPool)/sizeof(QBasicMutex)]);
}
+// ### Qt >= 5.6, remove qt_add/removeObject
extern "C" Q_CORE_EXPORT void qt_addObject(QObject *)
{}
@@ -820,6 +822,8 @@ QObject::QObject(QObject *parent)
}
}
qt_addObject(this);
+ if (Q_UNLIKELY(qtHookData[QHooks::AddQObject]))
+ reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this);
}
/*!
@@ -851,6 +855,8 @@ QObject::QObject(QObjectPrivate &dd, QObject *parent)
}
}
qt_addObject(this);
+ if (Q_UNLIKELY(qtHookData[QHooks::AddQObject]))
+ reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this);
}
/*!
@@ -1028,6 +1034,8 @@ QObject::~QObject()
d->deleteChildren();
qt_removeObject(this);
+ if (Q_UNLIKELY(qtHookData[QHooks::RemoveQObject]))
+ reinterpret_cast<QHooks::RemoveQObjectCallback>(qtHookData[QHooks::RemoveQObject])(this);
if (d->parent) // remove it from parent object
d->setParent_helper(0);
@@ -3504,7 +3512,8 @@ void QMetaObject::connectSlotsByName(QObject *o)
\a signal must be in the signal index range (see QObjectPrivate::signalIndex()).
*/
-static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv)
+static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv,
+ QMutexLocker &locker)
{
const int *argumentTypes = c->argumentTypes.load();
if (!argumentTypes && argumentTypes != &DIRECT_CONNECTION_ONLY) {
@@ -3529,8 +3538,28 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect
Q_CHECK_PTR(args);
types[0] = 0; // return type
args[0] = 0; // return value
- for (int n = 1; n < nargs; ++n)
- args[n] = QMetaType::create((types[n] = argumentTypes[n-1]), argv[n]);
+
+ if (nargs > 1) {
+ for (int n = 1; n < nargs; ++n)
+ types[n] = argumentTypes[n-1];
+
+ locker.unlock();
+ for (int n = 1; n < nargs; ++n)
+ args[n] = QMetaType::create(types[n], argv[n]);
+ locker.relock();
+
+ if (!c->receiver) {
+ locker.unlock();
+ // we have been disconnected while the mutex was unlocked
+ for (int n = 1; n < nargs; ++n)
+ QMetaType::destroy(types[n], args[n]);
+ free(types);
+ free(args);
+ locker.relock();
+ return;
+ }
+ }
+
QMetaCallEvent *ev = c->isSlotObject ?
new QMetaCallEvent(c->slotObj, sender, signal, nargs, types, args) :
new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal, nargs, types, args);
@@ -3630,7 +3659,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
// put into the event queue
if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread)
|| (c->connectionType == Qt::QueuedConnection)) {
- queued_activate(sender, signal_index, c, argv ? argv : empty_argv);
+ queued_activate(sender, signal_index, c, argv ? argv : empty_argv, locker);
continue;
#ifndef QT_NO_THREAD
} else if (c->connectionType == Qt::BlockingQueuedConnection) {
diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp
index db6ff568bd..97aae6f7e0 100644
--- a/src/corelib/kernel/qtimer.cpp
+++ b/src/corelib/kernel/qtimer.cpp
@@ -260,26 +260,50 @@ class QSingleShotTimer : public QObject
{
Q_OBJECT
int timerId;
+ bool hasValidReceiver;
+ QPointer<const QObject> receiver;
+ QtPrivate::QSlotObjectBase *slotObj;
public:
~QSingleShotTimer();
QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, const char * m);
+ QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, QtPrivate::QSlotObjectBase *slotObj);
+
Q_SIGNALS:
void timeout();
protected:
void timerEvent(QTimerEvent *);
};
-QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *receiver, const char *member)
- : QObject(QAbstractEventDispatcher::instance())
+QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, const char *member)
+ : QObject(QAbstractEventDispatcher::instance()), hasValidReceiver(true), slotObj(0)
+{
+ timerId = startTimer(msec, timerType);
+ connect(this, SIGNAL(timeout()), r, member);
+}
+
+QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, QtPrivate::QSlotObjectBase *slotObj)
+ : QObject(QAbstractEventDispatcher::instance()), hasValidReceiver(r), receiver(r), slotObj(slotObj)
{
- connect(this, SIGNAL(timeout()), receiver, member);
timerId = startTimer(msec, timerType);
+ if (r && thread() != r->thread()) {
+ // We need the invocation to happen in the receiver object's thread.
+ // So, move QSingleShotTimer to the correct thread. Before that occurs, we
+ // shall remove the parent from the object.
+ setParent(0);
+ moveToThread(r->thread());
+
+ // Given we're also parentless now, we should take defence against leaks
+ // in case the application quits before we expire.
+ connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &QObject::deleteLater);
+ }
}
QSingleShotTimer::~QSingleShotTimer()
{
if (timerId > 0)
killTimer(timerId);
+ if (slotObj)
+ slotObj->destroyIfLastRef();
}
void QSingleShotTimer::timerEvent(QTimerEvent *)
@@ -289,7 +313,18 @@ void QSingleShotTimer::timerEvent(QTimerEvent *)
if (timerId > 0)
killTimer(timerId);
timerId = -1;
- emit timeout();
+
+ if (slotObj) {
+ // If the receiver was destroyed, skip this part
+ if (Q_LIKELY(!receiver.isNull() || !hasValidReceiver)) {
+ // We allocate only the return type - we previously checked the function had
+ // no arguments.
+ void *args[1] = { 0 };
+ slotObj->call(const_cast<QObject*>(receiver.data()), args);
+ }
+ } else {
+ emit timeout();
+ }
// we would like to use delete later here, but it feels like a
// waste to post a new event to handle this event, so we just unset the flag
@@ -298,6 +333,25 @@ void QSingleShotTimer::timerEvent(QTimerEvent *)
}
/*!
+ \internal
+
+ Implementation of the template version of singleShot
+
+ \a msec is the timer interval
+ \a timerType is the timer type
+ \a receiver is the receiver object, can be null. In such a case, it will be the same
+ as the final sender class.
+ \a slot a pointer only used when using Qt::UniqueConnection
+ \a slotObj the slot object
+ */
+void QTimer::singleShotImpl(int msec, Qt::TimerType timerType,
+ const QObject *receiver,
+ QtPrivate::QSlotObjectBase *slotObj)
+{
+ new QSingleShotTimer(msec, timerType, receiver, slotObj);
+}
+
+/*!
\reentrant
This static function calls a slot after a given time interval.
@@ -357,6 +411,129 @@ void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiv
}
}
+/*!\fn void QTimer::singleShot(int msec, const QObject *receiver, PointerToMemberFunction method)
+
+ \since 5.4
+
+ \overload
+ \reentrant
+ This static function calls a member function of a QObject after a given time interval.
+
+ It is very convenient to use this function because you do not need
+ to bother with a \l{QObject::timerEvent()}{timerEvent} or
+ create a local QTimer object.
+
+ The \a receiver is the receiving object and the \a method is the member function. The
+ time interval is \a msec milliseconds.
+
+ If \a receiver is destroyed before the interval occurs, the method will not be called.
+ The function will be run in the thread of \a receiver. The receiver's thread must have
+ a running Qt event loop.
+
+ \sa start()
+*/
+
+/*!\fn void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiver, PointerToMemberFunction method)
+
+ \since 5.4
+
+ \overload
+ \reentrant
+ This static function calls a member function of a QObject after a given time interval.
+
+ It is very convenient to use this function because you do not need
+ to bother with a \l{QObject::timerEvent()}{timerEvent} or
+ create a local QTimer object.
+
+ The \a receiver is the receiving object and the \a method is the member function. The
+ time interval is \a msec milliseconds. The \a timerType affects the
+ accuracy of the timer.
+
+ If \a receiver is destroyed before the interval occurs, the method will not be called.
+ The function will be run in the thread of \a receiver. The receiver's thread must have
+ a running Qt event loop.
+
+ \sa start()
+*/
+
+/*!\fn void QTimer::singleShot(int msec, Functor functor)
+
+ \since 5.4
+
+ \overload
+ \reentrant
+ This static function calls \a functor after a given time interval.
+
+ It is very convenient to use this function because you do not need
+ to bother with a \l{QObject::timerEvent()}{timerEvent} or
+ create a local QTimer object.
+
+ The time interval is \a msec milliseconds.
+
+ \sa start()
+*/
+
+/*!\fn void QTimer::singleShot(int msec, Qt::TimerType timerType, Functor functor)
+
+ \since 5.4
+
+ \overload
+ \reentrant
+ This static function calls \a functor after a given time interval.
+
+ It is very convenient to use this function because you do not need
+ to bother with a \l{QObject::timerEvent()}{timerEvent} or
+ create a local QTimer object.
+
+ The time interval is \a msec milliseconds. The \a timerType affects the
+ accuracy of the timer.
+
+ \sa start()
+*/
+
+/*!\fn void QTimer::singleShot(int msec, const QObject *context, Functor functor)
+
+ \since 5.4
+
+ \overload
+ \reentrant
+ This static function calls \a functor after a given time interval.
+
+ It is very convenient to use this function because you do not need
+ to bother with a \l{QObject::timerEvent()}{timerEvent} or
+ create a local QTimer object.
+
+ The time interval is \a msec milliseconds.
+
+ If \a context is destroyed before the interval occurs, the method will not be called.
+ The function will be run in the thread of \a context. The context's thread must have
+ a running Qt event loop.
+
+ \sa start()
+*/
+
+/*!\fn void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *context, Functor functor)
+
+ \since 5.4
+
+ \overload
+ \reentrant
+ This static function calls \a functor after a given time interval.
+
+ It is very convenient to use this function because you do not need
+ to bother with a \l{QObject::timerEvent()}{timerEvent} or
+ create a local QTimer object.
+
+ The time interval is \a msec milliseconds. The \a timerType affects the
+ accuracy of the timer.
+
+ If \a context is destroyed before the interval occurs, the method will not be called.
+ The function will be run in the thread of \a context. The context's thread must have
+ a running Qt event loop.
+
+ \sa start()
+*/
+
/*!
\property QTimer::singleShot
\brief whether the timer is a single-shot timer
diff --git a/src/corelib/kernel/qtimer.h b/src/corelib/kernel/qtimer.h
index 3484f4dba8..6439070805 100644
--- a/src/corelib/kernel/qtimer.h
+++ b/src/corelib/kernel/qtimer.h
@@ -81,6 +81,67 @@ public:
static void singleShot(int msec, const QObject *receiver, const char *member);
static void singleShot(int msec, Qt::TimerType timerType, const QObject *receiver, const char *member);
+#ifdef Q_QDOC
+ static void singleShot(int msec, const QObject *receiver, PointerToMemberFunction method);
+ static void singleShot(int msec, Qt::TimerType timerType, const QObject *receiver, PointerToMemberFunction method);
+ static void singleShot(int msec, Functor functor);
+ static void singleShot(int msec, Qt::TimerType timerType, Functor functor);
+ static void singleShot(int msec, const QObject *context, Functor functor);
+ static void singleShot(int msec, Qt::TimerType timerType, const QObject *context, Functor functor);
+#else
+ // singleShot to a QObject slot
+ template <typename Func1>
+ static inline void singleShot(int msec, const typename QtPrivate::FunctionPointer<Func1>::Object *receiver, Func1 slot)
+ {
+ singleShot(msec, msec >= 2000 ? Qt::CoarseTimer : Qt::PreciseTimer, receiver, slot);
+ }
+ template <typename Func1>
+ static inline void singleShot(int msec, Qt::TimerType timerType, const typename QtPrivate::FunctionPointer<Func1>::Object *receiver,
+ Func1 slot)
+ {
+ typedef QtPrivate::FunctionPointer<Func1> SlotType;
+
+ //compilation error if the slot has arguments.
+ Q_STATIC_ASSERT_X(int(SlotType::ArgumentCount) == 0,
+ "The slot must not have any arguments.");
+
+ singleShotImpl(msec, timerType, receiver,
+ new QtPrivate::QSlotObject<Func1, typename SlotType::Arguments, void>(slot));
+ }
+ // singleShot to a functor or function pointer (without context)
+ template <typename Func1>
+ static inline void singleShot(int msec, Func1 slot)
+ {
+ singleShot(msec, msec >= 2000 ? Qt::CoarseTimer : Qt::PreciseTimer, Q_NULLPTR, slot);
+ }
+ template <typename Func1>
+ static inline void singleShot(int msec, Qt::TimerType timerType, Func1 slot)
+ {
+ singleShot(msec, timerType, Q_NULLPTR, slot);
+ }
+ // singleShot to a functor or function pointer (with context)
+ template <typename Func1>
+ static inline typename QtPrivate::QEnableIf<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
+ !QtPrivate::is_same<const char*, Func1>::value, void>::Type
+ singleShot(int msec, QObject *context, Func1 slot)
+ {
+ singleShot(msec, msec >= 2000 ? Qt::CoarseTimer : Qt::PreciseTimer, context, slot);
+ }
+ template <typename Func1>
+ static inline typename QtPrivate::QEnableIf<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
+ !QtPrivate::is_same<const char*, Func1>::value, void>::Type
+ singleShot(int msec, Qt::TimerType timerType, QObject *context, Func1 slot)
+ {
+ //compilation error if the slot has arguments.
+ typedef QtPrivate::FunctionPointer<Func1> SlotType;
+ Q_STATIC_ASSERT_X(int(SlotType::ArgumentCount) <= 0, "The slot must not have any arguments.");
+
+ singleShotImpl(msec, timerType, context,
+ new QtPrivate::QFunctorSlotObject<Func1, 0,
+ typename QtPrivate::List_Left<void, 0>::Value, void>(slot));
+ }
+#endif
+
public Q_SLOTS:
void start(int msec);
@@ -103,6 +164,9 @@ private:
inline int startTimer(int){ return -1;}
inline void killTimer(int){}
+ static void singleShotImpl(int msec, Qt::TimerType timerType,
+ const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj);
+
int id, inter, del;
uint single : 1;
uint nulltimer : 1;
diff --git a/src/corelib/mimetypes/qmimetype.cpp b/src/corelib/mimetypes/qmimetype.cpp
index 0ffa186d2e..a23e545729 100644
--- a/src/corelib/mimetypes/qmimetype.cpp
+++ b/src/corelib/mimetypes/qmimetype.cpp
@@ -443,4 +443,17 @@ bool QMimeType::inherits(const QString &mimeTypeName) const
return QMimeDatabasePrivate::instance()->inherits(d->name, mimeTypeName);
}
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QMimeType &mime)
+{
+ QDebugStateSaver saver(debug);
+ if (!mime.isValid()) {
+ debug.nospace() << "QMimeType(invalid)";
+ } else {
+ debug.nospace() << "QMimeType(" << mime.name() << ")";
+ }
+ return debug;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/corelib/mimetypes/qmimetype.h b/src/corelib/mimetypes/qmimetype.h
index 24d043eebc..d5acbc2184 100644
--- a/src/corelib/mimetypes/qmimetype.h
+++ b/src/corelib/mimetypes/qmimetype.h
@@ -110,5 +110,10 @@ protected:
Q_DECLARE_SHARED(QMimeType)
+#ifndef QT_NO_DEBUG_STREAM
+class QDebug;
+Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QMimeType &mime);
+#endif
+
QT_END_NAMESPACE
#endif // QMIMETYPE_H
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
index 50281b632a..8af38acf51 100644
--- a/src/corelib/plugin/qlibrary.cpp
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -455,7 +455,7 @@ inline QLibraryPrivate *QLibraryStore::findOrCreate(const QString &fileName, con
lib = new QLibraryPrivate(fileName, version, loadHints);
// track this library
- if (Q_LIKELY(data))
+ if (Q_LIKELY(data) && !fileName.isEmpty())
data->libraryMap.insert(fileName, lib);
lib->libraryRefCount.ref();
@@ -475,7 +475,7 @@ inline void QLibraryStore::releaseLibrary(QLibraryPrivate *lib)
// no one else is using
Q_ASSERT(lib->libraryUnloadCount.load() == 0);
- if (Q_LIKELY(data)) {
+ if (Q_LIKELY(data) && !lib->fileName.isEmpty()) {
QLibraryPrivate *that = data->libraryMap.take(lib->fileName);
Q_ASSERT(lib == that);
Q_UNUSED(that);
@@ -485,9 +485,9 @@ inline void QLibraryStore::releaseLibrary(QLibraryPrivate *lib)
QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints)
: pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0),
- loadHints(loadHints),
libraryRefCount(0), libraryUnloadCount(0), pluginState(MightBeAPlugin)
{
+ loadHintsInt.store(loadHints);
if (canonicalFileName.isEmpty())
errorString = QLibrary::tr("The shared library was not found.");
}
@@ -508,7 +508,7 @@ void QLibraryPrivate::mergeLoadHints(QLibrary::LoadHints lh)
if (pHnd)
return;
- loadHints = lh;
+ loadHintsInt.store(lh);
}
QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
@@ -518,6 +518,12 @@ QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
return resolve_sys(symbol);
}
+void QLibraryPrivate::setLoadHints(QLibrary::LoadHints lh)
+{
+ // this locks a global mutex
+ QMutexLocker lock(&qt_library_mutex);
+ mergeLoadHints(lh);
+}
bool QLibraryPrivate::load()
{
@@ -914,13 +920,12 @@ void QLibrary::setFileName(const QString &fileName)
{
QLibrary::LoadHints lh;
if (d) {
- lh = d->loadHints;
+ lh = d->loadHints();
d->release();
d = 0;
did_load = false;
}
- d = QLibraryPrivate::findOrCreate(fileName);
- d->loadHints = lh;
+ d = QLibraryPrivate::findOrCreate(fileName, QString(), lh);
}
QString QLibrary::fileName() const
@@ -943,13 +948,12 @@ void QLibrary::setFileNameAndVersion(const QString &fileName, int verNum)
{
QLibrary::LoadHints lh;
if (d) {
- lh = d->loadHints;
+ lh = d->loadHints();
d->release();
d = 0;
did_load = false;
}
- d = QLibraryPrivate::findOrCreate(fileName, verNum >= 0 ? QString::number(verNum) : QString());
- d->loadHints = lh;
+ d = QLibraryPrivate::findOrCreate(fileName, verNum >= 0 ? QString::number(verNum) : QString(), lh);
}
/*!
@@ -965,13 +969,12 @@ void QLibrary::setFileNameAndVersion(const QString &fileName, const QString &ver
{
QLibrary::LoadHints lh;
if (d) {
- lh = d->loadHints;
+ lh = d->loadHints();
d->release();
d = 0;
did_load = false;
}
- d = QLibraryPrivate::findOrCreate(fileName, version);
- d->loadHints = lh;
+ d = QLibraryPrivate::findOrCreate(fileName, version, lh);
}
/*!
@@ -1102,6 +1105,12 @@ QString QLibrary::errorString() const
By default, none of these flags are set, so libraries will be loaded with
lazy symbol resolution, and will not export external symbols for resolution
in other dynamically-loaded libraries.
+
+ \note Setting this property after the library has been loaded has no effect
+ and loadHints() will not reflect those changes.
+
+ \note This property is shared among all QLibrary instances that refer to
+ the same library.
*/
void QLibrary::setLoadHints(LoadHints hints)
{
@@ -1109,12 +1118,12 @@ void QLibrary::setLoadHints(LoadHints hints)
d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr
d->errorString.clear();
}
- d->loadHints = hints;
+ d->setLoadHints(hints);
}
QLibrary::LoadHints QLibrary::loadHints() const
{
- return d ? d->loadHints : (QLibrary::LoadHints)0;
+ return d ? d->loadHints() : QLibrary::LoadHints();
}
/* Internal, for debugging */
diff --git a/src/corelib/plugin/qlibrary_p.h b/src/corelib/plugin/qlibrary_p.h
index e58d18e87b..df95d1342d 100644
--- a/src/corelib/plugin/qlibrary_p.h
+++ b/src/corelib/plugin/qlibrary_p.h
@@ -94,6 +94,10 @@ public:
void release();
QFunctionPointer resolve(const char *);
+ QLibrary::LoadHints loadHints() const
+ { return QLibrary::LoadHints(loadHintsInt.load()); }
+ void setLoadHints(QLibrary::LoadHints lh);
+
static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString(),
QLibrary::LoadHints loadHints = 0);
static QStringList suffixes_sys(const QString &fullVersion);
@@ -104,7 +108,6 @@ public:
QJsonObject metaData;
QString errorString;
- QLibrary::LoadHints loadHints;
void updatePluginState();
bool isPlugin();
@@ -126,6 +129,8 @@ private:
bool unload_sys();
QFunctionPointer resolve_sys(const char *);
+ QAtomicInt loadHintsInt;
+
/// counts how many QLibrary or QPluginLoader are attached to us, plus 1 if it's loaded
QAtomicInt libraryRefCount;
/// counts how many times load() or loadPlugin() were called
diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp
index 43e2b5c15b..b9af143f35 100644
--- a/src/corelib/plugin/qlibrary_unix.cpp
+++ b/src/corelib/plugin/qlibrary_unix.cpp
@@ -162,6 +162,7 @@ bool QLibraryPrivate::load_sys()
dlFlags |= BIND_DEFERRED;
}
#else
+ int loadHints = this->loadHints();
if (loadHints & QLibrary::ResolveAllSymbolsHint) {
dlFlags |= RTLD_NOW;
} else {
diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp
index 2c139669e6..f34c019823 100644
--- a/src/corelib/plugin/qpluginloader.cpp
+++ b/src/corelib/plugin/qpluginloader.cpp
@@ -339,7 +339,7 @@ void QPluginLoader::setFileName(const QString &fileName)
#if defined(QT_SHARED)
QLibrary::LoadHints lh;
if (d) {
- lh = d->loadHints;
+ lh = d->loadHints();
d->release();
d = 0;
did_load = false;
@@ -405,17 +405,12 @@ void QPluginLoader::setLoadHints(QLibrary::LoadHints loadHints)
d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr
d->errorString.clear();
}
- d->loadHints = loadHints;
+ d->setLoadHints(loadHints);
}
QLibrary::LoadHints QPluginLoader::loadHints() const
{
- if (!d) {
- QPluginLoader *that = const_cast<QPluginLoader *>(this);
- that->d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr
- that->d->errorString.clear();
- }
- return d->loadHints;
+ return d ? d->loadHints() : QLibrary::LoadHints();
}
/*!
diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp
index 49091de8a8..e446c69519 100644
--- a/src/corelib/statemachine/qabstracttransition.cpp
+++ b/src/corelib/statemachine/qabstracttransition.cpp
@@ -201,10 +201,15 @@ QAbstractState *QAbstractTransition::targetState() const
void QAbstractTransition::setTargetState(QAbstractState* target)
{
Q_D(QAbstractTransition);
+ if ((d->targetStates.size() == 1 && target == d->targetStates.at(0).data()) ||
+ (d->targetStates.isEmpty() && target == 0)) {
+ return;
+ }
if (!target)
d->targetStates.clear();
else
setTargetStates(QList<QAbstractState*>() << target);
+ emit targetStateChanged(QPrivateSignal());
}
/*!
@@ -229,18 +234,26 @@ QList<QAbstractState*> QAbstractTransition::targetStates() const
void QAbstractTransition::setTargetStates(const QList<QAbstractState*> &targets)
{
Q_D(QAbstractTransition);
-
+ QList<QPointer<QAbstractState> > copy(d->targetStates);
+ bool sameList = true;
for (int i = 0; i < targets.size(); ++i) {
QAbstractState *target = targets.at(i);
if (!target) {
qWarning("QAbstractTransition::setTargetStates: target state(s) cannot be null");
return;
+ } else {
+ sameList &= copy.removeOne(target);
}
}
+ sameList &= copy.isEmpty();
+
d->targetStates.clear();
for (int i = 0; i < targets.size(); ++i)
d->targetStates.append(targets.at(i));
+
+ if (!sameList)
+ emit targetStatesChanged(QPrivateSignal());
}
/*!
@@ -324,6 +337,24 @@ QList<QAbstractAnimation*> QAbstractTransition::animations() const
*/
/*!
+ \fn QAbstractTransition::targetStateChanged()
+ \since 5.4
+
+ This signal is emitted when the targetState property is changed.
+
+ \sa QAbstractTransition::targetState
+*/
+
+/*!
+ \fn QAbstractTransition::targetStatesChanged()
+ \since 5.4
+
+ This signal is emitted when the targetStates property is changed.
+
+ \sa QAbstractTransition::targetStates
+*/
+
+/*!
\reimp
*/
bool QAbstractTransition::event(QEvent *e)
diff --git a/src/corelib/statemachine/qabstracttransition.h b/src/corelib/statemachine/qabstracttransition.h
index a35ad4ca96..ac3b40e55e 100644
--- a/src/corelib/statemachine/qabstracttransition.h
+++ b/src/corelib/statemachine/qabstracttransition.h
@@ -65,8 +65,8 @@ class Q_CORE_EXPORT QAbstractTransition : public QObject
{
Q_OBJECT
Q_PROPERTY(QState* sourceState READ sourceState)
- Q_PROPERTY(QAbstractState* targetState READ targetState WRITE setTargetState)
- Q_PROPERTY(QList<QAbstractState*> targetStates READ targetStates WRITE setTargetStates)
+ Q_PROPERTY(QAbstractState* targetState READ targetState WRITE setTargetState NOTIFY targetStateChanged)
+ Q_PROPERTY(QList<QAbstractState*> targetStates READ targetStates WRITE setTargetStates NOTIFY targetStatesChanged)
public:
QAbstractTransition(QState *sourceState = 0);
virtual ~QAbstractTransition();
@@ -91,6 +91,16 @@ Q_SIGNALS:
QPrivateSignal
#endif
);
+ void targetStateChanged(
+#if !defined(Q_QDOC)
+ QPrivateSignal
+#endif
+ );
+ void targetStatesChanged(
+#if !defined(Q_QDOC)
+ QPrivateSignal
+#endif
+ );
protected:
virtual bool eventTest(QEvent *event) = 0;
diff --git a/src/corelib/statemachine/qhistorystate.cpp b/src/corelib/statemachine/qhistorystate.cpp
index 65ac2a77a0..1706d86afd 100644
--- a/src/corelib/statemachine/qhistorystate.cpp
+++ b/src/corelib/statemachine/qhistorystate.cpp
@@ -181,7 +181,10 @@ void QHistoryState::setDefaultState(QAbstractState *state)
"to this history state's group (%p)", state, parentState());
return;
}
- d->defaultState = state;
+ if (d->defaultState != state) {
+ d->defaultState = state;
+ emit defaultStateChanged(QHistoryState::QPrivateSignal());
+ }
}
/*!
@@ -199,7 +202,10 @@ QHistoryState::HistoryType QHistoryState::historyType() const
void QHistoryState::setHistoryType(HistoryType type)
{
Q_D(QHistoryState);
- d->historyType = type;
+ if (d->historyType != type) {
+ d->historyType = type;
+ emit historyTypeChanged(QHistoryState::QPrivateSignal());
+ }
}
/*!
@@ -226,6 +232,24 @@ bool QHistoryState::event(QEvent *e)
return QAbstractState::event(e);
}
+/*!
+ \fn QHistoryState::defaultStateChanged()
+ \since 5.4
+
+ This signal is emitted when the defaultState property is changed.
+
+ \sa QHistoryState::defaultState
+*/
+
+/*!
+ \fn QHistoryState::historyTypeChanged()
+ \since 5.4
+
+ This signal is emitted when the historyType property is changed.
+
+ \sa QHistoryState::historyType
+*/
+
QT_END_NAMESPACE
#endif //QT_NO_STATEMACHINE
diff --git a/src/corelib/statemachine/qhistorystate.h b/src/corelib/statemachine/qhistorystate.h
index 62278ac47a..024c7e4b1f 100644
--- a/src/corelib/statemachine/qhistorystate.h
+++ b/src/corelib/statemachine/qhistorystate.h
@@ -53,8 +53,8 @@ class QHistoryStatePrivate;
class Q_CORE_EXPORT QHistoryState : public QAbstractState
{
Q_OBJECT
- Q_PROPERTY(QAbstractState* defaultState READ defaultState WRITE setDefaultState)
- Q_PROPERTY(HistoryType historyType READ historyType WRITE setHistoryType)
+ Q_PROPERTY(QAbstractState* defaultState READ defaultState WRITE setDefaultState NOTIFY defaultStateChanged)
+ Q_PROPERTY(HistoryType historyType READ historyType WRITE setHistoryType NOTIFY historyTypeChanged)
Q_ENUMS(HistoryType)
public:
enum HistoryType {
@@ -72,6 +72,18 @@ public:
HistoryType historyType() const;
void setHistoryType(HistoryType type);
+Q_SIGNALS:
+ void defaultStateChanged(
+#if !defined(Q_QDOC)
+ QPrivateSignal
+#endif
+ );
+ void historyTypeChanged(
+#if !defined(Q_QDOC)
+ QPrivateSignal
+#endif
+ );
+
protected:
void onEntry(QEvent *event);
void onExit(QEvent *event);
diff --git a/src/corelib/statemachine/qsignaltransition.cpp b/src/corelib/statemachine/qsignaltransition.cpp
index f1f4786bcc..259aaf52e9 100644
--- a/src/corelib/statemachine/qsignaltransition.cpp
+++ b/src/corelib/statemachine/qsignaltransition.cpp
@@ -185,6 +185,7 @@ void QSignalTransition::setSenderObject(const QObject *sender)
d->unregister();
d->sender = sender;
d->maybeRegister();
+ emit senderObjectChanged(QPrivateSignal());
}
/*!
@@ -207,6 +208,7 @@ void QSignalTransition::setSignal(const QByteArray &signal)
d->unregister();
d->signal = signal;
d->maybeRegister();
+ emit signalChanged(QPrivateSignal());
}
/*!
@@ -245,6 +247,24 @@ bool QSignalTransition::event(QEvent *e)
return QAbstractTransition::event(e);
}
+/*!
+ \fn QSignalTransition::senderObjectChanged()
+ \since 5.4
+
+ This signal is emitted when the senderObject property is changed.
+
+ \sa QSignalTransition::senderObject
+*/
+
+/*!
+ \fn QSignalTransition::signalChanged()
+ \since 5.4
+
+ This signal is emitted when the signal property is changed.
+
+ \sa QSignalTransition::signal
+*/
+
void QSignalTransitionPrivate::callOnTransition(QEvent *e)
{
Q_Q(QSignalTransition);
@@ -260,6 +280,7 @@ void QSignalTransitionPrivate::callOnTransition(QEvent *e)
}
}
+
QT_END_NAMESPACE
#endif //QT_NO_STATEMACHINE
diff --git a/src/corelib/statemachine/qsignaltransition.h b/src/corelib/statemachine/qsignaltransition.h
index 12f021d78e..792fb12a14 100644
--- a/src/corelib/statemachine/qsignaltransition.h
+++ b/src/corelib/statemachine/qsignaltransition.h
@@ -53,8 +53,9 @@ class QSignalTransitionPrivate;
class Q_CORE_EXPORT QSignalTransition : public QAbstractTransition
{
Q_OBJECT
- Q_PROPERTY(QObject* senderObject READ senderObject WRITE setSenderObject)
- Q_PROPERTY(QByteArray signal READ signal WRITE setSignal)
+ Q_PROPERTY(QObject* senderObject READ senderObject WRITE setSenderObject NOTIFY senderObjectChanged)
+ Q_PROPERTY(QByteArray signal READ signal WRITE setSignal NOTIFY signalChanged)
+
public:
QSignalTransition(QState *sourceState = 0);
QSignalTransition(const QObject *sender, const char *signal,
@@ -73,6 +74,18 @@ protected:
bool event(QEvent *e);
+Q_SIGNALS:
+ void senderObjectChanged(
+#if !defined(Q_QDOC)
+ QPrivateSignal
+#endif
+ );
+ void signalChanged(
+#if !defined(Q_QDOC)
+ QPrivateSignal
+#endif
+ );
+
private:
Q_DISABLE_COPY(QSignalTransition)
Q_DECLARE_PRIVATE(QSignalTransition)
diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp
index f3b4c5f235..e9baddc569 100644
--- a/src/corelib/statemachine/qstate.cpp
+++ b/src/corelib/statemachine/qstate.cpp
@@ -309,7 +309,10 @@ void QState::setErrorState(QAbstractState *state)
return;
}
- d->errorState = state;
+ if (d->errorState != state) {
+ d->errorState = state;
+ emit errorStateChanged(QState::QPrivateSignal());
+ }
}
/*!
@@ -491,7 +494,10 @@ void QState::setInitialState(QAbstractState *state)
state, this);
return;
}
- d->initialState = state;
+ if (d->initialState != state) {
+ d->initialState = state;
+ emit initialStateChanged(QState::QPrivateSignal());
+ }
}
/*!
@@ -509,7 +515,10 @@ QState::ChildMode QState::childMode() const
void QState::setChildMode(ChildMode mode)
{
Q_D(QState);
- d->childMode = mode;
+ if (d->childMode != mode) {
+ d->childMode = mode;
+ emit childModeChanged(QState::QPrivateSignal());
+ }
}
/*!
@@ -549,6 +558,33 @@ bool QState::event(QEvent *e)
\sa QState::assignProperty(), QAbstractTransition::addAnimation()
*/
+/*!
+ \fn QState::childModeChanged()
+ \since 5.4
+
+ This signal is emitted when the childMode property is changed.
+
+ \sa QState::childMode
+*/
+
+/*!
+ \fn QState::initialStateChanged()
+ \since 5.4
+
+ This signal is emitted when the initialState property is changed.
+
+ \sa QState::initialState
+*/
+
+/*!
+ \fn QState::errorStateChanged()
+ \since 5.4
+
+ This signal is emitted when the errorState property is changed.
+
+ \sa QState::errorState
+*/
+
QT_END_NAMESPACE
#endif //QT_NO_STATEMACHINE
diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h
index a5f2509ffb..09c98c30c6 100644
--- a/src/corelib/statemachine/qstate.h
+++ b/src/corelib/statemachine/qstate.h
@@ -58,9 +58,9 @@ class QStatePrivate;
class Q_CORE_EXPORT QState : public QAbstractState
{
Q_OBJECT
- Q_PROPERTY(QAbstractState* initialState READ initialState WRITE setInitialState)
- Q_PROPERTY(QAbstractState* errorState READ errorState WRITE setErrorState)
- Q_PROPERTY(ChildMode childMode READ childMode WRITE setChildMode)
+ Q_PROPERTY(QAbstractState* initialState READ initialState WRITE setInitialState NOTIFY initialStateChanged)
+ Q_PROPERTY(QAbstractState* errorState READ errorState WRITE setErrorState NOTIFY errorStateChanged)
+ Q_PROPERTY(ChildMode childMode READ childMode WRITE setChildMode NOTIFY childModeChanged)
Q_ENUMS(ChildMode RestorePolicy)
public:
enum ChildMode {
@@ -108,6 +108,21 @@ Q_SIGNALS:
QPrivateSignal
#endif
);
+ void childModeChanged(
+#if !defined(Q_QDOC)
+ QPrivateSignal
+#endif
+ );
+ void initialStateChanged(
+#if !defined(Q_QDOC)
+ QPrivateSignal
+#endif
+ );
+ void errorStateChanged(
+#if !defined(Q_QDOC)
+ QPrivateSignal
+#endif
+ );
protected:
void onEntry(QEvent *event);
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index d2e2368ca9..d46fa357ae 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -163,6 +163,13 @@ QT_BEGIN_NAMESPACE
QState::DontRestoreProperties.
*/
+/*!
+ \property QStateMachine::running
+ \since 5.4
+
+ \brief the running state of this state machine
+*/
+
#ifndef QT_NO_ANIMATION
/*!
\property QStateMachine::animated
@@ -1409,6 +1416,7 @@ void QStateMachinePrivate::_q_start()
#endif
emit q->started(QStateMachine::QPrivateSignal());
+ emit q->runningChanged(true);
if (stopProcessingReason == Finished) {
// The state machine immediately reached a final state.
@@ -1416,6 +1424,7 @@ void QStateMachinePrivate::_q_start()
state = NotRunning;
unregisterAllTransitions();
emitFinished();
+ emit q->runningChanged(false);
} else {
_q_process();
}
@@ -1498,12 +1507,14 @@ void QStateMachinePrivate::_q_process()
cancelAllDelayedEvents();
unregisterAllTransitions();
emitFinished();
+ emit q->runningChanged(false);
break;
case Stopped:
state = NotRunning;
cancelAllDelayedEvents();
unregisterAllTransitions();
emit q->stopped(QStateMachine::QPrivateSignal());
+ emit q->runningChanged(false);
break;
}
}
@@ -2117,7 +2128,7 @@ bool QStateMachine::isRunning() const
the main application event loop started with QCoreApplication::exec() or
QApplication::exec().
- \sa started(), finished(), stop(), initialState()
+ \sa started(), finished(), stop(), initialState(), setRunning()
*/
void QStateMachine::start()
{
@@ -2145,7 +2156,7 @@ void QStateMachine::start()
Stops this state machine. The state machine will stop processing events and
then emit the stopped() signal.
- \sa stopped(), start()
+ \sa stopped(), start(), setRunning()
*/
void QStateMachine::stop()
{
@@ -2165,6 +2176,19 @@ void QStateMachine::stop()
}
/*!
+ Convenience functions to start/stop this state machine.
+
+ \sa start(), stop(), started(), finished(), stopped()
+*/
+void QStateMachine::setRunning(bool running)
+{
+ if (running)
+ start();
+ else
+ stop();
+}
+
+/*!
\threadsafe
Posts the given \a event of the given \a priority for processing by this
@@ -2712,6 +2736,15 @@ QStateMachine::WrappedEvent::~WrappedEvent()
Returns a clone of the original event.
*/
+/*!
+ \fn QStateMachine::runningChanged(bool running)
+ \since 5.4
+
+ This signal is emitted when the running property is changed.
+
+ \sa QStateMachine::running
+*/
+
QT_END_NAMESPACE
#include "qstatemachine.moc"
diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h
index 9305676bb5..0092c4d0c5 100644
--- a/src/corelib/statemachine/qstatemachine.h
+++ b/src/corelib/statemachine/qstatemachine.h
@@ -62,6 +62,7 @@ class Q_CORE_EXPORT QStateMachine : public QState
Q_OBJECT
Q_PROPERTY(QString errorString READ errorString)
Q_PROPERTY(QState::RestorePolicy globalRestorePolicy READ globalRestorePolicy WRITE setGlobalRestorePolicy)
+ Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
#ifndef QT_NO_ANIMATION
Q_PROPERTY(bool animated READ isAnimated WRITE setAnimated)
#endif
@@ -149,6 +150,7 @@ public:
public Q_SLOTS:
void start();
void stop();
+ void setRunning(bool running);
Q_SIGNALS:
void started(
@@ -161,6 +163,8 @@ Q_SIGNALS:
QPrivateSignal
#endif
);
+ void runningChanged(bool running);
+
protected:
void onEntry(QEvent *event);
diff --git a/src/corelib/thread/qgenericatomic.h b/src/corelib/thread/qgenericatomic.h
index aeed199c97..3546becd77 100644
--- a/src/corelib/thread/qgenericatomic.h
+++ b/src/corelib/thread/qgenericatomic.h
@@ -294,9 +294,9 @@ template <typename BaseClass> struct QGenericAtomicOps
T fetchAndAndRelaxed(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
{
// implement fetchAndAnd on top of testAndSet
+ T tmp = BaseClass::load(_q_value);
Q_FOREVER {
- T tmp = BaseClass::load(_q_value);
- if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp & operand)))
+ if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp & operand), &tmp))
return tmp;
}
}
@@ -327,9 +327,9 @@ template <typename BaseClass> struct QGenericAtomicOps
T fetchAndOrRelaxed(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
{
// implement fetchAndOr on top of testAndSet
+ T tmp = BaseClass::load(_q_value);
Q_FOREVER {
- T tmp = BaseClass::load(_q_value);
- if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp | operand)))
+ if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp | operand), &tmp))
return tmp;
}
}
@@ -360,9 +360,9 @@ template <typename BaseClass> struct QGenericAtomicOps
T fetchAndXorRelaxed(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
{
// implement fetchAndXor on top of testAndSet
+ T tmp = BaseClass::load(_q_value);
Q_FOREVER {
- T tmp = BaseClass::load(_q_value);
- if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp ^ operand)))
+ if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp ^ operand), &tmp))
return tmp;
}
}
diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h
index e2951b125f..aec553113b 100644
--- a/src/corelib/thread/qthread_p.h
+++ b/src/corelib/thread/qthread_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -65,11 +65,6 @@
#include <algorithm>
-
-#ifdef Q_OS_WINRT
-#include <thread>
-#endif
-
QT_BEGIN_NAMESPACE
class QAbstractEventDispatcher;
@@ -138,6 +133,10 @@ private:
#ifndef QT_NO_THREAD
+#ifdef Q_OS_WINRT
+namespace ABI { namespace Windows { namespace Foundation { struct IAsyncAction; } } }
+#endif
+
class QThreadPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QThread)
@@ -174,19 +173,23 @@ public:
#endif // Q_OS_UNIX
#ifdef Q_OS_WIN
+# ifndef Q_OS_WINRT
static unsigned int __stdcall start(void *);
static void finish(void *, bool lockAnyway=true);
+# else
+ HRESULT start(ABI::Windows::Foundation::IAsyncAction *);
+ void finish(bool lockAnyway = true);
+# endif
# ifndef Q_OS_WINRT
Qt::HANDLE handle;
- unsigned int id;
# else
- std::thread *handle;
- std::thread::id id;
+ ABI::Windows::Foundation::IAsyncAction *handle;
# endif
+ unsigned int id;
int waiters;
bool terminationEnabled, terminatePending;
-# endif
+#endif // Q_OS_WIN
QThreadData *data;
static void createEventDispatcher(QThreadData *data);
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index bdc3463b9f..e950a02162 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -40,7 +40,7 @@
****************************************************************************/
//#define WINVER 0x0500
-#if (_WIN32_WINNT < 0x0400) && !defined(Q_OS_WINRT)
+#if (_WIN32_WINNT < 0x0400)
#define _WIN32_WINNT 0x0400
#endif
@@ -54,19 +54,10 @@
#include <qpointer.h>
#include <private/qcoreapplication_p.h>
-#ifdef Q_OS_WINRT
-#include <private/qeventdispatcher_winrt_p.h>
-#else
#include <private/qeventdispatcher_win_p.h>
-#endif
#include <qt_windows.h>
-#ifdef Q_OS_WINRT
-#include <qelapsedtimer.h>
-#include <thread>
-#endif
-
#ifndef Q_OS_WINCE
#ifndef _MT
#define _MT
@@ -79,7 +70,6 @@
#ifndef QT_NO_THREAD
QT_BEGIN_NAMESPACE
-#ifndef Q_OS_WINRT
void qt_watch_adopted_thread(const HANDLE adoptedThreadHandle, QThread *qthread);
DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID);
@@ -101,38 +91,6 @@ static void qt_free_tls()
}
}
Q_DESTRUCTOR_FUNCTION(qt_free_tls)
-#else // !Q_OS_WINRT
-
-__declspec(thread) static QThreadData* qt_current_thread_data_tls_index = 0;
-void qt_create_tls()
-{
-}
-
-static void qt_free_tls()
-{
- if (qt_current_thread_data_tls_index) {
- qt_current_thread_data_tls_index->deref();
- qt_current_thread_data_tls_index = 0;
- }
-}
-
-QThreadData* TlsGetValue(QThreadData*& tls)
-{
- Q_ASSERT(tls == qt_current_thread_data_tls_index);
- return tls;
-}
-
-void TlsSetValue(QThreadData*& tls, QThreadData* data)
-{
- Q_ASSERT(tls == qt_current_thread_data_tls_index);
- if (tls)
- tls->deref();
- tls = data;
- if (tls)
- tls->ref();
-}
-Q_DESTRUCTOR_FUNCTION(qt_free_tls)
-#endif // Q_OS_WINRT
/*
QThreadData
@@ -165,7 +123,6 @@ QThreadData *QThreadData::current(bool createIfNecessary)
if (!QCoreApplicationPrivate::theMainThread) {
QCoreApplicationPrivate::theMainThread = threadData->thread;
-#ifndef Q_OS_WINRT
// TODO: is there a way to reflect the branch's behavior using
// WinRT API?
} else {
@@ -182,7 +139,6 @@ QThreadData *QThreadData::current(bool createIfNecessary)
realHandle = reinterpret_cast<HANDLE>(GetCurrentThreadId());
#endif
qt_watch_adopted_thread(realHandle, threadData->thread);
-#endif // !Q_OS_WINRT
}
}
return threadData;
@@ -190,16 +146,10 @@ QThreadData *QThreadData::current(bool createIfNecessary)
void QAdoptedThread::init()
{
-#ifndef Q_OS_WINRT
d_func()->handle = GetCurrentThread();
d_func()->id = GetCurrentThreadId();
-#else
- d_func()->handle = nullptr;
- d_func()->id = std::this_thread::get_id();
-#endif
}
-#ifndef Q_OS_WINRT
static QVector<HANDLE> qt_adopted_thread_handles;
static QVector<QThread *> qt_adopted_qthreads;
static QMutex qt_adopted_thread_watcher_mutex;
@@ -352,7 +302,6 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName)
}
}
#endif // !QT_NO_DEBUG && Q_CC_MSVC && !Q_OS_WINCE
-#endif // !Q_OS_WINRT
/**************************************************************************
** QThreadPrivate
@@ -362,11 +311,7 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName)
void QThreadPrivate::createEventDispatcher(QThreadData *data)
{
-#ifdef Q_OS_WINRT
- QEventDispatcherWinRT *theEventDispatcher = new QEventDispatcherWinRT;
-#else
QEventDispatcherWin32 *theEventDispatcher = new QEventDispatcherWin32;
-#endif
data->eventDispatcher.storeRelease(theEventDispatcher);
theEventDispatcher->startingUp();
}
@@ -394,7 +339,7 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
else
createEventDispatcher(data);
-#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE)
// sets the name of the current thread.
QByteArray objectName = thr->objectName().toLocal8Bit();
qt_set_thread_name((HANDLE)-1,
@@ -440,21 +385,11 @@ void QThreadPrivate::finish(void *arg, bool lockAnyway)
d->interruptionRequested = false;
if (!d->waiters) {
-#ifndef Q_OS_WINRT
CloseHandle(d->handle);
-#else
- d->handle->detach();
- delete d->handle;
-#endif
d->handle = 0;
}
-#ifndef Q_OS_WINRT
d->id = 0;
-#else
- d->id = std::thread::id();
-#endif
-
}
/**************************************************************************
@@ -469,15 +404,10 @@ Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW
int QThread::idealThreadCount() Q_DECL_NOTHROW
{
SYSTEM_INFO sysinfo;
-#ifndef Q_OS_WINRT
GetSystemInfo(&sysinfo);
-#else
- GetNativeSystemInfo(&sysinfo);
-#endif
return sysinfo.dwNumberOfProcessors;
}
-#ifndef Q_OS_WINRT
void QThread::yieldCurrentThread()
{
#ifndef Q_OS_WINCE
@@ -501,28 +431,6 @@ void QThread::usleep(unsigned long usecs)
{
::Sleep((usecs / 1000) + 1);
}
-#else // !Q_OS_WINRT
-
-void QThread::yieldCurrentThread()
-{
- msleep(1);
-}
-
-void QThread::sleep(unsigned long secs)
-{
- msleep(secs * 1000);
-}
-
-void QThread::msleep(unsigned long msecs)
-{
- WaitForSingleObjectEx(GetCurrentThread(), msecs, FALSE);
-}
-
-void QThread::usleep(unsigned long usecs)
-{
- msleep((usecs / 1000) + 1);
-}
-#endif // Q_OS_WINRT
void QThread::start(Priority priority)
{
@@ -544,7 +452,6 @@ void QThread::start(Priority priority)
d->returnCode = 0;
d->interruptionRequested = false;
-#ifndef Q_OS_WINRT
/*
NOTE: we create the thread in the suspended state, set the
priority and then resume the thread.
@@ -609,23 +516,6 @@ void QThread::start(Priority priority)
if (ResumeThread(d->handle) == (DWORD) -1) {
qErrnoWarning("QThread::start: Failed to resume new thread");
}
-#else // !Q_OS_WINRT
- d->handle = new std::thread(QThreadPrivate::start, this);
-
- if (!d->handle) {
- qErrnoWarning(errno, "QThread::start: Failed to create thread");
- d->running = false;
- d->finished = true;
- return;
- }
-
- d->id = d->handle->get_id();
-
- if (priority != NormalPriority || priority != InheritPriority) {
- qWarning("QThread::start: Failed to set thread priority (not implemented)");
- d->priority = NormalPriority;
- }
-#endif // Q_OS_WINRT
}
void QThread::terminate()
@@ -639,11 +529,7 @@ void QThread::terminate()
return;
}
-#ifndef Q_OS_WINRT
TerminateThread(d->handle, 0);
-#else // !Q_OS_WINRT
- qWarning("QThread::terminate: Terminate is not supported on WinRT");
-#endif // Q_OS_WINRT
QThreadPrivate::finish(this, false);
}
@@ -652,11 +538,7 @@ bool QThread::wait(unsigned long time)
Q_D(QThread);
QMutexLocker locker(&d->mutex);
-#ifndef Q_OS_WINRT
if (d->id == GetCurrentThreadId()) {
-#else
- if (d->id == std::this_thread::get_id()) {
-#endif
qWarning("QThread::wait: Thread tried to wait on itself");
return false;
}
@@ -667,7 +549,6 @@ bool QThread::wait(unsigned long time)
locker.mutex()->unlock();
bool ret = false;
-#ifndef Q_OS_WINRT
switch (WaitForSingleObject(d->handle, time)) {
case WAIT_OBJECT_0:
ret = true;
@@ -680,14 +561,6 @@ bool QThread::wait(unsigned long time)
default:
break;
}
-#else // !Q_OS_WINRT
- if (!d->finished) {
- QElapsedTimer timer;
- timer.start();
- while (timer.elapsed() < time && !d->finished)
- yieldCurrentThread();
- }
-#endif // Q_OS_WINRT
locker.mutex()->lock();
--d->waiters;
@@ -699,12 +572,7 @@ bool QThread::wait(unsigned long time)
}
if (d->finished && !d->waiters) {
-#ifndef Q_OS_WINRT
CloseHandle(d->handle);
-#else
- d->handle->detach();
- delete d->handle;
-#endif
d->handle = 0;
}
@@ -722,16 +590,13 @@ void QThread::setTerminationEnabled(bool enabled)
if (enabled && d->terminatePending) {
QThreadPrivate::finish(thr, false);
locker.unlock(); // don't leave the mutex locked!
-#ifndef Q_OS_WINRT
_endthreadex(0);
-#endif
}
}
// Caller must hold the mutex
void QThreadPrivate::setPriority(QThread::Priority threadPriority)
{
-#ifndef Q_OS_WINRT
// copied from start() with a few modifications:
int prio;
@@ -774,12 +639,6 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority)
if (!SetThreadPriority(handle, prio)) {
qErrnoWarning("QThread::setPriority: Failed to set thread priority");
}
-#else // !Q_OS_WINRT
- if (priority != threadPriority) {
- qWarning("QThread::setPriority: Failed to set thread priority (not implemented)");
- return;
- }
-#endif // Q_OS_WINRT
}
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qthread_winrt.cpp b/src/corelib/thread/qthread_winrt.cpp
new file mode 100644
index 0000000000..85860dc545
--- /dev/null
+++ b/src/corelib/thread/qthread_winrt.cpp
@@ -0,0 +1,458 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qthread.h"
+#include "qthread_p.h"
+#include "qthreadstorage.h"
+
+#include <QtCore/QElapsedTimer>
+#include <QtCore/QUuid>
+#include <QtCore/qt_windows.h>
+#include <QtCore/qfunctions_winrt.h>
+#include <QtCore/private/qcoreapplication_p.h>
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+
+#include <wrl.h>
+#include <windows.system.threading.h>
+#include <windows.system.threading.core.h>
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::System::Threading;
+using namespace ABI::Windows::System::Threading::Core;
+
+#ifndef QT_NO_THREAD
+QT_BEGIN_NAMESPACE
+
+static WorkItemPriority nativePriority(QThread::Priority priority)
+{
+ switch (priority) {
+ default:
+ case QThread::NormalPriority:
+ return WorkItemPriority_Normal;
+ case QThread::IdlePriority:
+ case QThread::LowestPriority:
+ case QThread::LowPriority:
+ return WorkItemPriority_Low;
+ case QThread::HighPriority:
+ case QThread::HighestPriority:
+ case QThread::TimeCriticalPriority:
+ return WorkItemPriority_High;
+ }
+}
+
+class QWinRTThreadGlobal
+{
+public:
+ QWinRTThreadGlobal()
+ {
+ HRESULT hr;
+
+ hr = RoGetActivationFactory(
+ HString::MakeReference(RuntimeClass_Windows_System_Threading_Core_PreallocatedWorkItem).Get(),
+ IID_PPV_ARGS(&workItemFactory));
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = RoGetActivationFactory(
+ HString::MakeReference(RuntimeClass_Windows_System_Threading_Core_SignalNotifier).Get(),
+ IID_PPV_ARGS(&notifierFactory));
+ Q_ASSERT_SUCCEEDED(hr);
+
+ QString eventName = QUuid::createUuid().toString();
+ dispatchEvent = CreateEventEx(NULL, reinterpret_cast<LPCWSTR>(eventName.utf16()), 0, EVENT_ALL_ACCESS);
+
+ hr = notifierFactory->AttachToEvent(
+ HStringReference(reinterpret_cast<LPCWSTR>(eventName.utf16())).Get(),
+ Callback<ISignalHandler>(this, &QWinRTThreadGlobal::dispatch).Get(), &notifier);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = notifier->Enable();
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+
+ ~QWinRTThreadGlobal()
+ {
+ CloseHandle(dispatchEvent);
+ }
+
+ void dispatch()
+ {
+ SetEvent(dispatchEvent);
+ }
+
+ void push(QThreadPrivate *d)
+ {
+ threads.append(d);
+ }
+
+private:
+ HRESULT dispatch(ISignalNotifier *notifier, boolean timedOut)
+ {
+ Q_UNUSED(timedOut);
+ notifier->Enable();
+ if (threads.isEmpty())
+ return S_OK;
+
+ QThreadPrivate *thread = threads.takeFirst();
+ ComPtr<IPreallocatedWorkItem> workItem;
+ HRESULT hr = workItemFactory->CreateWorkItemWithPriority(
+ Callback<IWorkItemHandler>(thread, &QThreadPrivate::start).Get(),
+ nativePriority(thread->priority), &workItem);
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Failed to create thread work item");
+ thread->finish();
+ return hr;
+ }
+
+ hr = workItem->RunAsync(&thread->handle);
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Failed to run work item");
+ thread->finish();
+ return hr;
+ }
+
+ return S_OK;
+ }
+
+ HANDLE dispatchEvent;
+ ComPtr<ISignalNotifier> notifier;
+ ComPtr<ISignalNotifierStatics> notifierFactory;
+ ComPtr<IPreallocatedWorkItemFactory> workItemFactory;
+
+ QList<QThreadPrivate *> threads;
+};
+Q_GLOBAL_STATIC(QWinRTThreadGlobal, g)
+
+/**************************************************************************
+ ** QThreadData
+ *************************************************************************/
+
+__declspec(thread) static QThreadData *qt_current_thread_data = 0;
+
+void QThreadData::clearCurrentThreadData()
+{
+ qt_current_thread_data = 0;
+}
+
+QThreadData *QThreadData::current(bool createIfNecessary)
+{
+ static bool winmainThread = true;
+ QThreadData *threadData = qt_current_thread_data;
+ if (!threadData && createIfNecessary) {
+ threadData = new QThreadData;
+ // This needs to be called prior to new AdoptedThread() to
+ // avoid recursion.
+ qt_current_thread_data = threadData;
+ QT_TRY {
+ threadData->thread = new QAdoptedThread(threadData);
+ } QT_CATCH(...) {
+ qt_current_thread_data = 0;
+ threadData->deref();
+ threadData = 0;
+ QT_RETHROW;
+ }
+ threadData->deref();
+ threadData->isAdopted = true;
+ threadData->threadId = reinterpret_cast<Qt::HANDLE>(GetCurrentThreadId());
+
+ if (!QCoreApplicationPrivate::theMainThread && !winmainThread)
+ QCoreApplicationPrivate::theMainThread = threadData->thread;
+
+ if (winmainThread) {
+ g->dispatch();
+ threadData->thread->d_func()->createEventDispatcher(threadData);
+ winmainThread = false;
+ }
+ }
+
+ return threadData;
+}
+
+void QAdoptedThread::init()
+{
+ Q_D(QThread);
+
+ d->handle = Q_NULLPTR;
+ d->id = 0;
+}
+
+/**************************************************************************
+ ** QThreadPrivate
+ *************************************************************************/
+
+#endif // QT_NO_THREAD
+
+void QThreadPrivate::createEventDispatcher(QThreadData *data)
+{
+ QEventDispatcherWinRT *eventDispatcher = new QEventDispatcherWinRT;
+ data->eventDispatcher.storeRelease(eventDispatcher);
+ eventDispatcher->startingUp();
+}
+
+#ifndef QT_NO_THREAD
+
+HRESULT QThreadPrivate::start(IAsyncAction *)
+{
+ Q_Q(QThread);
+
+ qt_current_thread_data = data;
+ id = GetCurrentThreadId();
+ data->threadId = reinterpret_cast<Qt::HANDLE>(id);
+ QThread::setTerminationEnabled(false);
+
+ {
+ QMutexLocker locker(&mutex);
+ data->quitNow = exited;
+ }
+
+ if (data->eventDispatcher.load())
+ data->eventDispatcher.load()->startingUp();
+ else
+ createEventDispatcher(data);
+
+ running = true;
+ emit q->started(QThread::QPrivateSignal());
+
+ QThread::setTerminationEnabled(true);
+
+ q->run();
+
+ finish();
+
+ return S_OK;
+}
+
+void QThreadPrivate::finish(bool lockAnyway)
+{
+ Q_Q(QThread);
+
+ QMutexLocker locker(lockAnyway ? &mutex : 0);
+ isInFinish = true;
+ priority = QThread::InheritPriority;
+ void **tls_data = reinterpret_cast<void **>(&data->tls);
+ locker.unlock();
+ emit q->finished(QThread::QPrivateSignal());
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QThreadStorageData::finish(tls_data);
+ locker.relock();
+
+ QAbstractEventDispatcher *eventDispatcher = data->eventDispatcher.load();
+ if (eventDispatcher) {
+ data->eventDispatcher = 0;
+ locker.unlock();
+ eventDispatcher->closingDown();
+ delete eventDispatcher;
+ locker.relock();
+ }
+
+ running = false;
+ finished = true;
+ isInFinish = false;
+ interruptionRequested = false;
+
+ if (!waiters) {
+ if (handle)
+ handle->Release();
+ handle = Q_NULLPTR;
+ }
+
+ id = 0;
+}
+
+/**************************************************************************
+ ** QThread
+ *************************************************************************/
+
+Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW
+{
+ return reinterpret_cast<Qt::HANDLE>(GetCurrentThreadId());
+}
+
+int QThread::idealThreadCount() Q_DECL_NOTHROW
+{
+ SYSTEM_INFO sysinfo;
+ GetNativeSystemInfo(&sysinfo);
+ return sysinfo.dwNumberOfProcessors;
+}
+
+void QThread::yieldCurrentThread()
+{
+ msleep(1);
+}
+
+void QThread::sleep(unsigned long secs)
+{
+ msleep(secs * 1000);
+}
+
+void QThread::msleep(unsigned long msecs)
+{
+ WaitForSingleObjectEx(GetCurrentThread(), msecs, FALSE);
+}
+
+void QThread::usleep(unsigned long usecs)
+{
+ msleep((usecs / 1000) + 1);
+}
+
+void QThread::start(Priority priority)
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+
+ if (d->isInFinish) {
+ locker.unlock();
+ wait();
+ locker.relock();
+ }
+
+ if (d->running)
+ return;
+
+ d->finished = false;
+ d->exited = false;
+ d->returnCode = 0;
+ d->interruptionRequested = false;
+ d->priority = priority == QThread::InheritPriority ? currentThread()->priority() : priority;
+ g->push(d);
+ g->dispatch();
+
+ locker.unlock();
+ while (!d->running && !d->finished) {
+ QAbstractEventDispatcher *eventDispatcher = QThread::currentThread()->eventDispatcher();
+ if (eventDispatcher)
+ eventDispatcher->processEvents(QEventLoop::AllEvents);
+ else
+ yieldCurrentThread();
+ }
+}
+
+void QThread::terminate()
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+ if (!d->running)
+ return;
+ if (!d->terminationEnabled) {
+ d->terminatePending = true;
+ return;
+ }
+
+ if (d->handle) {
+ ComPtr<IAsyncInfo> info;
+ HRESULT hr = d->handle->QueryInterface(IID_PPV_ARGS(&info));
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = info->Cancel();
+ if (FAILED(hr))
+ qErrnoWarning(hr, "Failed to cancel thread action");
+ }
+
+ d->finish(false);
+}
+
+bool QThread::wait(unsigned long time)
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+
+ if (d->id == GetCurrentThreadId()) {
+ qWarning("QThread::wait: Thread tried to wait on itself");
+ return false;
+ }
+ if (d->finished || !d->running)
+ return true;
+
+ ++d->waiters;
+ locker.mutex()->unlock();
+
+ // Alternatively, we could check the handle
+ bool ret = false;
+ if (!d->finished) {
+ QElapsedTimer timer;
+ timer.start();
+ while (timer.elapsed() < time && !d->finished)
+ yieldCurrentThread();
+
+ ret = d->finished;
+ }
+
+ locker.mutex()->lock();
+ --d->waiters;
+
+ if (ret && !d->finished) {
+ // thread was terminated by someone else
+
+ d->finish(false);
+ }
+
+ if (d->finished && !d->waiters) {
+ if (d->handle)
+ d->handle->Release();
+ d->handle = Q_NULLPTR;
+ }
+
+ return ret;
+}
+
+void QThread::setTerminationEnabled(bool enabled)
+{
+ QThread *thr = currentThread();
+ Q_ASSERT_X(thr != 0, "QThread::setTerminationEnabled()",
+ "Current thread was not started with QThread.");
+ QThreadPrivate *d = thr->d_func();
+ QMutexLocker locker(&d->mutex);
+ d->terminationEnabled = enabled;
+ if (enabled && d->terminatePending) {
+ d->finish(false);
+ locker.unlock(); // don't leave the mutex locked!
+ }
+}
+
+// Caller must hold the mutex
+void QThreadPrivate::setPriority(QThread::Priority threadPriority)
+{
+ if (running)
+ qWarning("WinRT threads can't change priority while running.");
+
+ priority = threadPriority;
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri
index 3c1ddd984a..2e027c8e21 100644
--- a/src/corelib/thread/thread.pri
+++ b/src/corelib/thread/thread.pri
@@ -50,6 +50,11 @@ win32:SOURCES += thread/qmutex_win.cpp \
thread/qthread_win.cpp \
thread/qwaitcondition_win.cpp
+winrt {
+ SOURCES -= thread/qthread_win.cpp
+ SOURCES += thread/qthread_winrt.cpp
+}
+
integrity:SOURCES += thread/qmutex_unix.cpp \
thread/qthread_unix.cpp \
thread/qwaitcondition_unix.cpp
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp
index 12736d5c2e..4047bf611f 100644
--- a/src/corelib/tools/qarraydata.cpp
+++ b/src/corelib/tools/qarraydata.cpp
@@ -68,7 +68,7 @@ static const QArrayData &qt_array_empty = qt_array[0];
static const QArrayData &qt_array_unsharable_empty = qt_array[1];
QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
- size_t capacity, AllocationOptions options)
+ size_t capacity, AllocationOptions options) Q_DECL_NOTHROW
{
// Alignment is a power of two
Q_ASSERT(alignment >= Q_ALIGNOF(QArrayData)
@@ -114,7 +114,7 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
}
void QArrayData::deallocate(QArrayData *data, size_t objectSize,
- size_t alignment)
+ size_t alignment) Q_DECL_NOTHROW
{
// Alignment is a power of two
Q_ASSERT(alignment >= Q_ALIGNOF(QArrayData)
@@ -130,4 +130,33 @@ void QArrayData::deallocate(QArrayData *data, size_t objectSize,
::free(data);
}
+namespace QtPrivate {
+/*!
+ \internal
+*/
+QContainerImplHelper::CutResult QContainerImplHelper::mid(int originalLength, int *_position, int *_length)
+{
+ int &position = *_position;
+ int &length = *_length;
+ if (position > originalLength)
+ return Null;
+
+ if (position < 0) {
+ if (length < 0 || length + position >= originalLength)
+ return Full;
+ if (length + position <= 0)
+ return Null;
+ length += position;
+ position = 0;
+ } else if (uint(length) > uint(originalLength - position)) {
+ length = originalLength - position;
+ }
+
+ if (position == 0 && length == originalLength)
+ return Full;
+
+ return length > 0 ? Subset : Empty;
+}
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h
index 10a9e35542..dd2b777ed7 100644
--- a/src/corelib/tools/qarraydata.h
+++ b/src/corelib/tools/qarraydata.h
@@ -101,10 +101,6 @@ struct Q_CORE_EXPORT QArrayData
AllocationOptions detachFlags() const
{
AllocationOptions result;
-#if QT_SUPPORTS(UNSHARABLE_CONTAINERS)
- if (!ref.isSharable())
- result |= Unsharable;
-#endif
if (capacityReserved)
result |= CapacityReserved;
return result;
@@ -120,9 +116,9 @@ struct Q_CORE_EXPORT QArrayData
static QArrayData *allocate(size_t objectSize, size_t alignment,
size_t capacity, AllocationOptions options = Default)
- Q_REQUIRED_RESULT;
+ Q_DECL_NOTHROW Q_REQUIRED_RESULT;
static void deallocate(QArrayData *data, size_t objectSize,
- size_t alignment);
+ size_t alignment) Q_DECL_NOTHROW;
static const QArrayData shared_null[2];
static QArrayData *sharedNull() { return const_cast<QArrayData*>(shared_null); }
@@ -361,6 +357,14 @@ namespace QtPrivate {
QT_PREPEND_NAMESPACE(QtPrivate::qMakeArrayLiteral)<Type>( Array )
#endif // !defined(Q_ARRAY_LITERAL)
+namespace QtPrivate {
+struct Q_CORE_EXPORT QContainerImplHelper
+{
+ enum CutResult { Null, Empty, Full, Subset };
+ static CutResult mid(int originalLength, int *position, int *length);
+};
+}
+
QT_END_NAMESPACE
#endif // include guard
diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h
index b94c6b50ea..c7ea6ebf86 100644
--- a/src/corelib/tools/qarraydataops.h
+++ b/src/corelib/tools/qarraydataops.h
@@ -57,6 +57,7 @@ struct QPodArrayOps
{
void appendInitialize(size_t newSize)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(newSize > uint(this->size));
Q_ASSERT(newSize <= this->alloc);
@@ -67,6 +68,7 @@ struct QPodArrayOps
void copyAppend(const T *b, const T *e)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(b < e);
Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
@@ -77,6 +79,7 @@ struct QPodArrayOps
void copyAppend(size_t n, const T &t)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(n <= this->alloc - uint(this->size));
@@ -89,6 +92,7 @@ struct QPodArrayOps
void truncate(size_t newSize)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(newSize < size_t(this->size));
@@ -97,6 +101,7 @@ struct QPodArrayOps
void destroyAll() // Call from destructors, ONLY!
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(this->ref.atomic.load() == 0);
// As this is to be called only from destructor, it doesn't need to be
@@ -105,6 +110,7 @@ struct QPodArrayOps
void insert(T *where, const T *b, const T *e)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
Q_ASSERT(b < e);
@@ -118,6 +124,7 @@ struct QPodArrayOps
void erase(T *b, T *e)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(b < e);
Q_ASSERT(b >= this->begin() && b < this->end());
Q_ASSERT(e > this->begin() && e < this->end());
@@ -133,6 +140,7 @@ struct QGenericArrayOps
{
void appendInitialize(size_t newSize)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(newSize > uint(this->size));
Q_ASSERT(newSize <= this->alloc);
@@ -145,6 +153,7 @@ struct QGenericArrayOps
void copyAppend(const T *b, const T *e)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(b < e);
Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
@@ -158,6 +167,7 @@ struct QGenericArrayOps
void copyAppend(size_t n, const T &t)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(n <= this->alloc - uint(this->size));
@@ -171,6 +181,7 @@ struct QGenericArrayOps
void truncate(size_t newSize)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(newSize < size_t(this->size));
@@ -182,6 +193,7 @@ struct QGenericArrayOps
void destroyAll() // Call from destructors, ONLY
{
+ Q_ASSERT(this->isMutable());
// As this is to be called only from destructor, it doesn't need to be
// exception safe; size not updated.
@@ -196,6 +208,7 @@ struct QGenericArrayOps
void insert(T *where, const T *b, const T *e)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
Q_ASSERT(b < e);
@@ -261,6 +274,7 @@ struct QGenericArrayOps
void erase(T *b, T *e)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(b < e);
Q_ASSERT(b >= this->begin() && b < this->end());
Q_ASSERT(e > this->begin() && e < this->end());
@@ -290,6 +304,7 @@ struct QMovableArrayOps
void insert(T *where, const T *b, const T *e)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
Q_ASSERT(b < e);
@@ -354,6 +369,7 @@ struct QMovableArrayOps
void erase(T *b, T *e)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(b < e);
Q_ASSERT(b >= this->begin() && b < this->end());
Q_ASSERT(e > this->begin() && e < this->end());
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index fb92d82f07..52af67c86a 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -48,6 +48,7 @@
#include "qlocale_p.h"
#include "qscopedpointer.h"
#include <qdatastream.h>
+#include <qmath.h>
#ifndef QT_NO_COMPRESS
#include <zlib.h>
@@ -67,24 +68,12 @@ int qFindByteArray(
const char *needle0, int needleLen);
-int qAllocMore(int alloc, int extra)
+int qAllocMore(int alloc, int extra) Q_DECL_NOTHROW
{
Q_ASSERT(alloc >= 0 && extra >= 0);
Q_ASSERT_X(alloc < (1 << 30) - extra, "qAllocMore", "Requested size is too large!");
- unsigned nalloc = alloc + extra;
-
- // Round up to next power of 2
-
- // Assuming container is growing, always overshoot
- //--nalloc;
-
- nalloc |= nalloc >> 1;
- nalloc |= nalloc >> 2;
- nalloc |= nalloc >> 4;
- nalloc |= nalloc >> 8;
- nalloc |= nalloc >> 16;
- ++nalloc;
+ unsigned nalloc = qNextPowerOfTwo(alloc + extra);
Q_ASSERT(nalloc > unsigned(alloc + extra));
@@ -2677,19 +2666,22 @@ QByteArray QByteArray::right(int len) const
QByteArray QByteArray::mid(int pos, int len) const
{
- if ((d->size == 0 && d->ref.isStatic()) || pos > d->size)
+ using namespace QtPrivate;
+ switch (QContainerImplHelper::mid(size(), &pos, &len)) {
+ case QContainerImplHelper::Null:
return QByteArray();
- if (len < 0)
- len = d->size - pos;
- if (pos < 0) {
- len += pos;
- pos = 0;
+ case QContainerImplHelper::Empty:
+ {
+ QByteArrayDataPtr empty = { Data::allocate(0) };
+ return QByteArray(empty);
}
- if (len + pos > d->size)
- len = d->size - pos;
- if (pos == 0 && len == d->size)
+ case QContainerImplHelper::Full:
return *this;
- return QByteArray(d->data() + pos, len);
+ case QContainerImplHelper::Subset:
+ return QByteArray(d->data() + pos, len);
+ }
+ Q_UNREACHABLE();
+ return QByteArray();
}
/*!
@@ -4186,6 +4178,27 @@ QByteArray QByteArray::fromPercentEncoding(const QByteArray &input, char percent
return tmp;
}
+/*! \fn QByteArray QByteArray::fromStdString(const std::string &str)
+ \since 5.4
+
+ Returns a copy of the \a str string as a QByteArray.
+
+ \sa toStdString(), QString::fromStdString()
+*/
+
+/*!
+ \fn std::string QByteArray::toStdString() const
+ \since 5.4
+
+ Returns a std::string object with the data contained in this
+ QByteArray.
+
+ This operator is mostly useful to pass a QByteArray to a function
+ that accepts a std::string object.
+
+ \sa fromStdString(), QString::toStdString()
+*/
+
/*! \fn QByteArray QByteArray::fromCFData(CFDataRef data)
\since 5.3
diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h
index 0a2f7a9e53..b5af305233 100644
--- a/src/corelib/tools/qbytearray.h
+++ b/src/corelib/tools/qbytearray.h
@@ -50,6 +50,8 @@
#include <string.h>
#include <stdarg.h>
+#include <string>
+
#ifdef truncate
#error qbytearray.h must be included before any header file that defines truncate
#endif
@@ -247,9 +249,9 @@ public:
int count(const char *a) const;
int count(const QByteArray &a) const;
- QByteArray left(int len) const;
- QByteArray right(int len) const;
- QByteArray mid(int index, int len = -1) const;
+ 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;
bool startsWith(const QByteArray &a) const;
bool startsWith(char c) const;
@@ -262,13 +264,13 @@ public:
void truncate(int pos);
void chop(int n);
- QByteArray toLower() const;
- QByteArray toUpper() const;
+ QByteArray toLower() const Q_REQUIRED_RESULT;
+ QByteArray toUpper() const Q_REQUIRED_RESULT;
- QByteArray trimmed() const;
- QByteArray simplified() const;
- QByteArray leftJustified(int width, char fill = ' ', bool truncate = false) const;
- QByteArray rightJustified(int width, char fill = ' ', bool truncate = false) const;
+ QByteArray trimmed() const Q_REQUIRED_RESULT;
+ QByteArray simplified() const Q_REQUIRED_RESULT;
+ QByteArray leftJustified(int width, char fill = ' ', bool truncate = false) const Q_REQUIRED_RESULT;
+ QByteArray rightJustified(int width, char fill = ' ', bool truncate = false) const Q_REQUIRED_RESULT;
QByteArray &prepend(char c);
QByteArray &prepend(const char *s);
@@ -300,7 +302,7 @@ public:
QList<QByteArray> split(char sep) const;
- QByteArray repeated(int times) const;
+ QByteArray repeated(int times) const Q_REQUIRED_RESULT;
#ifndef QT_NO_CAST_TO_ASCII
QT_ASCII_CAST_WARN QByteArray &append(const QString &s);
@@ -349,16 +351,16 @@ public:
QByteArray &setNum(double, char f = 'g', int prec = 6);
QByteArray &setRawData(const char *a, uint n); // ### Qt 6: use an int
- static QByteArray number(int, int base = 10);
- static QByteArray number(uint, int base = 10);
- static QByteArray number(qlonglong, int base = 10);
- static QByteArray number(qulonglong, int base = 10);
- static QByteArray number(double, char f = 'g', int prec = 6);
- static QByteArray fromRawData(const char *, int size);
- static QByteArray fromBase64(const QByteArray &base64, Base64Options options);
- static QByteArray fromBase64(const QByteArray &base64); // ### Qt6 merge with previous
- static QByteArray fromHex(const QByteArray &hexEncoded);
- static QByteArray fromPercentEncoding(const QByteArray &pctEncoded, char percent = '%');
+ static QByteArray number(int, int base = 10) Q_REQUIRED_RESULT;
+ static QByteArray number(uint, int base = 10) Q_REQUIRED_RESULT;
+ static QByteArray number(qlonglong, int base = 10) Q_REQUIRED_RESULT;
+ static QByteArray number(qulonglong, int base = 10) Q_REQUIRED_RESULT;
+ static QByteArray number(double, char f = 'g', int prec = 6) Q_REQUIRED_RESULT;
+ static QByteArray fromRawData(const char *, int size) Q_REQUIRED_RESULT;
+ static QByteArray fromBase64(const QByteArray &base64, Base64Options options) Q_REQUIRED_RESULT;
+ static QByteArray fromBase64(const QByteArray &base64) Q_REQUIRED_RESULT; // ### Qt6 merge with previous
+ static QByteArray fromHex(const QByteArray &hexEncoded) Q_REQUIRED_RESULT;
+ static QByteArray fromPercentEncoding(const QByteArray &pctEncoded, char percent = '%') Q_REQUIRED_RESULT;
#if defined(Q_OS_MAC) || defined(Q_QDOC)
static QByteArray fromCFData(CFDataRef data);
@@ -397,6 +399,9 @@ public:
void push_front(const char *c);
void push_front(const QByteArray &a);
+ static inline QByteArray fromStdString(const std::string &s);
+ inline std::string toStdString() const;
+
inline int count() const { return d->size; }
int length() const { return d->size; }
bool isNull() const;
@@ -620,6 +625,11 @@ inline QByteArray &QByteArray::setNum(uint n, int base)
inline QByteArray &QByteArray::setNum(float n, char f, int prec)
{ return setNum(double(n),f,prec); }
+inline std::string QByteArray::toStdString() const
+{ return std::string(constData(), length()); }
+
+inline QByteArray QByteArray::fromStdString(const std::string &s)
+{ return QByteArray(s.data(), int(s.size())); }
#if !defined(QT_NO_DATASTREAM) || (defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE))
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QByteArray &);
diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp
index eb59cc719f..656e57391f 100644
--- a/src/corelib/tools/qchar.cpp
+++ b/src/corelib/tools/qchar.cpp
@@ -1398,7 +1398,7 @@ QChar::UnicodeVersion QChar::currentUnicodeVersion()
template <typename T>
-static inline T toLowerCase_helper(T uc)
+Q_DECL_CONST_FUNCTION static inline T toLowerCase_helper(T uc)
{
const QUnicodeTables::Properties *p = qGetProp(uc);
if (p->lowerCaseSpecial) {
@@ -1409,7 +1409,7 @@ static inline T toLowerCase_helper(T uc)
}
template <typename T>
-static inline T toUpperCase_helper(T uc)
+Q_DECL_CONST_FUNCTION static inline T toUpperCase_helper(T uc)
{
const QUnicodeTables::Properties *p = qGetProp(uc);
if (p->upperCaseSpecial) {
@@ -1420,7 +1420,7 @@ static inline T toUpperCase_helper(T uc)
}
template <typename T>
-static inline T toTitleCase_helper(T uc)
+Q_DECL_CONST_FUNCTION static inline T toTitleCase_helper(T uc)
{
const QUnicodeTables::Properties *p = qGetProp(uc);
if (p->titleCaseSpecial) {
@@ -1431,7 +1431,7 @@ static inline T toTitleCase_helper(T uc)
}
template <typename T>
-static inline T toCaseFolded_helper(T uc)
+Q_DECL_CONST_FUNCTION static inline T toCaseFolded_helper(T uc)
{
const QUnicodeTables::Properties *p = qGetProp(uc);
if (p->caseFoldSpecial) {
diff --git a/src/corelib/tools/qchar.h b/src/corelib/tools/qchar.h
index 24c757f9f4..5dfd7b30f9 100644
--- a/src/corelib/tools/qchar.h
+++ b/src/corelib/tools/qchar.h
@@ -388,7 +388,7 @@ public:
QT_DEPRECATED inline char toAscii() const { return toLatin1(); }
#endif
inline char toLatin1() const;
- inline ushort unicode() const { return ucs; }
+ Q_DECL_CONSTEXPR inline ushort unicode() const { return ucs; }
inline ushort &unicode() { return ucs; }
#if QT_DEPRECATED_SINCE(5, 0)
@@ -450,50 +450,50 @@ public:
return ushort(ucs4%0x400 + 0xdc00);
}
- static Category QT_FASTCALL category(uint ucs4);
- static Direction QT_FASTCALL direction(uint ucs4);
- static JoiningType QT_FASTCALL joiningType(uint ucs4);
+ static Category QT_FASTCALL category(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static Direction QT_FASTCALL direction(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static JoiningType QT_FASTCALL joiningType(uint ucs4) Q_DECL_CONST_FUNCTION;
#if QT_DEPRECATED_SINCE(5, 3)
- QT_DEPRECATED static Joining QT_FASTCALL joining(uint ucs4);
+ QT_DEPRECATED static Joining QT_FASTCALL joining(uint ucs4) Q_DECL_CONST_FUNCTION;
#endif
- static unsigned char QT_FASTCALL combiningClass(uint ucs4);
+ static unsigned char QT_FASTCALL combiningClass(uint ucs4) Q_DECL_CONST_FUNCTION;
- static uint QT_FASTCALL mirroredChar(uint ucs4);
- static bool QT_FASTCALL hasMirrored(uint ucs4);
+ static uint QT_FASTCALL mirroredChar(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL hasMirrored(uint ucs4) Q_DECL_CONST_FUNCTION;
static QString QT_FASTCALL decomposition(uint ucs4);
- static Decomposition QT_FASTCALL decompositionTag(uint ucs4);
+ static Decomposition QT_FASTCALL decompositionTag(uint ucs4) Q_DECL_CONST_FUNCTION;
- static int QT_FASTCALL digitValue(uint ucs4);
- static uint QT_FASTCALL toLower(uint ucs4);
- static uint QT_FASTCALL toUpper(uint ucs4);
- static uint QT_FASTCALL toTitleCase(uint ucs4);
- static uint QT_FASTCALL toCaseFolded(uint ucs4);
+ static int QT_FASTCALL digitValue(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static uint QT_FASTCALL toLower(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static uint QT_FASTCALL toUpper(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static uint QT_FASTCALL toTitleCase(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static uint QT_FASTCALL toCaseFolded(uint ucs4) Q_DECL_CONST_FUNCTION;
- static Script QT_FASTCALL script(uint ucs4);
+ static Script QT_FASTCALL script(uint ucs4) Q_DECL_CONST_FUNCTION;
- static UnicodeVersion QT_FASTCALL unicodeVersion(uint ucs4);
+ static UnicodeVersion QT_FASTCALL unicodeVersion(uint ucs4) Q_DECL_CONST_FUNCTION;
- static UnicodeVersion QT_FASTCALL currentUnicodeVersion();
+ static UnicodeVersion QT_FASTCALL currentUnicodeVersion() Q_DECL_CONST_FUNCTION;
- static bool QT_FASTCALL isPrint(uint ucs4);
- static inline bool isSpace(uint ucs4);
- static bool QT_FASTCALL isMark(uint ucs4);
- static bool QT_FASTCALL isPunct(uint ucs4);
- static bool QT_FASTCALL isSymbol(uint ucs4);
- static inline bool isLetter(uint ucs4);
- static inline bool isNumber(uint ucs4);
- static inline bool isLetterOrNumber(uint ucs4);
- static inline bool isDigit(uint ucs4);
- static inline bool isLower(uint ucs4);
- static inline bool isUpper(uint ucs4);
- static inline bool isTitleCase(uint ucs4);
+ static bool QT_FASTCALL isPrint(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static inline bool isSpace(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL isMark(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL isPunct(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL isSymbol(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static inline bool isLetter(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static inline bool isNumber(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static inline bool isLetterOrNumber(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static inline bool isDigit(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static inline bool isLower(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static inline bool isUpper(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static inline bool isTitleCase(uint ucs4) Q_DECL_CONST_FUNCTION;
private:
- static bool QT_FASTCALL isSpace_helper(uint ucs4);
- static bool QT_FASTCALL isLetter_helper(uint ucs4);
- static bool QT_FASTCALL isNumber_helper(uint ucs4);
- static bool QT_FASTCALL isLetterOrNumber_helper(uint ucs4);
+ static bool QT_FASTCALL isSpace_helper(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL isLetter_helper(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL isNumber_helper(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL isLetterOrNumber_helper(uint ucs4) Q_DECL_CONST_FUNCTION;
#ifdef QT_NO_CAST_FROM_ASCII
QChar(char c);
diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp
index 505ab5f46d..168701d13c 100644
--- a/src/corelib/tools/qcommandlineparser.cpp
+++ b/src/corelib/tools/qcommandlineparser.cpp
@@ -495,10 +495,8 @@ void QCommandLineParser::process(const QStringList &arguments)
::exit(EXIT_FAILURE);
}
- if (d->builtinVersionOption && isSet(QStringLiteral("version"))) {
- printf("%s %s\n", qPrintable(QCoreApplication::applicationName()), qPrintable(QCoreApplication::applicationVersion()));
- ::exit(EXIT_SUCCESS);
- }
+ if (d->builtinVersionOption && isSet(QStringLiteral("version")))
+ showVersion();
if (d->builtinHelpOption && isSet(QStringLiteral("help")))
showHelp(EXIT_SUCCESS);
@@ -888,6 +886,22 @@ QStringList QCommandLineParser::unknownOptionNames() const
}
/*!
+ Displays the version information from QCoreApplication::applicationVersion(),
+ and exits the application.
+ This is automatically triggered by the --version option, but can also
+ be used to display the version when not using process().
+ The exit code is set to EXIT_SUCCESS (0).
+
+ \sa addVersionOption()
+ \since 5.4
+*/
+Q_NORETURN void QCommandLineParser::showVersion()
+{
+ fprintf(stdout, "%s %s\n", qPrintable(QCoreApplication::applicationName()), qPrintable(QCoreApplication::applicationVersion()));
+ ::exit(EXIT_SUCCESS);
+}
+
+/*!
Displays the help information, and exits the application.
This is automatically triggered by the --help option, but can also
be used to display the help when the user is not invoking the
diff --git a/src/corelib/tools/qcommandlineparser.h b/src/corelib/tools/qcommandlineparser.h
index 5a7061f031..946d4dd238 100644
--- a/src/corelib/tools/qcommandlineparser.h
+++ b/src/corelib/tools/qcommandlineparser.h
@@ -92,6 +92,7 @@ public:
QStringList optionNames() const;
QStringList unknownOptionNames() const;
+ Q_NORETURN void showVersion();
Q_NORETURN void showHelp(int exitCode = 0);
QString helpText() const;
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index d6f1d6c942..3c01edc83e 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -3194,7 +3194,7 @@ QTimeZone QDateTime::timeZone() const
return d->m_timeZone;
case Qt::UTC:
if (!d->m_timeZone.isValid())
- d->m_timeZone = QTimeZone("UTC");
+ d->m_timeZone = QTimeZone(QTimeZonePrivate::utcQByteArray());
return d->m_timeZone;
case Qt::TimeZone :
return d->m_timeZone;
@@ -3254,9 +3254,9 @@ QString QDateTime::timeZoneAbbreviation() const
{
switch (d->m_spec) {
case Qt::UTC:
- return QStringLiteral("UTC");
+ return QTimeZonePrivate::utcQString();
case Qt::OffsetFromUTC:
- return QLatin1String("UTC") + toOffsetString(Qt::ISODate, d->m_offsetFromUtc);
+ return QTimeZonePrivate::utcQString() + toOffsetString(Qt::ISODate, d->m_offsetFromUtc);
case Qt::TimeZone:
#ifndef QT_BOOTSTRAPPED
return d->m_timeZone.d->abbreviation(d->toMSecsSinceEpoch());
@@ -4976,7 +4976,7 @@ QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DATESTRING)
QDebug operator<<(QDebug dbg, const QDate &date)
{
- dbg.nospace() << "QDate(" << date.toString(QStringLiteral("yyyy-MM-dd")) << ')';
+ dbg.nospace() << "QDate(" << date.toString(Qt::ISODate) << ')';
return dbg.space();
}
diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h
index b9f6995155..ac7296f742 100644
--- a/src/corelib/tools/qdatetime.h
+++ b/src/corelib/tools/qdatetime.h
@@ -94,9 +94,9 @@ QT_DEPRECATED inline bool setYMD(int y, int m, int d)
void getDate(int *year, int *month, int *day);
- QDate addDays(qint64 days) const;
- QDate addMonths(int months) const;
- QDate addYears(int years) const;
+ QDate addDays(qint64 days) const Q_REQUIRED_RESULT;
+ QDate addMonths(int months) const Q_REQUIRED_RESULT;
+ QDate addYears(int years) const Q_REQUIRED_RESULT;
qint64 daysTo(const QDate &) const;
bool operator==(const QDate &other) const { return jd == other.jd; }
@@ -157,9 +157,9 @@ public:
#endif
bool setHMS(int h, int m, int s, int ms = 0);
- QTime addSecs(int secs) const;
+ QTime addSecs(int secs) const Q_REQUIRED_RESULT;
int secsTo(const QTime &) const;
- QTime addMSecs(int ms) const;
+ QTime addMSecs(int ms) const Q_REQUIRED_RESULT;
int msecsTo(const QTime &) const;
bool operator==(const QTime &other) const { return mds == other.mds; }
@@ -251,11 +251,11 @@ public:
QString toString(Qt::DateFormat f = Qt::TextDate) const;
QString toString(const QString &format) const;
#endif
- QDateTime addDays(qint64 days) const;
- QDateTime addMonths(int months) const;
- QDateTime addYears(int years) const;
- QDateTime addSecs(qint64 secs) const;
- QDateTime addMSecs(qint64 msecs) const;
+ QDateTime addDays(qint64 days) const Q_REQUIRED_RESULT;
+ QDateTime addMonths(int months) const Q_REQUIRED_RESULT;
+ QDateTime addYears(int years) const Q_REQUIRED_RESULT;
+ QDateTime addSecs(qint64 secs) const Q_REQUIRED_RESULT;
+ QDateTime addMSecs(qint64 msecs) const Q_REQUIRED_RESULT;
QDateTime toTimeSpec(Qt::TimeSpec spec) const;
inline QDateTime toLocalTime() const { return toTimeSpec(Qt::LocalTime); }
diff --git a/src/corelib/tools/qfreelist_p.h b/src/corelib/tools/qfreelist_p.h
index ca946cbd8a..d6d3a3ad3d 100644
--- a/src/corelib/tools/qfreelist_p.h
+++ b/src/corelib/tools/qfreelist_p.h
@@ -191,7 +191,7 @@ class QFreeList
Q_DISABLE_COPY(QFreeList)
public:
- inline QFreeList();
+ Q_DECL_CONSTEXPR inline QFreeList();
inline ~QFreeList();
// returns the payload for the given index \a x
@@ -207,7 +207,7 @@ public:
};
template <typename T, typename ConstantsType>
-inline QFreeList<T, ConstantsType>::QFreeList()
+Q_DECL_CONSTEXPR inline QFreeList<T, ConstantsType>::QFreeList()
: _next(ConstantsType::InitialNextValue)
{ }
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index 7200ea7993..c9271848ec 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -94,13 +94,14 @@ QT_BEGIN_NAMESPACE
(for instance, gcc 4.4 does that even at -O0).
*/
-#ifdef __SSE4_2__
+#if QT_COMPILER_SUPPORTS_HERE(SSE4_2)
static inline bool hasFastCrc32()
{
- return true;
+ return qCpuHasFeature(SSE4_2);
}
template <typename Char>
+QT_FUNCTION_TARGET(SSE4_2)
static uint crc32(const Char *ptr, size_t len, uint h)
{
// The CRC32 instructions from Nehalem calculate a 32-bit CRC32 checksum
@@ -163,6 +164,11 @@ static inline uint hash(const uchar *p, int len, uint seed) Q_DECL_NOTHROW
return h;
}
+uint qHashBits(const void *p, size_t len, uint seed) Q_DECL_NOTHROW
+{
+ return hash(static_cast<const uchar*>(p), int(len), seed);
+}
+
static inline uint hash(const QChar *p, int len, uint seed) Q_DECL_NOTHROW
{
uint h = seed;
@@ -669,6 +675,25 @@ void QHashData::checkSanity()
Types \c T1 and \c T2 must be supported by qHash().
*/
+/*! \fn uint qHashBits(const void *p, size_t len, uint seed = 0)
+ \relates QHash
+ \since 5.4
+
+ Returns the hash value for the memory block of size \a len pointed
+ to by \a p, using \a seed to seed the calculation.
+
+ Use this function only to implement qHash() for your own custom
+ types. E.g., here's how you could implement a qHash() overload for
+ std::vector<int>:
+
+ \snippet code/src_corelib_tools_qhash.cpp qhashbits
+
+ It bears repeating that the implementation of qHashBits() - like
+ the qHash() overloads offered by Qt - may change at any time. You
+ \b{must not} rely on the fact that qHashBits() will give the same
+ results (for the same inputs) across different Qt versions.
+*/
+
/*! \fn uint qHash(char key, uint seed = 0)
\relates QHash
\since 5.0
@@ -778,7 +803,7 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW
}
#endif
-/*! \fn uint qHash(QChar key, uint seed = 0)
+/*! \fn uint qHash(const QChar key, uint seed = 0)
\relates QHash
\since 5.0
@@ -961,8 +986,8 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW
A QHash's key type has additional requirements other than being an
assignable data type: it must provide operator==(), and there must also be
- a global qHash() function that returns a hash value for an argument of the
- key's type.
+ a qHash() function in the type's namespace that returns a hash value for an
+ argument of the key's type.
The qHash() function computes a numeric value based on a key. It
can use any algorithm imaginable, as long as it always returns
@@ -2127,8 +2152,8 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW
QMultiHash's key and value data types must be \l{assignable data
types}. You cannot, for example, store a QWidget as a value;
instead, store a QWidget *. In addition, QMultiHash's key type
- must provide operator==(), and there must also be a global
- qHash() function that returns a hash value for an argument of the
+ must provide operator==(), and there must also be a qHash() function
+ in the type's namespace that returns a hash value for an argument of the
key's type. See the QHash documentation for details.
\sa QHash, QHashIterator, QMutableHashIterator, QMultiMap
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index f68b02be2c..db2d084035 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -66,44 +66,40 @@ class QString;
class QStringRef;
class QLatin1String;
-inline uint qHash(char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-inline uint qHash(uchar key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-inline uint qHash(signed char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-inline uint qHash(ushort key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-inline uint qHash(short key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-inline uint qHash(uint key, uint seed = 0) Q_DECL_NOTHROW { return key ^ seed; }
-inline uint qHash(int key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-inline uint qHash(ulong key, uint seed = 0) Q_DECL_NOTHROW
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHashBits(const void *p, size_t size, uint seed = 0) Q_DECL_NOTHROW;
+
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(uchar key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(signed char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(ushort key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(short key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(uint key, uint seed = 0) Q_DECL_NOTHROW { return key ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(int key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(ulong key, uint seed = 0) Q_DECL_NOTHROW
{
- if (sizeof(ulong) > sizeof(uint)) {
- return uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U)) ^ seed;
- } else {
- return uint(key & (~0U)) ^ seed;
- }
+ return (sizeof(ulong) > sizeof(uint))
+ ? (uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U)) ^ seed)
+ : (uint(key & (~0U)) ^ seed);
}
-inline uint qHash(long key, uint seed = 0) Q_DECL_NOTHROW { return qHash(ulong(key), seed); }
-inline uint qHash(quint64 key, uint seed = 0) Q_DECL_NOTHROW
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(long key, uint seed = 0) Q_DECL_NOTHROW { return qHash(ulong(key), seed); }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(quint64 key, uint seed = 0) Q_DECL_NOTHROW
{
- if (sizeof(quint64) > sizeof(uint)) {
- return uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U)) ^ seed;
- } else {
- return uint(key & (~0U)) ^ seed;
- }
+ return uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U)) ^ seed;
}
-inline uint qHash(qint64 key, uint seed = 0) Q_DECL_NOTHROW { return qHash(quint64(key), seed); }
-Q_CORE_EXPORT uint qHash(float key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qHash(double key, uint seed = 0) Q_DECL_NOTHROW;
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(qint64 key, uint seed = 0) Q_DECL_NOTHROW { return qHash(quint64(key), seed); }
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(float key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(double key, uint seed = 0) Q_DECL_NOTHROW;
#ifndef Q_OS_DARWIN
-Q_CORE_EXPORT uint qHash(long double key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(long double key, uint seed = 0) Q_DECL_NOTHROW;
#endif
-inline uint qHash(QChar key, uint seed = 0) Q_DECL_NOTHROW { return qHash(key.unicode(), seed); }
-Q_CORE_EXPORT uint qHash(const QByteArray &key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qHash(const QString &key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qHash(const QStringRef &key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qHash(const QBitArray &key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qHash(QLatin1String key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qt_hash(const QString &key) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qt_hash(const QStringRef &key) Q_DECL_NOTHROW;
+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;
+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;
+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;
template <class T> inline uint qHash(const T *key, uint seed = 0) Q_DECL_NOTHROW
{
@@ -221,17 +217,23 @@ private:
Q_DISABLE_COPY(QHashNode)
};
-template <class Key, class T>
-struct QHashDummyNode
+// Specialize for QHashDummyValue in order to save some memory
+template <class Key>
+struct QHashNode<Key, QHashDummyValue>
{
- QHashNode<Key, T> *next;
+ union {
+ QHashNode *next;
+ QHashDummyValue value;
+ };
const uint h;
const Key key;
- inline QHashDummyNode(const Key &key0, uint hash, QHashNode<Key, T> *n) : next(n), h(hash), key(key0) {}
+ inline QHashNode(const Key &key0, const QHashDummyValue &, uint hash, QHashNode *n)
+ : next(n), h(hash), key(key0) {}
+ inline bool same_key(uint h0, const Key &key0) const { return h0 == h && key0 == key; }
private:
- Q_DISABLE_COPY(QHashDummyNode)
+ Q_DISABLE_COPY(QHashNode)
};
@@ -280,7 +282,6 @@ Q_HASH_DECLARE_INT_NODES(uint);
template <class Key, class T>
class QHash
{
- typedef QHashDummyNode<Key, T> DummyNode;
typedef QHashNode<Key, T> Node;
union {
@@ -293,7 +294,6 @@ class QHash
}
static inline int alignOfNode() { return qMax<int>(sizeof(void*), Q_ALIGNOF(Node)); }
- static inline int alignOfDummyNode() { return qMax<int>(sizeof(void*), Q_ALIGNOF(DummyNode)); }
public:
inline QHash() : d(const_cast<QHashData *>(&QHashData::shared_null)) { }
@@ -301,7 +301,7 @@ public:
inline QHash(std::initializer_list<std::pair<Key,T> > list)
: d(const_cast<QHashData *>(&QHashData::shared_null))
{
- reserve(list.size());
+ reserve(int(list.size()));
for (typename std::initializer_list<std::pair<Key,T> >::const_iterator it = list.begin(); it != list.end(); ++it)
insert(it->first, it->second);
}
@@ -558,25 +558,14 @@ template <class Key, class T>
Q_INLINE_TEMPLATE void QHash<Key, T>::duplicateNode(QHashData::Node *node, void *newNode)
{
Node *concreteNode = concrete(node);
- if (QTypeInfo<T>::isDummy) {
- (void) new (newNode) DummyNode(concreteNode->key, concreteNode->h, 0);
- } else {
- (void) new (newNode) Node(concreteNode->key, concreteNode->value, concreteNode->h, 0);
- }
+ new (newNode) Node(concreteNode->key, concreteNode->value, concreteNode->h, 0);
}
template <class Key, class T>
Q_INLINE_TEMPLATE typename QHash<Key, T>::Node *
QHash<Key, T>::createNode(uint ah, const Key &akey, const T &avalue, Node **anextNode)
{
- Node *node;
-
- if (QTypeInfo<T>::isDummy) {
- node = reinterpret_cast<Node *>(new (d->allocateNode(alignOfDummyNode())) DummyNode(akey, ah, *anextNode));
- } else {
- node = new (d->allocateNode(alignOfNode())) Node(akey, avalue, ah, *anextNode);
- }
-
+ Node *node = new (d->allocateNode(alignOfNode())) Node(akey, avalue, ah, *anextNode);
*anextNode = node;
++d->size;
return node;
@@ -609,9 +598,7 @@ Q_INLINE_TEMPLATE void QHash<Key, T>::clear()
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE void QHash<Key, T>::detach_helper()
{
- QHashData *x = d->detach_helper(duplicateNode, deleteNode2,
- QTypeInfo<T>::isDummy ? sizeof(DummyNode) : sizeof(Node),
- QTypeInfo<T>::isDummy ? alignOfDummyNode() : alignOfNode());
+ QHashData *x = d->detach_helper(duplicateNode, deleteNode2, sizeof(Node), alignOfNode());
if (!d->ref.deref())
freeData(d);
d = x;
@@ -793,7 +780,7 @@ Q_INLINE_TEMPLATE typename QHash<Key, T>::iterator QHash<Key, T>::insert(const K
return iterator(createNode(h, akey, avalue, node));
}
- if (!QTypeInfo<T>::isDummy)
+ if (!QtPrivate::is_same<T, QHashDummyValue>::value)
(*node)->value = avalue;
return iterator(*node);
}
@@ -962,7 +949,7 @@ Q_OUTOFLINE_TEMPLATE bool QHash<Key, T>::operator==(const QHash<Key, T> &other)
do {
if (it2 == other.end() || !(it2.key() == akey))
return false;
- if (!QTypeInfo<T>::isDummy && !(it.value() == it2.value()))
+ if (!(it.value() == it2.value()))
return false;
++it;
++it2;
@@ -979,7 +966,7 @@ public:
#ifdef Q_COMPILER_INITIALIZER_LISTS
inline QMultiHash(std::initializer_list<std::pair<Key,T> > list)
{
- this->reserve(list.size());
+ this->reserve(int(list.size()));
for (typename std::initializer_list<std::pair<Key,T> >::const_iterator it = list.begin(); it != list.end(); ++it)
insert(it->first, it->second);
}
diff --git a/src/corelib/tools/qiterator.h b/src/corelib/tools/qiterator.h
index 3b86edd750..86b78eb522 100644
--- a/src/corelib/tools/qiterator.h
+++ b/src/corelib/tools/qiterator.h
@@ -87,12 +87,9 @@ class QMutable##C##Iterator \
public: \
inline QMutable##C##Iterator(Q##C<T> &container) \
: c(&container) \
- { c->setSharable(false); i = c->begin(); n = c->end(); } \
- inline ~QMutable##C##Iterator() \
- { c->setSharable(true); } \
+ { i = c->begin(); n = c->end(); } \
inline QMutable##C##Iterator &operator=(Q##C<T> &container) \
- { c->setSharable(true); c = &container; c->setSharable(false); \
- i = c->begin(); n = c->end(); return *this; } \
+ { c = &container; i = c->begin(); n = c->end(); return *this; } \
inline void toFront() { i = c->begin(); n = c->end(); } \
inline void toBack() { i = c->end(); n = i; } \
inline bool hasNext() const { return c->constEnd() != const_iterator(i); } \
@@ -160,11 +157,9 @@ class QMutable##C##Iterator \
public: \
inline QMutable##C##Iterator(Q##C<Key,T> &container) \
: c(&container) \
- { c->setSharable(false); i = c->begin(); n = c->end(); } \
- inline ~QMutable##C##Iterator() \
- { c->setSharable(true); } \
+ { i = c->begin(); n = c->end(); } \
inline QMutable##C##Iterator &operator=(Q##C<Key,T> &container) \
- { c->setSharable(true); c = &container; c->setSharable(false); i = c->begin(); n = c->end(); return *this; } \
+ { c = &container; i = c->begin(); n = c->end(); return *this; } \
inline void toFront() { i = c->begin(); n = c->end(); } \
inline void toBack() { i = c->end(); n = c->end(); } \
inline bool hasNext() const { return const_iterator(i) != c->constEnd(); } \
diff --git a/src/corelib/tools/qiterator.qdoc b/src/corelib/tools/qiterator.qdoc
index 1ae9c58daa..f140af152d 100644
--- a/src/corelib/tools/qiterator.qdoc
+++ b/src/corelib/tools/qiterator.qdoc
@@ -501,17 +501,6 @@
\sa operator=()
*/
-/*!
- \fn QMutableListIterator::~QMutableListIterator()
- \fn QMutableLinkedListIterator::~QMutableLinkedListIterator()
- \fn QMutableVectorIterator::~QMutableVectorIterator()
- \fn QMutableSetIterator::~QMutableSetIterator()
-
- Destroys the iterator.
-
- \sa operator=()
-*/
-
/*! \fn QMutableListIterator &QMutableListIterator::operator=(QList<T> &list)
\fn QMutableLinkedListIterator &QMutableLinkedListIterator::operator=(QLinkedList<T> &list)
\fn QListIterator &QListIterator::operator=(const QList<T> &list)
@@ -1121,15 +1110,6 @@
\sa operator=()
*/
-/*!
- \fn QMutableMapIterator::~QMutableMapIterator()
- \fn QMutableHashIterator::~QMutableHashIterator()
-
- Destroys the iterator.
-
- \sa operator=()
-*/
-
/*! \fn QMapIterator &QMapIterator::operator=(const QMap<Key, T> &map)
\fn QMutableMapIterator &QMutableMapIterator::operator=(QMap<Key, T> &map)
diff --git a/src/corelib/tools/qline.cpp b/src/corelib/tools/qline.cpp
index 990e6bef09..61c7899ef4 100644
--- a/src/corelib/tools/qline.cpp
+++ b/src/corelib/tools/qline.cpp
@@ -259,10 +259,11 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug d, const QLine &p)
+QDebug operator<<(QDebug dbg, const QLine &p)
{
- d << "QLine(" << p.p1() << ',' << p.p2() << ')';
- return d;
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QLine(" << p.p1() << ',' << p.p2() << ')';
+ return dbg;
}
#endif
@@ -819,10 +820,11 @@ qreal QLineF::angle(const QLineF &l) const
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug d, const QLineF &p)
+QDebug operator<<(QDebug dbg, const QLineF &p)
{
- d << "QLineF(" << p.p1() << ',' << p.p2() << ')';
- return d;
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QLineF(" << p.p1() << ',' << p.p2() << ')';
+ return dbg;
}
#endif
diff --git a/src/corelib/tools/qline.h b/src/corelib/tools/qline.h
index 69e8a8245a..9b41d7b83e 100644
--- a/src/corelib/tools/qline.h
+++ b/src/corelib/tools/qline.h
@@ -75,8 +75,8 @@ public:
inline void translate(const QPoint &p);
inline void translate(int dx, int dy);
- Q_DECL_CONSTEXPR inline QLine translated(const QPoint &p) const;
- Q_DECL_CONSTEXPR inline QLine translated(int dx, int dy) const;
+ Q_DECL_CONSTEXPR inline QLine translated(const QPoint &p) const Q_REQUIRED_RESULT;
+ Q_DECL_CONSTEXPR inline QLine translated(int dx, int dy) const Q_REQUIRED_RESULT;
inline void setP1(const QPoint &p1);
inline void setP2(const QPoint &p2);
@@ -216,7 +216,7 @@ public:
Q_DECL_CONSTEXPR inline QLineF(qreal x1, qreal y1, qreal x2, qreal y2);
Q_DECL_CONSTEXPR inline QLineF(const QLine &line) : pt1(line.p1()), pt2(line.p2()) { }
- static QLineF fromPolar(qreal length, qreal angle);
+ static QLineF fromPolar(qreal length, qreal angle) Q_REQUIRED_RESULT;
Q_DECL_CONSTEXPR bool isNull() const;
@@ -240,8 +240,8 @@ public:
qreal angleTo(const QLineF &l) const;
- QLineF unitVector() const;
- Q_DECL_CONSTEXPR inline QLineF normalVector() const;
+ QLineF unitVector() const Q_REQUIRED_RESULT;
+ Q_DECL_CONSTEXPR inline QLineF normalVector() const Q_REQUIRED_RESULT;
// ### Qt 6: rename intersects() or intersection() and rename IntersectType IntersectionType
IntersectType intersect(const QLineF &l, QPointF *intersectionPoint) const;
@@ -252,8 +252,8 @@ public:
inline void translate(const QPointF &p);
inline void translate(qreal dx, qreal dy);
- Q_DECL_CONSTEXPR inline QLineF translated(const QPointF &p) const;
- Q_DECL_CONSTEXPR inline QLineF translated(qreal dx, qreal dy) const;
+ Q_DECL_CONSTEXPR inline QLineF translated(const QPointF &p) const Q_REQUIRED_RESULT;
+ Q_DECL_CONSTEXPR inline QLineF translated(qreal dx, qreal dy) const Q_REQUIRED_RESULT;
inline void setP1(const QPointF &p1);
inline void setP2(const QPointF &p2);
diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp
index 0811c3793e..db49fe9802 100644
--- a/src/corelib/tools/qlist.cpp
+++ b/src/corelib/tools/qlist.cpp
@@ -491,11 +491,11 @@ void **QListData::erase(void **xi)
/*!
\fn QList<T> QList<T>::mid(int pos, int length) const
- Returns a list whose elements are copied from this list,
+ Returns a sub-list which includes elements from this list,
starting at position \a pos. If \a length is -1 (the default), all
- elements from \a pos are copied; otherwise \a length elements (or
+ elements from \a pos are included; otherwise \a length elements (or
all remaining elements if there are less than \a length elements)
- are copied.
+ are included.
*/
/*! \fn QList::QList()
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index 9e4ba70908..4c52c22300 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -45,6 +45,7 @@
#include <QtCore/qalgorithms.h>
#include <QtCore/qiterator.h>
#include <QtCore/qrefcount.h>
+#include <QtCore/qarraydata.h>
#include <iterator>
#include <list>
@@ -646,10 +647,17 @@ inline void QList<T>::move(int from, int to)
template<typename T>
Q_OUTOFLINE_TEMPLATE QList<T> QList<T>::mid(int pos, int alength) const
{
- if (alength < 0 || pos > size() - alength)
- alength = size() - pos;
- if (pos == 0 && alength == size())
+ using namespace QtPrivate;
+ switch (QContainerImplHelper::mid(size(), &pos, &alength)) {
+ case QContainerImplHelper::Null:
+ case QContainerImplHelper::Empty:
+ return QList<T>();
+ case QContainerImplHelper::Full:
return *this;
+ case QContainerImplHelper::Subset:
+ break;
+ }
+
QList<T> cpy;
if (alength <= 0)
return cpy;
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index 98e38ca587..3754a1bfcf 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -2404,6 +2404,13 @@ Qt::LayoutDirection QLocale::textDirection() const
\since 4.8
Returns an uppercase copy of \a str.
+
+ If Qt Core is using the ICU libraries, they will be used to perform
+ the transformation according to the rules of the current locale.
+ Otherwise the conversion may be done in a platform-dependent manner,
+ with QString::toUpper() as a generic fallback.
+
+ \sa QString::toUpper()
*/
QString QLocale::toUpper(const QString &str) const
{
@@ -2421,6 +2428,13 @@ QString QLocale::toUpper(const QString &str) const
\since 4.8
Returns a lowercase copy of \a str.
+
+ If Qt Core is using the ICU libraries, they will be used to perform
+ the transformation according to the rules of the current locale.
+ Otherwise the conversion may be done in a platform-dependent manner,
+ with QString::toLower() as a generic fallback.
+
+ \sa QString::toLower()
*/
QString QLocale::toLower(const QString &str) const
{
diff --git a/src/corelib/tools/qpoint.cpp b/src/corelib/tools/qpoint.cpp
index 1063cda52b..090e8d0ff2 100644
--- a/src/corelib/tools/qpoint.cpp
+++ b/src/corelib/tools/qpoint.cpp
@@ -452,15 +452,18 @@ QDataStream &operator>>(QDataStream &s, QPoint &p)
*/
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QPoint &p) {
+QDebug operator<<(QDebug dbg, const QPoint &p)
+{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QPoint(" << p.x() << ',' << p.y() << ')';
- return dbg.space();
+ return dbg;
}
-QDebug operator<<(QDebug d, const QPointF &p)
+QDebug operator<<(QDebug dbg, const QPointF &p)
{
- d.nospace() << "QPointF(" << p.x() << ", " << p.y() << ')';
- return d.space();
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QPointF(" << p.x() << ',' << p.y() << ')';
+ return dbg;
}
#endif
diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp
index 382793f175..04269e485b 100644
--- a/src/corelib/tools/qrect.cpp
+++ b/src/corelib/tools/qrect.cpp
@@ -1286,10 +1286,12 @@ QDataStream &operator>>(QDataStream &s, QRect &r)
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QRect &r) {
+QDebug operator<<(QDebug dbg, const QRect &r)
+{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QRect(" << r.x() << ',' << r.y() << ' '
<< r.width() << 'x' << r.height() << ')';
- return dbg.space();
+ return dbg;
}
#endif
@@ -2493,10 +2495,12 @@ QDataStream &operator>>(QDataStream &s, QRectF &r)
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QRectF &r) {
+QDebug operator<<(QDebug dbg, const QRectF &r)
+{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QRectF(" << r.x() << ',' << r.y() << ' '
<< r.width() << 'x' << r.height() << ')';
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/corelib/tools/qrect.h b/src/corelib/tools/qrect.h
index 2bb74e8221..8ee08877e8 100644
--- a/src/corelib/tools/qrect.h
+++ b/src/corelib/tools/qrect.h
@@ -68,7 +68,7 @@ public:
Q_DECL_CONSTEXPR inline int top() const;
Q_DECL_CONSTEXPR inline int right() const;
Q_DECL_CONSTEXPR inline int bottom() const;
- QRect normalized() const;
+ QRect normalized() const Q_REQUIRED_RESULT;
Q_DECL_CONSTEXPR inline int x() const;
Q_DECL_CONSTEXPR inline int y() const;
@@ -102,8 +102,8 @@ public:
inline void translate(int dx, int dy);
inline void translate(const QPoint &p);
- Q_DECL_CONSTEXPR inline QRect translated(int dx, int dy) const;
- Q_DECL_CONSTEXPR inline QRect translated(const QPoint &p) const;
+ Q_DECL_CONSTEXPR inline QRect translated(int dx, int dy) const Q_REQUIRED_RESULT;
+ Q_DECL_CONSTEXPR inline QRect translated(const QPoint &p) const Q_REQUIRED_RESULT;
inline void moveTo(int x, int t);
inline void moveTo(const QPoint &p);
@@ -115,7 +115,7 @@ public:
inline void getCoords(int *x1, int *y1, int *x2, int *y2) const;
inline void adjust(int x1, int y1, int x2, int y2);
- Q_DECL_CONSTEXPR inline QRect adjusted(int x1, int y1, int x2, int y2) const;
+ Q_DECL_CONSTEXPR inline QRect adjusted(int x1, int y1, int x2, int y2) const Q_REQUIRED_RESULT;
Q_DECL_CONSTEXPR inline QSize size() const;
Q_DECL_CONSTEXPR inline int width() const;
@@ -133,8 +133,8 @@ public:
bool contains(const QPoint &p, bool proper=false) const;
inline bool contains(int x, int y) const;
inline bool contains(int x, int y, bool proper) const;
- inline QRect united(const QRect &other) const;
- inline QRect intersected(const QRect &other) const;
+ inline QRect united(const QRect &other) const Q_REQUIRED_RESULT;
+ inline QRect intersected(const QRect &other) const Q_REQUIRED_RESULT;
bool intersects(const QRect &r) const;
Q_DECL_CONSTEXPR inline QRect marginsAdded(const QMargins &margins) const;
@@ -143,8 +143,8 @@ public:
inline QRect &operator-=(const QMargins &margins);
#if QT_DEPRECATED_SINCE(5, 0)
- QT_DEPRECATED QRect unite(const QRect &r) const { return united(r); }
- QT_DEPRECATED QRect intersect(const QRect &r) const { return intersected(r); }
+ QT_DEPRECATED QRect unite(const QRect &r) const Q_REQUIRED_RESULT { return united(r); }
+ QT_DEPRECATED QRect intersect(const QRect &r) const Q_REQUIRED_RESULT { return intersected(r); }
#endif
friend Q_DECL_CONSTEXPR inline bool operator==(const QRect &, const QRect &);
@@ -510,7 +510,7 @@ public:
Q_DECL_CONSTEXPR inline bool isNull() const;
Q_DECL_CONSTEXPR inline bool isEmpty() const;
Q_DECL_CONSTEXPR inline bool isValid() const;
- QRectF normalized() const;
+ QRectF normalized() const Q_REQUIRED_RESULT;
Q_DECL_CONSTEXPR inline qreal left() const { return xp; }
Q_DECL_CONSTEXPR inline qreal top() const { return yp; }
@@ -550,8 +550,8 @@ public:
inline void translate(qreal dx, qreal dy);
inline void translate(const QPointF &p);
- Q_DECL_CONSTEXPR inline QRectF translated(qreal dx, qreal dy) const;
- Q_DECL_CONSTEXPR inline QRectF translated(const QPointF &p) const;
+ Q_DECL_CONSTEXPR inline QRectF translated(qreal dx, qreal dy) const Q_REQUIRED_RESULT;
+ Q_DECL_CONSTEXPR inline QRectF translated(const QPointF &p) const Q_REQUIRED_RESULT;
inline void moveTo(qreal x, qreal y);
inline void moveTo(const QPointF &p);
@@ -563,7 +563,7 @@ public:
inline void getCoords(qreal *x1, qreal *y1, qreal *x2, qreal *y2) const;
inline void adjust(qreal x1, qreal y1, qreal x2, qreal y2);
- Q_DECL_CONSTEXPR inline QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const;
+ Q_DECL_CONSTEXPR inline QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const Q_REQUIRED_RESULT;
Q_DECL_CONSTEXPR inline QSizeF size() const;
Q_DECL_CONSTEXPR inline qreal width() const;
@@ -580,8 +580,8 @@ public:
bool contains(const QRectF &r) const;
bool contains(const QPointF &p) const;
inline bool contains(qreal x, qreal y) const;
- inline QRectF united(const QRectF &other) const;
- inline QRectF intersected(const QRectF &other) const;
+ inline QRectF united(const QRectF &other) const Q_REQUIRED_RESULT;
+ inline QRectF intersected(const QRectF &other) const Q_REQUIRED_RESULT;
bool intersects(const QRectF &r) const;
Q_DECL_CONSTEXPR inline QRectF marginsAdded(const QMarginsF &margins) const;
@@ -590,15 +590,15 @@ public:
inline QRectF &operator-=(const QMarginsF &margins);
#if QT_DEPRECATED_SINCE(5, 0)
- QT_DEPRECATED QRectF unite(const QRectF &r) const { return united(r); }
- QT_DEPRECATED QRectF intersect(const QRectF &r) const { return intersected(r); }
+ QT_DEPRECATED QRectF unite(const QRectF &r) const Q_REQUIRED_RESULT { return united(r); }
+ QT_DEPRECATED QRectF intersect(const QRectF &r) const Q_REQUIRED_RESULT { return intersected(r); }
#endif
friend Q_DECL_CONSTEXPR inline bool operator==(const QRectF &, const QRectF &);
friend Q_DECL_CONSTEXPR inline bool operator!=(const QRectF &, const QRectF &);
- Q_DECL_CONSTEXPR inline QRect toRect() const;
- QRect toAlignedRect() const;
+ Q_DECL_CONSTEXPR inline QRect toRect() const Q_REQUIRED_RESULT;
+ QRect toAlignedRect() const Q_REQUIRED_RESULT;
private:
qreal xp;
diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp
index e1cf82bb8c..88ce4caea3 100644
--- a/src/corelib/tools/qregularexpression.cpp
+++ b/src/corelib/tools/qregularexpression.cpp
@@ -699,6 +699,23 @@ QT_BEGIN_NAMESPACE
\c{\w} to match any character with either the Unicode L (letter) or N
(digit) property, plus underscore, and so on. This option corresponds
to the \c{/u} modifier in Perl regular expressions.
+
+ \value OptimizeOnFirstUsageOption
+ The regular expression will be optimized (and possibly
+ JIT-compiled) on its first usage, instead of after a certain (undefined)
+ number of usages. See also \l{QRegularExpression::}{optimize()}.
+ This enum value has been introduced in Qt 5.4.
+
+ \value DontAutomaticallyOptimizeOption
+ Regular expressions are automatically optimized after a
+ certain number of usages; setting this option prevents such
+ optimizations, therefore avoiding possible unpredictable spikes in
+ CPU and memory usage. If both this option and the
+ \c{OptimizeOnFirstUsageOption} option are set, then this option takes
+ precedence. Note: this option will still let the regular expression
+ to be optimized by manually calling
+ \l{QRegularExpression::}{optimize()}. This enum value has been
+ introduced in Qt 5.4.
*/
/*!
@@ -746,6 +763,13 @@ QT_BEGIN_NAMESPACE
The match is constrained to start exactly at the offset passed to
match() in order to be successful, even if the pattern string does not
contain any metacharacter that anchors the match at that point.
+
+ \value DontCheckSubjectStringMatchOption
+ The subject string is not checked for UTF-16 validity before
+ attempting a match. Use this option with extreme caution, as
+ attempting to match an invalid string may crash the program and/or
+ constitute a security issue. This enum value has been introduced in
+ Qt 5.4.
*/
// after how many usages we optimize the regexp
@@ -802,13 +826,24 @@ struct QRegularExpressionPrivate : QSharedData
void cleanCompiledPattern();
void compilePattern();
void getPatternInfo();
- void optimizePattern();
+
+ enum OptimizePatternOption {
+ LazyOptimizeOption,
+ ImmediateOptimizeOption
+ };
+
+ void optimizePattern(OptimizePatternOption option);
+
+ enum CheckSubjectStringOption {
+ CheckSubjectString,
+ DontCheckSubjectString
+ };
QRegularExpressionMatchPrivate *doMatch(const QString &subject,
int offset,
QRegularExpression::MatchType matchType,
QRegularExpression::MatchOptions matchOptions,
- bool checkSubjectString = true,
+ CheckSubjectStringOption checkSubjectStringOption = CheckSubjectString,
const QRegularExpressionMatchPrivate *previous = 0) const;
int captureIndexForName(const QString &name) const;
@@ -1096,7 +1131,10 @@ static bool isJitEnabled()
setting the studyData member variable to the result of the study. It gets
called by doMatch() every time a match is performed. As of now, the
optimizations on the pattern are performed after a certain number of usages
- (i.e. the qt_qregularexpression_optimize_after_use_count constant).
+ (i.e. the qt_qregularexpression_optimize_after_use_count constant) unless
+ the DontAutomaticallyOptimizeOption option is set on the QRegularExpression
+ object, or anyhow by calling optimize() (which will pass
+ ImmediateOptimizeOption).
Notice that although the method is protected by a mutex, one thread may
invoke this function and return immediately (i.e. not study the pattern,
@@ -1107,20 +1145,23 @@ static bool isJitEnabled()
(localStudyData) before using storeRelease on studyData. In doMatch there's
the corresponding loadAcquire.
*/
-void QRegularExpressionPrivate::optimizePattern()
+void QRegularExpressionPrivate::optimizePattern(OptimizePatternOption option)
{
Q_ASSERT(compiledPattern);
QMutexLocker lock(&mutex);
- if (studyData.load() || (++usedCount != qt_qregularexpression_optimize_after_use_count))
+ if (studyData.load()) // already optimized
+ return;
+
+ if ((option == LazyOptimizeOption) && (++usedCount != qt_qregularexpression_optimize_after_use_count))
return;
static const bool enableJit = isJitEnabled();
int studyOptions = 0;
if (enableJit)
- studyOptions |= PCRE_STUDY_JIT_COMPILE;
+ studyOptions |= (PCRE_STUDY_JIT_COMPILE | PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE | PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE);
const char *err;
pcre16_extra * const localStudyData = pcre16_study(compiledPattern, studyOptions, &err);
@@ -1187,7 +1228,9 @@ static int pcre16SafeExec(const pcre16 *code, const pcre16_extra *extra,
options \a matchOptions and returns the QRegularExpressionMatchPrivate of
the result. It also advances a match if a previous result is given as \a
previous. The \a subject string goes a Unicode validity check if
- \a checkSubjectString is true (PCRE doesn't like illegal UTF-16 sequences).
+ \a checkSubjectString is CheckSubjectString and the match options don't
+ include DontCheckSubjectStringMatchOption (PCRE doesn't like illegal
+ UTF-16 sequences).
Advancing a match is a tricky algorithm. If the previous match matched a
non-empty string, we just do an ordinary match at the offset position.
@@ -1204,7 +1247,7 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
int offset,
QRegularExpression::MatchType matchType,
QRegularExpression::MatchOptions matchOptions,
- bool checkSubjectString,
+ CheckSubjectStringOption checkSubjectStringOption,
const QRegularExpressionMatchPrivate *previous) const
{
if (offset < 0)
@@ -1233,8 +1276,15 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
matchType, matchOptions,
capturingCount + 1);
- // this is mutex protected
- const_cast<QRegularExpressionPrivate *>(this)->optimizePattern();
+ if (!(patternOptions & QRegularExpression::DontAutomaticallyOptimizeOption)) {
+ const OptimizePatternOption optimizePatternOption =
+ (patternOptions & QRegularExpression::OptimizeOnFirstUsageOption)
+ ? ImmediateOptimizeOption
+ : LazyOptimizeOption;
+
+ // this is mutex protected
+ const_cast<QRegularExpressionPrivate *>(this)->optimizePattern(optimizePatternOption);
+ }
// work with a local copy of the study data, as we are running pcre_exec
// potentially more than once, and we don't want to run call it
@@ -1248,8 +1298,10 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
else if (matchType == QRegularExpression::PartialPreferFirstMatch)
pcreOptions |= PCRE_PARTIAL_HARD;
- if (!checkSubjectString)
+ if (checkSubjectStringOption == DontCheckSubjectString
+ || matchOptions & QRegularExpression::DontCheckSubjectStringMatchOption) {
pcreOptions |= PCRE_NO_UTF16_CHECK;
+ }
bool previousMatchWasEmpty = false;
if (previous && previous->hasMatch &&
@@ -1360,7 +1412,7 @@ QRegularExpressionMatch QRegularExpressionMatchPrivate::nextMatch() const
Q_ASSERT(isValid);
Q_ASSERT(hasMatch || hasPartialMatch);
- // Note the "false" passed for the check of the subject string:
+ // Note the DontCheckSubjectString passed for the check of the subject string:
// if we're advancing a match on the same subject,
// then that subject was already checked at least once (when this object
// was created, or when the object that created this one was created, etc.)
@@ -1368,7 +1420,7 @@ QRegularExpressionMatch QRegularExpressionMatchPrivate::nextMatch() const
capturedOffsets.at(1),
matchType,
matchOptions,
- false,
+ QRegularExpressionPrivate::DontCheckSubjectString,
this);
return QRegularExpressionMatch(*nextPrivate);
}
@@ -1667,6 +1719,27 @@ QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QString &s
}
/*!
+ \since 5.4
+
+ Forces an immediate optimization of the pattern, including
+ JIT-compiling it (if the JIT compiler is enabled).
+
+ Patterns are normally optimized only after a certain number of usages.
+ If you can predict that this QRegularExpression object is going to be
+ used for several matches, it may be convenient to optimize it in
+ advance by calling this function.
+
+ \sa QRegularExpression::OptimizeOnFirstUsageOption
+*/
+void QRegularExpression::optimize() const
+{
+ if (!isValid()) // will compile the pattern
+ return;
+
+ d->optimizePattern(QRegularExpressionPrivate::ImmediateOptimizeOption);
+}
+
+/*!
Returns \c true if the regular expression is equal to \a re, or false
otherwise. Two QRegularExpression objects are equal if they have
the same pattern string and the same pattern options.
@@ -2327,6 +2400,10 @@ QDebug operator<<(QDebug debug, QRegularExpression::PatternOptions patternOption
flags.append("DontCaptureOption|");
if (patternOptions & QRegularExpression::UseUnicodePropertiesOption)
flags.append("UseUnicodePropertiesOption|");
+ if (patternOptions & QRegularExpression::OptimizeOnFirstUsageOption)
+ flags.append("OptimizeOnFirstUsageOption|");
+ if (patternOptions & QRegularExpression::DontAutomaticallyOptimizeOption)
+ flags.append("DontAutomaticallyOptimizeOption|");
flags.chop(1);
}
@@ -2490,7 +2567,16 @@ static const char *pcreCompileErrorCodes[] =
QT_TRANSLATE_NOOP("QRegularExpression", "disallowed Unicode code point (>= 0xd800 && <= 0xdfff)"),
QT_TRANSLATE_NOOP("QRegularExpression", "invalid UTF-16 string"),
QT_TRANSLATE_NOOP("QRegularExpression", "name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN)"),
- QT_TRANSLATE_NOOP("QRegularExpression", "character value in \\u.... sequence is too large")
+ QT_TRANSLATE_NOOP("QRegularExpression", "character value in \\u.... sequence is too large"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "invalid UTF-32 string"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "setting UTF is disabled by the application"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "non-hex character in \\x{} (closing brace missing?)"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "non-octal character in \\o{} (closing brace missing?)"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "missing opening brace after \\o"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "parentheses are too deeply nested"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "invalid range in character class"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "group name must start with a non-digit"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "parentheses are too deeply nested (stack check)")
};
#endif // #if 0
diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h
index 5059ea6431..ce91eace5f 100644
--- a/src/corelib/tools/qregularexpression.h
+++ b/src/corelib/tools/qregularexpression.h
@@ -69,7 +69,9 @@ public:
ExtendedPatternSyntaxOption = 0x0008,
InvertedGreedinessOption = 0x0010,
DontCaptureOption = 0x0020,
- UseUnicodePropertiesOption = 0x0040
+ UseUnicodePropertiesOption = 0x0040,
+ OptimizeOnFirstUsageOption = 0x0080,
+ DontAutomaticallyOptimizeOption = 0x0100
};
Q_DECLARE_FLAGS(PatternOptions, PatternOption)
@@ -108,7 +110,8 @@ public:
enum MatchOption {
NoMatchOption = 0x0000,
- AnchoredMatchOption = 0x0001
+ AnchoredMatchOption = 0x0001,
+ DontCheckSubjectStringMatchOption = 0x0002
};
Q_DECLARE_FLAGS(MatchOptions, MatchOption)
@@ -122,6 +125,8 @@ public:
MatchType matchType = NormalMatch,
MatchOptions matchOptions = NoMatchOption) const;
+ void optimize() const;
+
static QString escape(const QString &str);
bool operator==(const QRegularExpression &re) const;
diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h
index 5d25b0add1..5aa1f165be 100644
--- a/src/corelib/tools/qringbuffer_p.h
+++ b/src/corelib/tools/qringbuffer_p.h
@@ -61,9 +61,9 @@ QT_BEGIN_NAMESPACE
class QRingBuffer
{
public:
- explicit inline QRingBuffer(int growth = 4096) : basicBlockSize(growth) {
- buffers << QByteArray();
- clear();
+ explicit inline QRingBuffer(int growth = 4096) :
+ head(0), tail(0), tailBuffer(0), basicBlockSize(growth), bufferSize(0) {
+ buffers.append(QByteArray());
}
inline int nextDataBlockSize() const {
@@ -78,115 +78,65 @@ public:
// the out-variable length will contain the amount of bytes readable
// from there, e.g. the amount still the same QByteArray
inline const char *readPointerAtPosition(qint64 pos, qint64 &length) const {
- if (buffers.isEmpty()) {
- length = 0;
- return 0;
- }
-
- if (pos >= bufferSize) {
- length = 0;
- return 0;
- }
-
- // special case: it is in the first buffer
- int nextDataBlockSizeValue = nextDataBlockSize();
- if (pos < nextDataBlockSizeValue) {
- length = nextDataBlockSizeValue - pos;
- return buffers.at(0).constData() + head + pos;
- }
-
- // special case: we only had one buffer and tried to read over it
- if (buffers.length() == 1) {
- length = 0;
- return 0;
- }
-
- // skip the first
- pos -= nextDataBlockSizeValue;
-
- // normal case: it is somewhere in the second to the-one-before-the-tailBuffer
- for (int i = 1; i < tailBuffer; i++) {
- if (pos >= buffers[i].size()) {
- pos -= buffers[i].size();
- continue;
+ if (pos >= 0) {
+ pos += head;
+ for (int i = 0; i < buffers.size(); ++i) {
+ length = (i == tailBuffer ? tail : buffers[i].size());
+ if (length > pos) {
+ length -= pos;
+ return buffers[i].constData() + pos;
+ }
+ pos -= length;
}
-
- length = buffers[i].length() - pos;
- return buffers[i].constData() + pos;
}
- // it is in the tail buffer
- length = tail - pos;
- return buffers[tailBuffer].constData() + pos;
+ length = 0;
+ return 0;
}
inline void free(int bytes) {
- bufferSize -= bytes;
- if (bufferSize < 0)
- bufferSize = 0;
-
- for (;;) {
- int nextBlockSize = nextDataBlockSize();
- if (bytes < nextBlockSize) {
- head += bytes;
- if (head == tail && tailBuffer == 0)
- head = tail = 0;
- break;
- }
-
- bytes -= nextBlockSize;
- if (buffers.count() == 1) {
- if (buffers.at(0).size() != basicBlockSize)
- buffers[0].resize(basicBlockSize);
- head = tail = 0;
- tailBuffer = 0;
- break;
+ while (bytes > 0) {
+ int blockSize = buffers.first().size() - head;
+
+ if (tailBuffer == 0 || blockSize > bytes) {
+ bufferSize -= bytes;
+ if (bufferSize <= 0)
+ clear(); // try to minify/squeeze us
+ else
+ head += bytes;
+ return;
}
- buffers.removeAt(0);
+ bufferSize -= blockSize;
+ bytes -= blockSize;
+ buffers.removeFirst();
--tailBuffer;
head = 0;
}
-
- if (isEmpty())
- clear(); // try to minify/squeeze us
}
inline char *reserve(int bytes) {
- // if this is a fresh empty QRingBuffer
- if (bufferSize == 0) {
- buffers[0].resize(qMax(basicBlockSize, bytes));
- bufferSize += bytes;
- tail = bytes;
- return buffers[tailBuffer].data();
- }
-
- bufferSize += bytes;
+ if (bytes <= 0)
+ return 0;
- // if there is already enough space, simply return.
- if (tail + bytes <= buffers.at(tailBuffer).size()) {
- char *writePtr = buffers[tailBuffer].data() + tail;
- tail += bytes;
- return writePtr;
- }
+ // if need buffer reallocation
+ if (tail + bytes > buffers.last().size()) {
+ if (tail >= basicBlockSize) {
+ // shrink this buffer to its current size
+ buffers.last().resize(tail);
- // if our buffer isn't half full yet, simply resize it.
- if (tail < buffers.at(tailBuffer).size() / 2) {
- buffers[tailBuffer].resize(tail + bytes);
- char *writePtr = buffers[tailBuffer].data() + tail;
- tail += bytes;
- return writePtr;
+ // create a new QByteArray
+ buffers.append(QByteArray());
+ ++tailBuffer;
+ tail = 0;
+ }
+ buffers.last().resize(qMax(basicBlockSize, tail + bytes));
}
- // shrink this buffer to its current size
- buffers[tailBuffer].resize(tail);
-
- // create a new QByteArray with the right size
- buffers << QByteArray();
- ++tailBuffer;
- buffers[tailBuffer].resize(qMax(basicBlockSize, bytes));
- tail = bytes;
- return buffers[tailBuffer].data();
+ char *writePtr = buffers.last().data() + tail;
+ bufferSize += bytes;
+ tail += bytes;
+ return writePtr;
}
inline void truncate(int pos) {
@@ -195,33 +145,22 @@ public:
}
inline void chop(int bytes) {
- bufferSize -= bytes;
- if (bufferSize < 0)
- bufferSize = 0;
-
- for (;;) {
- // special case: head and tail are in the same buffer
- if (tailBuffer == 0) {
- tail -= bytes;
- if (tail <= head)
- tail = head = 0;
- return;
- }
-
- if (bytes <= tail) {
- tail -= bytes;
+ while (bytes > 0) {
+ if (tailBuffer == 0 || tail > bytes) {
+ bufferSize -= bytes;
+ if (bufferSize <= 0)
+ clear(); // try to minify/squeeze us
+ else
+ tail -= bytes;
return;
}
+ bufferSize -= tail;
bytes -= tail;
- buffers.removeAt(tailBuffer);
-
+ buffers.removeLast();
--tailBuffer;
- tail = buffers.at(tailBuffer).size();
+ tail = buffers.last().size();
}
-
- if (isEmpty())
- clear(); // try to minify/squeeze us
}
inline bool isEmpty() const {
@@ -245,11 +184,11 @@ public:
--head;
if (head < 0) {
buffers.prepend(QByteArray());
- buffers[0].resize(basicBlockSize);
+ buffers.first().resize(basicBlockSize);
head = basicBlockSize - 1;
++tailBuffer;
}
- buffers[0][head] = c;
+ buffers.first()[head] = c;
++bufferSize;
}
@@ -259,8 +198,7 @@ public:
inline void clear() {
buffers.erase(buffers.begin() + 1, buffers.end());
- buffers[0].resize(0);
- buffers[0].squeeze();
+ buffers.first().clear();
head = tail = 0;
tailBuffer = 0;
@@ -269,47 +207,34 @@ public:
inline int indexOf(char c) const {
int index = 0;
+ int j = head;
for (int i = 0; i < buffers.size(); ++i) {
- int start = 0;
- int end = buffers.at(i).size();
-
- if (i == 0)
- start = head;
- if (i == tailBuffer)
- end = tail;
- const char *ptr = buffers.at(i).data() + start;
- for (int j = start; j < end; ++j) {
+ const char *ptr = buffers[i].constData() + j;
+ j = index + (i == tailBuffer ? tail : buffers[i].size()) - j;
+
+ while (index < j) {
if (*ptr++ == c)
return index;
++index;
}
+ j = 0;
}
return -1;
}
inline int indexOf(char c, int maxLength) const {
int index = 0;
- int remain = qMin(size(), maxLength);
- for (int i = 0; remain && i < buffers.size(); ++i) {
- int start = 0;
- int end = buffers.at(i).size();
-
- if (i == 0)
- start = head;
- if (i == tailBuffer)
- end = tail;
- if (remain < end - start) {
- end = start + remain;
- remain = 0;
- } else {
- remain -= end - start;
- }
- const char *ptr = buffers.at(i).data() + start;
- for (int j = start; j < end; ++j) {
+ int j = head;
+ for (int i = 0; index < maxLength && i < buffers.size(); ++i) {
+ const char *ptr = buffers[i].constData() + j;
+ j = qMin(index + (i == tailBuffer ? tail : buffers[i].size()) - j, maxLength);
+
+ while (index < j) {
if (*ptr++ == c)
return index;
++index;
}
+ j = 0;
}
return -1;
}
@@ -318,95 +243,47 @@ public:
int bytesToRead = qMin(size(), maxLength);
int readSoFar = 0;
while (readSoFar < bytesToRead) {
- const char *ptr = readPointer();
int bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar, nextDataBlockSize());
if (data)
- memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock);
+ memcpy(data + readSoFar, readPointer(), bytesToReadFromThisBlock);
readSoFar += bytesToReadFromThisBlock;
free(bytesToReadFromThisBlock);
}
return readSoFar;
}
- inline QByteArray read(int maxLength) {
- QByteArray tmp;
- tmp.resize(qMin(maxLength, size()));
- read(tmp.data(), tmp.size());
- return tmp;
- }
-
- inline QByteArray readAll() {
- return read(size());
- }
-
// read an unspecified amount (will read the first buffer)
inline QByteArray read() {
if (bufferSize == 0)
return QByteArray();
- // multiple buffers, just take the first one
- if (head == 0 && tailBuffer != 0) {
- QByteArray qba = buffers.takeFirst();
- --tailBuffer;
- bufferSize -= qba.length();
- return qba;
- }
+ QByteArray qba(buffers.takeFirst());
- // one buffer with good value for head. Just take it.
- if (head == 0 && tailBuffer == 0) {
- QByteArray qba = buffers.takeFirst();
- qba.resize(tail);
- buffers << QByteArray();
- bufferSize = 0;
- tail = 0;
- return qba;
- }
-
- // Bad case: We have to memcpy.
- // We can avoid by initializing the QRingBuffer with basicBlockSize of 0
- // and only using this read() function.
- QByteArray qba(readPointer(), nextDataBlockSize());
- buffers.removeFirst();
- head = 0;
+ qba.reserve(0); // avoid that resizing needlessly reallocates
if (tailBuffer == 0) {
- buffers << QByteArray();
+ qba.resize(tail);
tail = 0;
+ buffers.append(QByteArray());
} else {
--tailBuffer;
}
- bufferSize -= qba.length();
+ qba.remove(0, head); // does nothing if head is 0
+ head = 0;
+ bufferSize -= qba.size();
return qba;
}
// append a new buffer to the end
inline void append(const QByteArray &qba) {
- buffers[tailBuffer].resize(tail);
- buffers << qba;
- ++tailBuffer;
- tail = qba.length();
- bufferSize += qba.length();
- }
-
- inline QByteArray peek(int maxLength) const {
- int bytesToRead = qMin(size(), maxLength);
- if(maxLength <= 0)
- return QByteArray();
- QByteArray ret;
- ret.resize(bytesToRead);
- int readSoFar = 0;
- for (int i = 0; readSoFar < bytesToRead && i < buffers.size(); ++i) {
- int start = 0;
- int end = buffers.at(i).size();
- if (i == 0)
- start = head;
- if (i == tailBuffer)
- end = tail;
- const int len = qMin(ret.size()-readSoFar, end-start);
- memcpy(ret.data()+readSoFar, buffers.at(i).constData()+start, len);
- readSoFar += len;
+ if (tail == 0) {
+ buffers.last() = qba;
+ } else {
+ buffers.last().resize(tail);
+ buffers.append(qba);
+ ++tailBuffer;
}
- Q_ASSERT(readSoFar == ret.size());
- return ret;
+ tail = qba.size();
+ bufferSize += tail;
}
inline int skip(int length) {
@@ -414,35 +291,26 @@ public:
}
inline int readLine(char *data, int maxLength) {
- int index = indexOf('\n');
- if (index == -1)
- return read(data, maxLength);
- if (maxLength <= 0)
+ if (!data || --maxLength <= 0)
return -1;
- int readSoFar = 0;
- while (readSoFar < index + 1 && readSoFar < maxLength - 1) {
- int bytesToRead = qMin((index + 1) - readSoFar, nextDataBlockSize());
- bytesToRead = qMin(bytesToRead, (maxLength - 1) - readSoFar);
- memcpy(data + readSoFar, readPointer(), bytesToRead);
- readSoFar += bytesToRead;
- free(bytesToRead);
- }
+ int i = indexOf('\n', maxLength);
+ i = read(data, i >= 0 ? (i + 1) : maxLength);
// Terminate it.
- data[readSoFar] = '\0';
- return readSoFar;
+ data[i] = '\0';
+ return i;
}
inline bool canReadLine() const {
- return indexOf('\n') != -1;
+ return indexOf('\n') >= 0;
}
private:
QList<QByteArray> buffers;
int head, tail;
int tailBuffer; // always buffers.size() - 1
- int basicBlockSize;
+ const int basicBlockSize;
int bufferSize;
};
diff --git a/src/corelib/tools/qscopedvaluerollback.cpp b/src/corelib/tools/qscopedvaluerollback.cpp
index 2d61d2114e..bd3e03c464 100644
--- a/src/corelib/tools/qscopedvaluerollback.cpp
+++ b/src/corelib/tools/qscopedvaluerollback.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -70,6 +70,15 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn QScopedValueRollback::QScopedValueRollback(T &var, T value)
+
+ Assigns \a value to \ var and stores the previous value of \a var
+ internally, for revert on destruction.
+
+ \since 5.4
+*/
+
+/*!
\fn QScopedValueRollback::~QScopedValueRollback()
Assigns the previous value to the managed variable.
diff --git a/src/corelib/tools/qscopedvaluerollback.h b/src/corelib/tools/qscopedvaluerollback.h
index dfaf1984be..2a5bd8c223 100644
--- a/src/corelib/tools/qscopedvaluerollback.h
+++ b/src/corelib/tools/qscopedvaluerollback.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -56,6 +56,13 @@ public:
oldValue = varRef;
}
+ explicit QScopedValueRollback(T &var, T value) :
+ varRef(var)
+ {
+ oldValue = varRef;
+ varRef = value;
+ }
+
~QScopedValueRollback()
{
varRef = oldValue;
diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h
index 0cc704b6cf..9682c97fec 100644
--- a/src/corelib/tools/qset.h
+++ b/src/corelib/tools/qset.h
@@ -60,7 +60,7 @@ public:
#ifdef Q_COMPILER_INITIALIZER_LISTS
inline QSet(std::initializer_list<T> list)
{
- reserve(list.size());
+ reserve(int(list.size()));
for (typename std::initializer_list<T>::const_iterator it = list.begin(); it != list.end(); ++it)
insert(*it);
}
@@ -356,12 +356,9 @@ class QMutableSetIterator
public:
inline QMutableSetIterator(QSet<T> &container)
: c(&container)
- { c->setSharable(false); i = c->begin(); n = c->end(); }
- inline ~QMutableSetIterator()
- { c->setSharable(true); }
+ { i = c->begin(); n = c->end(); }
inline QMutableSetIterator &operator=(QSet<T> &container)
- { c->setSharable(true); c = &container; c->setSharable(false);
- i = c->begin(); n = c->end(); return *this; }
+ { c = &container; i = c->begin(); n = c->end(); return *this; }
inline void toFront() { i = c->begin(); n = c->end(); }
inline void toBack() { i = c->end(); n = i; }
inline bool hasNext() const { return c->constEnd() != i; }
diff --git a/src/corelib/tools/qshareddata.cpp b/src/corelib/tools/qshareddata.cpp
index 941e58ee7c..b5eed0f504 100644
--- a/src/corelib/tools/qshareddata.cpp
+++ b/src/corelib/tools/qshareddata.cpp
@@ -538,10 +538,34 @@ QT_BEGIN_NAMESPACE
/*! \fn QExplicitlySharedDataPointer::QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X>& other)
This copy constructor is different in that it allows \a other to be
a different type of explicitly shared data pointer but one that has
- a compatible shared data object. It performs a static cast of the
- \e{d pointer} in \a other and sets the \e {d pointer} of \e this to
- the converted \e{d pointer}. It increments the reference count of
- the shared data object.
+ a compatible shared data object.
+
+ By default, the \e{d pointer} of \a other (of type \c{X *}) gets
+ implicitly converted to the type \c{T *}; the result of this
+ conversion is set as the \e{d pointer} of \e{this}, and the
+ reference count of the shared data object is incremented.
+
+ However, if the macro
+ \c{QT_ENABLE_QEXPLICITLYSHAREDDATAPOINTER_STATICCAST} is defined
+ before including the \c{QExplicitlySharedDataPointer} header, then
+ the \e{d pointer} of \a other undergoes a \c{static_cast} to the
+ type \c{T *}. The result of the cast is then set as the
+ \e{d pointer} of \e{this}, and the reference count of the shared data
+ object is incremented.
+
+ \warning relying on such \c{static_cast} is potentially dangerous,
+ because it allows code like this to compile:
+
+ \code
+ QExplicitlySharedDataPointer<Base> base(new Base);
+ QExplicitlySharedDataPointer<Derived> derived(base); // !!! DANGER !!!
+ \endcode
+
+ Starting from Qt 5.4 the cast is disabled by default. It is
+ possible to enable it back by defining the
+ \c{QT_ENABLE_QEXPLICITLYSHAREDDATAPOINTER_STATICCAST} macro, and
+ therefore to allow old code (that relied on this feature) to
+ compile without modifications.
*/
/*! \fn QExplicitlySharedDataPointer<T>& QExplicitlySharedDataPointer::operator=(const QExplicitlySharedDataPointer<T>& other)
diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h
index 00bf4cba2a..d85184e995 100644
--- a/src/corelib/tools/qshareddata.h
+++ b/src/corelib/tools/qshareddata.h
@@ -44,6 +44,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qatomic.h>
+#include <QtCore/qhash.h>
QT_BEGIN_NAMESPACE
@@ -166,7 +167,12 @@ public:
inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); }
template<class X>
- inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o) : d(static_cast<T *>(o.data()))
+ inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o)
+#ifdef QT_ENABLE_QEXPLICITLYSHAREDDATAPOINTER_STATICCAST
+ : d(static_cast<T *>(o.data()))
+#else
+ : d(o.data())
+#endif
{
if(d)
d->ref.ref();
@@ -274,6 +280,17 @@ namespace std {
}
QT_BEGIN_NAMESPACE
+template <class T>
+Q_INLINE_TEMPLATE uint qHash(const QSharedDataPointer<T> &ptr, uint seed = 0)
+{
+ return qHash(ptr.data(), seed);
+}
+template <class T>
+Q_INLINE_TEMPLATE uint qHash(const QExplicitlySharedDataPointer<T> &ptr, uint seed = 0)
+{
+ return qHash(ptr.data(), seed);
+}
+
template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedDataPointer<T>, Q_MOVABLE_TYPE);
template<typename T> Q_DECLARE_TYPEINFO_BODY(QExplicitlySharedDataPointer<T>, Q_MOVABLE_TYPE);
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp
index a610fc46e5..e0cd54022e 100644
--- a/src/corelib/tools/qsharedpointer.cpp
+++ b/src/corelib/tools/qsharedpointer.cpp
@@ -372,6 +372,64 @@
*/
/*!
+ \class QEnableSharedFromThis
+ \inmodule QtCore
+ \brief A base class that allows obtaining a QSharedPointer for an object already managed by a shared pointer
+ \since 5.4
+
+ You can inherit this class when you need to create a QSharedPointer
+ from any instance of a class; for instance, from within the
+ object itself. The key point is that the technique of
+ just returning QSharedPointer<T>(this) can not be used, because
+ this winds up creating multiple distinct QSharedPointer objects
+ with separate reference counts. For this reason you must never
+ create more than one QSharedPointer from the same raw pointer.
+
+ QEnableSharedFromThis defines two member functions called
+ sharedFromThis() that return a QSharedPointer<T> and
+ QSharedPointer<const T>, depending on constness, to \c this:
+
+ \code
+ class Y: public QEnableSharedFromThis<Y>
+ {
+ public:
+ QSharedPointer<Y> f()
+ {
+ return sharedFromThis();
+ }
+ };
+
+ int main()
+ {
+ QSharedPointer<Y> p(new Y());
+ QSharedPointer<Y> y = p->f();
+ Q_ASSERT(p == y); // p and q must share ownership
+ }
+ \endcode
+
+ It is also possible to get a shared pointer from an object outside of
+ the class itself. This is especially useful in code that provides an
+ interface to scripts, where it is currently not possible to use shared
+ pointers. For example:
+
+ \code
+ class ScriptInterface : public QObject
+ {
+ Q_OBJECT
+
+ // ...
+
+ public slots:
+ void slotCalledByScript(Y *managedBySharedPointer)
+ {
+ QSharedPointer<Y> yPtr = managedBySharedPointer->sharedFromThis();
+ // Some other code unrelated to scripts that expects a QSharedPointer<Y> ...
+ }
+ };
+ \endcode
+*/
+
+/*!
\fn QSharedPointer::QSharedPointer()
Creates a QSharedPointer that points to null (0).
@@ -630,9 +688,15 @@
This function will attempt to call a constructor for type \tt T that can
accept all the arguments passed. Arguments will be perfectly-forwarded.
- \note This function is only available with a C++11 compiler that supports
- perfect forwarding of an arbitrary number of arguments. If the compiler
- does not support the necessary C++11 features, you must use the overload
+ \note This function is only fully available with a C++11 compiler that
+ supports perfect forwarding of an arbitrary number of arguments.
+
+ If the compiler does not support the necessary C++11 features,
+ then a restricted version is available since Qt 5.4: you may pass
+ one (but just one) argument, and it will always be passed by const
+ reference.
+
+ If you target Qt before version 5.4, you must use the overload
that calls the default constructor.
*/
@@ -771,6 +835,14 @@
*/
/*!
+ \fn void QWeakPointer::swap(QWeakPointer<T> &other)
+ \since 5.4
+
+ Swaps this weak pointer instance with \a other. This function is
+ very fast and never fails.
+*/
+
+/*!
\fn bool QWeakPointer::isNull() const
Returns \c true if this object is holding a reference to a null
@@ -894,6 +966,15 @@
*/
/*!
+ \fn QSharedPointer<T> QWeakPointer::lock() const
+ \since 5.4
+
+ Same as toStrongRef().
+
+ This function is provided for API compatibility with std::weak_ptr.
+*/
+
+/*!
\fn void QWeakPointer::clear()
Clears this QWeakPointer object, dropping the reference that it
@@ -901,6 +982,23 @@
*/
/*!
+ \fn QSharedPointer<T> QEnableSharedFromThis::sharedFromThis()
+ \since 5.4
+
+ If \c this (that is, the subclass instance invoking this method) is being
+ managed by a QSharedPointer, returns a shared pointer instance pointing to
+ \c this; otherwise returns a QSharedPointer holding a null pointer.
+*/
+
+/*!
+ \fn QSharedPointer<const T> QEnableSharedFromThis::sharedFromThis() const
+ \overload
+ \since 5.4
+
+ Const overload of sharedFromThis().
+*/
+
+/*!
\fn bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
\relates QSharedPointer
diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h
index 34b4bfbb12..431868ee08 100644
--- a/src/corelib/tools/qsharedpointer.h
+++ b/src/corelib/tools/qsharedpointer.h
@@ -122,10 +122,21 @@ public:
QWeakPointer(const QObject *other);
QWeakPointer<T> operator=(const QObject *other);
+ void swap(QWeakPointer<T> &other);
+
T *data() const;
void clear();
QSharedPointer<T> toStrongRef() const;
+ QSharedPointer<T> lock() const;
+};
+
+template <class T>
+class QEnableSharedFromThis
+{
+public:
+ QSharedPointer<T> sharedFromThis();
+ QSharedPointer<const T> sharedFromThis() const;
};
template<class T, class X> bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2);
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index 1423449a69..fe79aa1db1 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -91,6 +91,7 @@ template<typename T> inline void qt_sharedpointer_cast_check(T *) { }
//
template <class T> class QWeakPointer;
template <class T> class QSharedPointer;
+template <class T> class QEnableSharedFromThis;
class QVariant;
@@ -318,16 +319,22 @@ public:
inline QSharedPointer(T *ptr, Deleter deleter) : value(ptr) // throws
{ internalConstruct(ptr, deleter); }
- inline QSharedPointer(const QSharedPointer<T> &other) : value(other.value), d(other.d)
+ inline QSharedPointer(const QSharedPointer &other) : value(other.value), d(other.d)
{ if (d) ref(); }
- inline QSharedPointer<T> &operator=(const QSharedPointer<T> &other)
+ inline QSharedPointer &operator=(const QSharedPointer &other)
{
QSharedPointer copy(other);
swap(copy);
return *this;
}
#ifdef Q_COMPILER_RVALUE_REFS
- inline QSharedPointer<T> &operator=(QSharedPointer<T> &&other)
+ inline QSharedPointer(QSharedPointer &&other)
+ : value(other.value), d(other.d)
+ {
+ other.d = 0;
+ other.value = 0;
+ }
+ inline QSharedPointer &operator=(QSharedPointer &&other)
{
swap(other);
return *this;
@@ -339,7 +346,7 @@ public:
{ if (d) ref(); }
template <class X>
- inline QSharedPointer<T> &operator=(const QSharedPointer<X> &other)
+ inline QSharedPointer &operator=(const QSharedPointer<X> &other)
{
QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid
internalCopy(other);
@@ -355,7 +362,7 @@ public:
{ internalSet(other.d, other.value); return *this; }
inline void swap(QSharedPointer &other)
- { QSharedPointer<T>::internalSwap(other); }
+ { this->internalSwap(other); }
inline void reset() { clear(); }
inline void reset(T *t)
@@ -396,7 +403,7 @@ public:
#if defined(Q_COMPILER_RVALUE_REFS) && defined(Q_COMPILER_VARIADIC_TEMPLATES)
template <typename... Args>
- static QSharedPointer<T> create(Args && ...arguments)
+ static QSharedPointer create(Args && ...arguments)
{
typedef QtSharedPointer::ExternalRefCountWithContiguousData<T> Private;
# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
@@ -404,7 +411,7 @@ public:
# else
typename Private::DestroyerFn destroy = &Private::deleter;
# endif
- QSharedPointer<T> result(Qt::Uninitialized);
+ QSharedPointer result(Qt::Uninitialized);
result.d = Private::create(&result.value, destroy);
// now initialize the data
@@ -416,7 +423,7 @@ public:
return result;
}
#else
- static inline QSharedPointer<T> create()
+ static inline QSharedPointer create()
{
typedef QtSharedPointer::ExternalRefCountWithContiguousData<T> Private;
# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
@@ -424,7 +431,7 @@ public:
# else
typename Private::DestroyerFn destroy = &Private::deleter;
# endif
- QSharedPointer<T> result(Qt::Uninitialized);
+ QSharedPointer result(Qt::Uninitialized);
result.d = Private::create(&result.value, destroy);
// now initialize the data
@@ -435,6 +442,27 @@ public:
result.d->setQObjectShared(result.value, true);
return result;
}
+
+ template <typename Arg>
+ static inline QSharedPointer create(const Arg &arg)
+ {
+ typedef QtSharedPointer::ExternalRefCountWithContiguousData<T> Private;
+# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
+ typename Private::DestroyerFn destroy = &Private::safetyCheckDeleter;
+# else
+ typename Private::DestroyerFn destroy = &Private::deleter;
+# endif
+ QSharedPointer result(Qt::Uninitialized);
+ result.d = Private::create(&result.value, destroy);
+
+ // now initialize the data
+ new (result.data()) T(arg);
+# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
+ internalSafetyCheckAdd(result.d, result.value);
+# endif
+ result.d->setQObjectShared(result.value, true);
+ return result;
+ }
#endif
private:
@@ -452,6 +480,14 @@ private:
delete d;
}
+ template <class X>
+ inline void enableSharedFromThis(const QEnableSharedFromThis<X> *ptr)
+ {
+ ptr->initializeFromSharedPointer(*this);
+ }
+
+ inline void enableSharedFromThis(...) {}
+
template <typename Deleter>
inline void internalConstruct(T *ptr, Deleter deleter)
{
@@ -472,6 +508,7 @@ private:
internalSafetyCheckAdd(d, ptr);
#endif
d->setQObjectShared(ptr, true);
+ enableSharedFromThis(ptr);
}
template <class X>
@@ -555,7 +592,7 @@ public:
inline bool operator !() const { return isNull(); }
inline T *data() const { return d == 0 || d->strongref.load() == 0 ? 0 : value; }
- inline QWeakPointer() : d(0), value(0) { }
+ Q_DECL_CONSTEXPR inline QWeakPointer() : d(0), value(0) { }
inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
#ifndef QT_NO_QOBJECT
@@ -573,17 +610,23 @@ public:
{ return *this = QWeakPointer(ptr); }
#endif
- inline QWeakPointer(const QWeakPointer<T> &o) : d(o.d), value(o.value)
+ inline QWeakPointer(const QWeakPointer &o) : d(o.d), value(o.value)
{ if (d) d->weakref.ref(); }
- inline QWeakPointer<T> &operator=(const QWeakPointer<T> &o)
+ inline QWeakPointer &operator=(const QWeakPointer &o)
{
internalSet(o.d, o.value);
return *this;
}
+ inline void swap(QWeakPointer &other)
+ {
+ qSwap(this->d, other.d);
+ qSwap(this->value, other.value);
+ }
+
inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data())
{ if (d) d->weakref.ref();}
- inline QWeakPointer<T> &operator=(const QSharedPointer<T> &o)
+ inline QWeakPointer &operator=(const QSharedPointer<T> &o)
{
internalSet(o.d, o.value);
return *this;
@@ -594,7 +637,7 @@ public:
{ *this = o; }
template <class X>
- inline QWeakPointer<T> &operator=(const QWeakPointer<X> &o)
+ inline QWeakPointer &operator=(const QWeakPointer<X> &o)
{
// conversion between X and T could require access to the virtual table
// so force the operation to go through QSharedPointer
@@ -615,7 +658,7 @@ public:
{ *this = o; }
template <class X>
- inline QWeakPointer<T> &operator=(const QSharedPointer<X> &o)
+ inline QWeakPointer &operator=(const QSharedPointer<X> &o)
{
QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid
internalSet(o.d, o.data());
@@ -630,9 +673,11 @@ public:
inline bool operator!=(const QSharedPointer<X> &o) const
{ return !(*this == o); }
- inline void clear() { *this = QWeakPointer<T>(); }
+ inline void clear() { *this = QWeakPointer(); }
inline QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
+ // std::weak_ptr compatibility:
+ inline QSharedPointer<T> lock() const { return toStrongRef(); }
#if defined(QWEAKPOINTER_ENABLE_ARROW)
inline T *operator->() const { return data(); }
@@ -672,6 +717,37 @@ public:
T *value;
};
+template <class T>
+class QEnableSharedFromThis
+{
+protected:
+#ifdef Q_COMPILER_DEFAULT_MEMBERS
+ QEnableSharedFromThis() = default;
+#else
+ Q_DECL_CONSTEXPR QEnableSharedFromThis() {}
+#endif
+ QEnableSharedFromThis(const QEnableSharedFromThis &) {}
+ QEnableSharedFromThis &operator=(const QEnableSharedFromThis &) { return *this; }
+
+public:
+ inline QSharedPointer<T> sharedFromThis() { return QSharedPointer<T>(weakPointer); }
+ inline QSharedPointer<const T> sharedFromThis() const { return QSharedPointer<const T>(weakPointer); }
+
+#ifndef Q_NO_TEMPLATE_FRIENDS
+private:
+ template <class X> friend class QSharedPointer;
+#else
+public:
+#endif
+ template <class X>
+ inline void initializeFromSharedPointer(const QSharedPointer<X> &ptr) const
+ {
+ weakPointer = ptr;
+ }
+
+ mutable QWeakPointer<T> weakPointer;
+};
+
//
// operator== and operator!=
//
diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp
index 2d679e036e..07558cedda 100644
--- a/src/corelib/tools/qsimd.cpp
+++ b/src/corelib/tools/qsimd.cpp
@@ -54,7 +54,7 @@
# include <intrin.h>
# endif
# endif
-#elif defined(Q_OS_LINUX) && (defined(Q_PROCESSOR_ARM) || defined(QT_COMPILER_SUPPORTS_IWMMXT))
+#elif defined(Q_OS_LINUX) && (defined(Q_PROCESSOR_ARM) || defined(Q_PROCESSOR_MIPS_32) || defined(QT_COMPILER_SUPPORTS_IWMMXT))
#include "private/qcore_unix_p.h"
// the kernel header definitions for HWCAP_*
@@ -308,6 +308,141 @@ static inline uint detectProcessorFeatures()
return features;
}
+#elif defined(Q_PROCESSOR_MIPS_32)
+
+#if defined(Q_OS_LINUX)
+//
+// Do not use QByteArray: it could use SIMD instructions itself at
+// some point, thus creating a recursive dependency. Instead, use a
+// QSimpleBuffer, which has the bare minimum needed to use memory
+// dynamically and read lines from /proc/cpuinfo of arbitrary sizes.
+//
+struct QSimpleBuffer {
+ static const int chunk_size = 256;
+ char *data;
+ unsigned alloc;
+ unsigned size;
+
+ QSimpleBuffer(): data(0), alloc(0), size(0) {}
+ ~QSimpleBuffer() { ::free(data); }
+
+ void resize(unsigned newsize) {
+ if (newsize > alloc) {
+ unsigned newalloc = chunk_size * ((newsize / chunk_size) + 1);
+ if (newalloc < newsize) newalloc = newsize;
+ if (newalloc != alloc) {
+ data = static_cast<char*>(::realloc(data, newalloc));
+ alloc = newalloc;
+ }
+ }
+ size = newsize;
+ }
+ void append(const QSimpleBuffer &other, unsigned appendsize) {
+ unsigned oldsize = size;
+ resize(oldsize + appendsize);
+ ::memcpy(data + oldsize, other.data, appendsize);
+ }
+ void popleft(unsigned amount) {
+ if (amount >= size) return resize(0);
+ size -= amount;
+ ::memmove(data, data + amount, size);
+ }
+ char* cString() {
+ if (!alloc) resize(1);
+ return (data[size] = '\0', data);
+ }
+};
+
+//
+// Uses a scratch "buffer" (which must be used for all reads done in the
+// same file descriptor) to read chunks of data from a file, to read
+// one line at a time. Lines include the trailing newline character ('\n').
+// On EOF, line.size is zero.
+//
+static void bufReadLine(int fd, QSimpleBuffer &line, QSimpleBuffer &buffer)
+{
+ for (;;) {
+ char *newline = static_cast<char*>(::memchr(buffer.data, '\n', buffer.size));
+ if (newline) {
+ unsigned piece_size = newline - buffer.data + 1;
+ line.append(buffer, piece_size);
+ buffer.popleft(piece_size);
+ line.resize(line.size - 1);
+ return;
+ }
+ if (buffer.size + QSimpleBuffer::chunk_size > buffer.alloc) {
+ int oldsize = buffer.size;
+ buffer.resize(buffer.size + QSimpleBuffer::chunk_size);
+ buffer.size = oldsize;
+ }
+ ssize_t read_bytes = ::qt_safe_read(fd, buffer.data + buffer.size, QSimpleBuffer::chunk_size);
+ if (read_bytes > 0) buffer.size += read_bytes;
+ else return;
+ }
+}
+
+//
+// Checks if any line with a given prefix from /proc/cpuinfo contains
+// a certain string, surrounded by spaces.
+//
+static bool procCpuinfoContains(const char *prefix, const char *string)
+{
+ int cpuinfo_fd = ::qt_safe_open("/proc/cpuinfo", O_RDONLY);
+ if (cpuinfo_fd == -1)
+ return false;
+
+ unsigned string_len = ::strlen(string);
+ unsigned prefix_len = ::strlen(prefix);
+ QSimpleBuffer line, buffer;
+ bool present = false;
+ do {
+ line.resize(0);
+ bufReadLine(cpuinfo_fd, line, buffer);
+ char *colon = static_cast<char*>(::memchr(line.data, ':', line.size));
+ if (colon && line.size > prefix_len + string_len) {
+ if (!::strncmp(prefix, line.data, prefix_len)) {
+ // prefix matches, next character must be ':' or space
+ if (line.data[prefix_len] == ':' || ::isspace(line.data[prefix_len])) {
+ // Does it contain the string?
+ char *found = ::strstr(line.cString(), string);
+ if (found && ::isspace(found[-1]) &&
+ (::isspace(found[string_len]) || found[string_len] == '\0')) {
+ present = true;
+ break;
+ }
+ }
+ }
+ }
+ } while (line.size);
+
+ ::qt_safe_close(cpuinfo_fd);
+ return present;
+}
+#endif
+
+static inline uint detectProcessorFeatures()
+{
+ // NOTE: MIPS 74K cores are the only ones supporting DSPr2.
+ uint flags = 0;
+
+#if defined __mips_dsp
+ flags |= DSP;
+# if defined __mips_dsp_rev && __mips_dsp_rev >= 2
+ flags |= DSPR2;
+# elif defined(Q_OS_LINUX)
+ if (procCpuinfoContains("cpu model", "MIPS 74Kc") || procCpuinfoContains("cpu model", "MIPS 74Kf"))
+ flags |= DSPR2;
+# endif
+#elif defined(Q_OS_LINUX)
+ if (procCpuinfoContains("ASEs implemented", "dsp")) {
+ flags |= DSP;
+ if (procCpuinfoContains("cpu model", "MIPS 74Kc") || procCpuinfoContains("cpu model", "MIPS 74Kf"))
+ flags |= DSPR2;
+ }
+#endif
+
+ return flags;
+}
#else
static inline uint detectProcessorFeatures()
@@ -330,6 +465,8 @@ static inline uint detectProcessorFeatures()
avx2
hle
rtm
+ dsp
+ dspr2
*/
// begin generated
@@ -345,11 +482,13 @@ static const char features_string[] =
" avx2\0"
" hle\0"
" rtm\0"
+ " dsp\0"
+ " dspr2\0"
"\0";
static const int features_indices[] = {
0, 8, 14, 20, 26, 33, 41, 49,
- 54, 60, 65, -1
+ 54, 60, 65, 70, 75, -1
};
// end generated
diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h
index e1c22bac71..19a1943367 100644
--- a/src/corelib/tools/qsimd_p.h
+++ b/src/corelib/tools/qsimd_p.h
@@ -50,6 +50,7 @@
* They mean the compiler supports the necessary flags and the headers
* for the x86 and ARM intrinsics:
* - GCC: the -mXXX or march=YYY flag is necessary before #include
+ * up to 4.8; GCC >= 4.9 can include unconditionally
* - Intel CC: #include can happen unconditionally
* - MSVC: #include can happen unconditionally
* - RVCT: ???
@@ -60,25 +61,99 @@
* up do define __AVX__ if the -arch:AVX option is passed on the command-line.
*
* Supported XXX are:
- * Flag | Arch | GCC | Intel CC | MSVC |
- * NEON | ARM | I & C | None | ? |
- * IWMMXT | ARM | I & C | None | I & C |
- * SSE2 | x86 | I & C | I & C | I & C |
- * SSE3 | x86 | I & C | I & C | I only |
- * SSSE3 | x86 | I & C | I & C | I only |
- * SSE4_1 | x86 | I & C | I & C | I only |
- * SSE4_2 | x86 | I & C | I & C | I only |
- * AVX | x86 | I & C | I & C | I & C |
- * AVX2 | x86 | I & C | I & C | I only |
+ * Flag | Arch | GCC | Intel CC | MSVC |
+ * ARM_NEON | ARM | I & C | None | ? |
+ * IWMMXT | ARM | I & C | None | I & C |
+ * SSE2 | x86 | I & C | I & C | I & C |
+ * SSE3 | x86 | I & C | I & C | I only |
+ * SSSE3 | x86 | I & C | I & C | I only |
+ * SSE4_1 | x86 | I & C | I & C | I only |
+ * SSE4_2 | x86 | I & C | I & C | I only |
+ * AVX | x86 | I & C | I & C | I & C |
+ * AVX2 | x86 | I & C | I & C | I only |
* I = intrinsics; C = code generation
+ *
+ * Code can use the following constructs to determine compiler support & status:
+ * - #ifdef __XXX__ (e.g: #ifdef __AVX__ or #ifdef __ARM_NEON__)
+ * If this test passes, then the compiler is already generating code for that
+ * given sub-architecture. The intrinsics for that sub-architecture are
+ * #included and can be used without restriction or runtime check.
+ *
+ * - #if QT_COMPILER_SUPPORTS(XXX)
+ * If this test passes, then the compiler is able to generate code for that
+ * given sub-architecture in another translation unit, given the right set of
+ * flags. Use of the intrinsics is not guaranteed. This is useful with
+ * runtime detection (see below).
+ *
+ * - #if QT_COMPILER_SUPPORTS_HERE(XXX)
+ * If this test passes, then the compiler is able to generate code for that
+ * given sub-architecture in this translation unit, even if it is not doing
+ * that now (it might be). Individual functions may be tagged with
+ * QT_FUNCTION_TARGET(XXX) to cause the compiler to generate code for that
+ * sub-arch. Only inside such functions is the use of the intrisics
+ * guaranteed to work. This is useful with runtime detection (see below).
+ *
+ * Runtime detection of a CPU sub-architecture can be done with the
+ * qCpuHasFeature(XXX) function. There are two strategies for generating
+ * optimized code like that:
+ *
+ * 1) place the optimized code in a different translation unit (C or assembly
+ * sources) and pass the correct flags to the compiler to enable support. Those
+ * sources must not include qglobal.h, which means they cannot include this
+ * file either. The dispatcher function would look like this:
+ *
+ * void foo()
+ * {
+ * #if QT_COMPILER_SUPPORTS(XXX)
+ * if (qCpuHasFeature(XXX)) {
+ * foo_optimized_xxx();
+ * return;
+ * }
+ * #endif
+ * foo_plain();
+ * }
+ *
+ * 2) place the optimized code in a function tagged with QT_FUNCTION_TARGET and
+ * surrounded by #if QT_COMPILER_SUPPORTS_HERE(XXX). That code can freely use
+ * other Qt code. The dispatcher function would look like this:
+ *
+ * void foo()
+ * {
+ * #if QT_COMPILER_SUPPORTS_HERE(XXX)
+ * if (qCpuHasFeature(XXX)) {
+ * foo_optimized_xxx();
+ * return;
+ * }
+ * #endif
+ * foo_plain();
+ * }
*/
#if defined(__MINGW64_VERSION_MAJOR) || (defined(Q_CC_MSVC) && !defined(Q_OS_WINCE))
#include <intrin.h>
#endif
+#define QT_COMPILER_SUPPORTS(x) (QT_COMPILER_SUPPORTS_ ## x - 0)
+
+#if (defined(Q_CC_INTEL) || defined(Q_CC_MSVC) \
+ || (defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && (__GNUC__-0) * 100 + (__GNUC_MINOR__-0) >= 409)) \
+ && !defined(QT_BOOTSTRAPPED)
+# define QT_COMPILER_SUPPORTS_SIMD_ALWAYS
+# define QT_COMPILER_SUPPORTS_HERE(x) QT_COMPILER_SUPPORTS(x)
+# if defined(Q_CC_GNU) && !defined(Q_CC_INTEL)
+ /* GCC requires attributes for a function */
+# define QT_FUNCTION_TARGET(x) __attribute__((__target__(QT_FUNCTION_TARGET_STRING_ ## x)))
+# else
+# define QT_FUNCTION_TARGET(x)
+# endif
+#else
+# define QT_COMPILER_SUPPORTS_HERE(x) defined(__ ## x ## __)
+# define QT_FUNCTION_TARGET(x)
+#endif
+
// SSE intrinsics
-#if defined(__SSE2__) || (defined(QT_COMPILER_SUPPORTS_SSE2) && defined(Q_CC_MSVC))
+#define QT_FUNCTION_TARGET_STRING_SSE2 "sse2"
+#if defined(__SSE2__) || (defined(QT_COMPILER_SUPPORTS_SSE2) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
#if defined(QT_LINUXBASE) || defined(Q_OS_ANDROID_NO_SDK)
/// this is an evil hack - the posix_memalign declaration in LSB
/// is wrong - see http://bugs.linuxbase.org/show_bug.cgi?id=2431
@@ -95,27 +170,33 @@
#endif
// SSE3 intrinsics
-#if defined(__SSE3__) || (defined(QT_COMPILER_SUPPORTS_SSE3) && defined(Q_CC_MSVC))
+#define QT_FUNCTION_TARGET_STRING_SSE3 "sse3"
+#if defined(__SSE3__) || (defined(QT_COMPILER_SUPPORTS_SSE3) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
#include <pmmintrin.h>
#endif
// SSSE3 intrinsics
-#if defined(__SSSE3__) || (defined(QT_COMPILER_SUPPORTS_SSSE3) && defined(Q_CC_MSVC))
+#define QT_FUNCTION_TARGET_STRING_SSSE3 "ssse3"
+#if defined(__SSSE3__) || (defined(QT_COMPILER_SUPPORTS_SSSE3) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
#include <tmmintrin.h>
#endif
// SSE4.1 intrinsics
-#if defined(__SSE4_1__) || (defined(QT_COMPILER_SUPPORTS_SSE4_1) && defined(Q_CC_MSVC))
+#define QT_FUNCTION_TARGET_STRING_SSE4_1 "sse4.1"
+#if defined(__SSE4_1__) || (defined(QT_COMPILER_SUPPORTS_SSE4_1) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
#include <smmintrin.h>
#endif
// SSE4.2 intrinsics
-#if defined(__SSE4_2__) || (defined(QT_COMPILER_SUPPORTS_SSE4_2) && defined(Q_CC_MSVC))
+#define QT_FUNCTION_TARGET_STRING_SSE4_2 "sse4.2"
+#if defined(__SSE4_2__) || (defined(QT_COMPILER_SUPPORTS_SSE4_2) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
#include <nmmintrin.h>
#endif
// AVX intrinsics
-#if defined(__AVX__) || (defined(QT_COMPILER_SUPPORTS_AVX) && defined(Q_CC_MSVC))
+#define QT_FUNCTION_TARGET_STRING_AVX "avx"
+#define QT_FUNCTION_TARGET_STRING_AVX2 "avx2"
+#if defined(__AVX__) || (defined(QT_COMPILER_SUPPORTS_AVX) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
// immintrin.h is the ultimate header, we don't need anything else after this
#include <immintrin.h>
@@ -149,8 +230,10 @@
#endif
// NEON intrinsics
+// note: as of GCC 4.9, does not support function targets for ARM
#if defined __ARM_NEON__
#include <arm_neon.h>
+#define QT_FUNCTION_TARGET_STRING_ARM_NEON "neon"
#endif
@@ -171,12 +254,14 @@
#endif
#endif
+#undef QT_COMPILER_SUPPORTS_SIMD_ALWAYS
+
QT_BEGIN_NAMESPACE
enum CPUFeatures {
IWMMXT = 0x1,
- NEON = 0x2,
+ NEON = 0x2, ARM_NEON = NEON,
SSE2 = 0x4,
SSE3 = 0x8,
SSSE3 = 0x10,
@@ -186,6 +271,8 @@ enum CPUFeatures {
AVX2 = 0x100,
HLE = 0x200,
RTM = 0x400,
+ DSP = 0x800,
+ DSPR2 = 0x1000,
// used only to indicate that the CPU detection was initialised
QSimdInitialized = 0x80000000
@@ -225,6 +312,12 @@ static const uint qCompilerCpuFeatures = 0
#if defined __IWMMXT__
| IWMMXT
#endif
+#if defined __mips_dsp
+ | DSP
+#endif
+#if defined __mips_dspr2
+ | DSPR2
+#endif
;
diff --git a/src/corelib/tools/qsize.cpp b/src/corelib/tools/qsize.cpp
index c9a6ffa03a..03966ab1d6 100644
--- a/src/corelib/tools/qsize.cpp
+++ b/src/corelib/tools/qsize.cpp
@@ -445,9 +445,11 @@ QDataStream &operator>>(QDataStream &s, QSize &sz)
#endif // QT_NO_DATASTREAM
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QSize &s) {
+QDebug operator<<(QDebug dbg, const QSize &s)
+{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QSize(" << s.width() << ", " << s.height() << ')';
- return dbg.space();
+ return dbg;
}
#endif
@@ -870,9 +872,11 @@ QDataStream &operator>>(QDataStream &s, QSizeF &sz)
#endif // QT_NO_DATASTREAM
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QSizeF &s) {
+QDebug operator<<(QDebug dbg, const QSizeF &s)
+{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QSizeF(" << s.width() << ", " << s.height() << ')';
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 83f1bac2ef..e8eb04b598 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -223,8 +223,15 @@ void qt_from_latin1(ushort *dst, const char *str, size_t size)
// we're going to read str[offset..offset+15] (16 bytes)
for ( ; str + offset + 15 < e; offset += 16) {
- const __m128i nullMask = _mm_set1_epi32(0);
const __m128i chunk = _mm_loadu_si128((__m128i*)(str + offset)); // load
+#ifdef __AVX2__
+ // zero extend to an YMM register
+ const __m256i extended = _mm256_cvtepu8_epi16(chunk);
+
+ // store
+ _mm256_storeu_si256((__m256i*)(dst + offset), extended);
+#else
+ const __m128i nullMask = _mm_set1_epi32(0);
// unpack the first 8 bytes, padding with zeros
const __m128i firstHalf = _mm_unpacklo_epi8(chunk, nullMask);
@@ -233,6 +240,7 @@ void qt_from_latin1(ushort *dst, const char *str, size_t size)
// unpack the last 8 bytes, padding with zeros
const __m128i secondHalf = _mm_unpackhi_epi8 (chunk, nullMask);
_mm_storeu_si128((__m128i*)(dst + offset + 8), secondHalf); // store
+#endif
}
size = size % 16;
@@ -540,8 +548,20 @@ static int ucstrncmp(const QChar *a, const uchar *c, int l)
// and c[offset..offset+15] (16 bytes)
for ( ; uc + offset + 15 < e; offset += 16) {
// similar to fromLatin1_helper:
- // load Latin 1 data and expand to UTF-16
+ // load 16 bytes of Latin 1 data
__m128i chunk = _mm_loadu_si128((__m128i*)(c + offset));
+
+# ifdef __AVX2__
+ // expand Latin 1 data via zero extension
+ __m256i ldata = _mm256_cvtepu8_epi16(chunk);
+
+ // load UTF-16 data and compare
+ __m256i ucdata = _mm256_loadu_si256((__m256i*)(uc + offset));
+ __m256i result = _mm256_cmpeq_epi16(ldata, ucdata);
+
+ uint mask = ~_mm256_movemask_epi8(result);
+# else
+ // expand via unpacking
__m128i firstHalf = _mm_unpacklo_epi8(chunk, nullmask);
__m128i secondHalf = _mm_unpackhi_epi8(chunk, nullmask);
@@ -552,6 +572,7 @@ static int ucstrncmp(const QChar *a, const uchar *c, int l)
__m128i result2 = _mm_cmpeq_epi16(secondHalf, ucdata2);
uint mask = ~(_mm_movemask_epi8(result1) | _mm_movemask_epi8(result2) << 16);
+# endif
if (mask) {
// found a different character
uint idx = uint(_bit_scan_forward(mask));
@@ -1309,7 +1330,7 @@ const QString::Null QString::null = { };
This constructor is only available if Qt is configured with STL
compatibility enabled.
- \sa fromLatin1(), fromLocal8Bit(), fromUtf8()
+ \sa fromLatin1(), fromLocal8Bit(), fromUtf8(), QByteArray::fromStdString()
*/
/*! \fn QString QString::fromStdWString(const std::wstring &str)
@@ -4090,21 +4111,22 @@ QString QString::right(int n) const
QString QString::mid(int position, int n) const
{
- if (position > d->size)
+ using namespace QtPrivate;
+ switch (QContainerImplHelper::mid(d->size, &position, &n)) {
+ case QContainerImplHelper::Null:
return QString();
- if (position < 0) {
- if (n < 0 || n + position >= d->size)
- return *this;
- if (n + position <= 0)
- return QString();
-
- n += position;
- position = 0;
- } else if (uint(n) > uint(d->size - position))
- n = d->size - position;
- if (position == 0 && n == d->size)
+ case QContainerImplHelper::Empty:
+ {
+ QStringDataPtr empty = { Data::allocate(0) };
+ return QString(empty);
+ }
+ case QContainerImplHelper::Full:
return *this;
- return QString((const QChar*) d->data() + position, n);
+ case QContainerImplHelper::Subset:
+ return QString((const QChar*)d->data() + position, n);
+ }
+ Q_UNREACHABLE();
+ return QString();
}
/*!
@@ -6602,6 +6624,27 @@ QString QString::number(double n, char f, int prec)
return s;
}
+namespace {
+template<class ResultList, typename MidMethod, typename Separator>
+static ResultList splitString(const QString &source, MidMethod mid, const Separator &sep,
+ QString::SplitBehavior behavior, Qt::CaseSensitivity cs, const int separatorSize)
+{
+ ResultList list;
+ int start = 0;
+ int end;
+ int extra = 0;
+ while ((end = source.indexOf(sep, start + extra, cs)) != -1) {
+ if (start != end || behavior == QString::KeepEmptyParts)
+ list.append((source.*mid)(start, end - start));
+ start = end + separatorSize;
+ extra = (separatorSize == 0 ? 1 : 0);
+ }
+ if (start != source.size() || behavior == QString::KeepEmptyParts)
+ list.append((source.*mid)(start, -1));
+ return list;
+}
+} // namespace
+
/*!
Splits the string into substrings wherever \a sep occurs, and
returns the list of those strings. If \a sep does not match
@@ -6622,19 +6665,7 @@ QString QString::number(double n, char f, int prec)
*/
QStringList QString::split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
{
- QStringList list;
- int start = 0;
- int extra = 0;
- int end;
- while ((end = indexOf(sep, start + extra, cs)) != -1) {
- if (start != end || behavior == KeepEmptyParts)
- list.append(mid(start, end - start));
- start = end + sep.size();
- extra = (sep.size() == 0 ? 1 : 0);
- }
- if (start != size() || behavior == KeepEmptyParts)
- list.append(mid(start));
- return list;
+ return splitString<QStringList>(*this, &QString::mid, sep, behavior, cs, sep.size());
}
/*!
@@ -6642,20 +6673,32 @@ QStringList QString::split(const QString &sep, SplitBehavior behavior, Qt::CaseS
*/
QStringList QString::split(QChar sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
{
- QStringList list;
+ return splitString<QStringList>(*this, &QString::mid, sep, behavior, cs, 1);
+}
+
+#ifndef QT_NO_REGEXP
+namespace {
+template<class ResultList, typename MidMethod>
+static ResultList splitString(const QString &source, MidMethod mid, const QRegExp &rx, QString::SplitBehavior behavior)
+{
+ QRegExp rx2(rx);
+ ResultList list;
int start = 0;
+ int extra = 0;
int end;
- while ((end = indexOf(sep, start, cs)) != -1) {
- if (start != end || behavior == KeepEmptyParts)
- list.append(mid(start, end - start));
- start = end + 1;
+ while ((end = rx2.indexIn(source, start + extra)) != -1) {
+ int matchedLen = rx2.matchedLength();
+ if (start != end || behavior == QString::KeepEmptyParts)
+ list.append((source.*mid)(start, end - start));
+ start = end + matchedLen;
+ extra = (matchedLen == 0) ? 1 : 0;
}
- if (start != size() || behavior == KeepEmptyParts)
- list.append(mid(start));
+ if (start != source.size() || behavior == QString::KeepEmptyParts)
+ list.append((source.*mid)(start, -1));
return list;
}
+} // namespace
-#ifndef QT_NO_REGEXP
/*!
\overload
@@ -6684,26 +6727,41 @@ QStringList QString::split(QChar sep, SplitBehavior behavior, Qt::CaseSensitivit
*/
QStringList QString::split(const QRegExp &rx, SplitBehavior behavior) const
{
- QRegExp rx2(rx);
- QStringList list;
- int start = 0;
- int extra = 0;
- int end;
- while ((end = rx2.indexIn(*this, start + extra)) != -1) {
- int matchedLen = rx2.matchedLength();
- if (start != end || behavior == KeepEmptyParts)
- list.append(mid(start, end - start));
- start = end + matchedLen;
- extra = (matchedLen == 0) ? 1 : 0;
- }
- if (start != size() || behavior == KeepEmptyParts)
- list.append(mid(start));
- return list;
+ return splitString<QStringList>(*this, &QString::mid, rx, behavior);
}
#endif
#ifndef QT_NO_REGULAREXPRESSION
#ifndef QT_BOOTSTRAPPED
+namespace {
+template<class ResultList, typename MidMethod>
+static ResultList splitString(const QString &source, MidMethod mid, const QRegularExpression &re,
+ QString::SplitBehavior behavior)
+{
+ ResultList list;
+ if (!re.isValid()) {
+ qWarning("QString::split: invalid QRegularExpression object");
+ return list;
+ }
+
+ int start = 0;
+ int end = 0;
+ QRegularExpressionMatchIterator iterator = re.globalMatch(source);
+ while (iterator.hasNext()) {
+ QRegularExpressionMatch match = iterator.next();
+ end = match.capturedStart();
+ if (start != end || behavior == QString::KeepEmptyParts)
+ list.append((source.*mid)(start, end - start));
+ start = match.capturedEnd();
+ }
+
+ if (start != source.size() || behavior == QString::KeepEmptyParts)
+ list.append((source.*mid)(start, -1));
+
+ return list;
+}
+} // namespace
+
/*!
\overload
\since 5.0
@@ -6733,27 +6791,7 @@ QStringList QString::split(const QRegExp &rx, SplitBehavior behavior) const
*/
QStringList QString::split(const QRegularExpression &re, SplitBehavior behavior) const
{
- QStringList list;
- if (!re.isValid()) {
- qWarning("QString::split: invalid QRegularExpression object");
- return list;
- }
-
- int start = 0;
- int end = 0;
- QRegularExpressionMatchIterator iterator = re.globalMatch(*this);
- while (iterator.hasNext()) {
- QRegularExpressionMatch match = iterator.next();
- end = match.capturedStart();
- if (start != end || behavior == KeepEmptyParts)
- list.append(mid(start, end - start));
- start = match.capturedEnd();
- }
-
- if (start != size() || behavior == KeepEmptyParts)
- list.append(mid(start));
-
- return list;
+ return splitString<QStringList>(*this, &QString::mid, re, behavior);
}
#endif // QT_BOOTSTRAPPED
#endif // QT_NO_REGULAREXPRESSION
@@ -6938,15 +6976,18 @@ static ArgEscapeData findArgEscapes(const QString &s)
break;
}
- if (c->digitValue() == -1)
+ int escape = c->digitValue();
+ if (escape == -1)
continue;
- int escape = c->digitValue();
++c;
- if (c != uc_end && c->digitValue() != -1) {
- escape = (10 * escape) + c->digitValue();
- ++c;
+ if (c != uc_end) {
+ int next_escape = c->digitValue();
+ if (next_escape != -1) {
+ escape = (10 * escape) + next_escape;
+ ++c;
+ }
}
if (escape > d.min_escape)
@@ -7726,7 +7767,7 @@ bool QString::isRightToLeft() const
If the QString contains non-Latin1 Unicode characters, using this
can lead to loss of information.
- \sa toLatin1(), toUtf8(), toLocal8Bit()
+ \sa toLatin1(), toUtf8(), toLocal8Bit(), QByteArray::toStdString()
*/
/*!
@@ -8794,19 +8835,19 @@ QStringRef QString::rightRef(int n) const
*/
QStringRef QStringRef::mid(int pos, int n) const
{
- if (pos > m_size)
+ using namespace QtPrivate;
+ switch (QContainerImplHelper::mid(m_size, &pos, &n)) {
+ case QContainerImplHelper::Null:
return QStringRef();
- if (pos < 0) {
- if (n < 0 || n + pos >= m_size)
- return QStringRef(m_string, m_position, m_size);
- if (n + pos <= 0)
- return QStringRef();
- n += pos;
- pos = 0;
- } else if (uint(n) > uint(m_size - pos)) {
- n = m_size - pos;
+ case QContainerImplHelper::Empty:
+ return QStringRef(m_string, 0, 0);
+ case QContainerImplHelper::Full:
+ return *this;
+ case QContainerImplHelper::Subset:
+ return QStringRef(m_string, pos + m_position, n);
}
- return QStringRef(m_string, pos + m_position, n);
+ Q_UNREACHABLE();
+ return QStringRef();
}
/*!
@@ -8831,19 +8872,19 @@ QStringRef QStringRef::mid(int pos, int n) const
*/
QStringRef QString::midRef(int position, int n) const
{
- if (position > d->size)
+ using namespace QtPrivate;
+ switch (QContainerImplHelper::mid(d->size, &position, &n)) {
+ case QContainerImplHelper::Null:
return QStringRef();
- if (position < 0) {
- if (n < 0 || n + position >= d->size)
- return QStringRef(this, 0, d->size);
- if (n + position <= 0)
- return QStringRef();
-
- n += position;
- position = 0;
- } else if (uint(n) > uint(d->size - position))
- n = d->size - position;
- return QStringRef(this, position, n);
+ case QContainerImplHelper::Empty:
+ return QStringRef(this, 0, 0);
+ case QContainerImplHelper::Full:
+ return QStringRef(this, 0, d->size);
+ case QContainerImplHelper::Subset:
+ return QStringRef(this, position, n);
+ }
+ Q_UNREACHABLE();
+ return QStringRef();
}
/*!
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 3985bc76fe..3afd68af1f 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -724,7 +724,6 @@ private:
void reallocData(uint alloc, bool grow = false);
void expand(int i);
- void updateProperties() const;
QString multiArg(int numArgs, const QString **args) const;
static int compare_helper(const QChar *data1, int length1,
const QChar *data2, int length2,
@@ -1222,7 +1221,7 @@ inline QT_ASCII_CAST_WARN const QString operator+(const QString &s, const QByteA
#endif // QT_USE_QSTRINGBUILDER
inline std::string QString::toStdString() const
-{ const QByteArray asc = toUtf8(); return std::string(asc.constData(), asc.length()); }
+{ return toUtf8().toStdString(); }
inline QString QString::fromStdString(const std::string &s)
{ return fromUtf8(s.data(), int(s.size())); }
diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp
index 6b0b39c7bb..0d37b6ea58 100644
--- a/src/corelib/tools/qstringlist.cpp
+++ b/src/corelib/tools/qstringlist.cpp
@@ -191,20 +191,6 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QStringList::QStringList(const QStringList &other)
-
- Constructs a copy of the \a other string list.
-
- This operation takes \l{constant time} because QStringList is
- \l{implicitly shared}, making the process of returning a
- QStringList from a function very fast. If a shared instance is
- modified, it will be copied (copy-on-write), and that takes
- \l{linear time}.
-
- \sa operator=()
-*/
-
-/*!
\fn QStringList::QStringList(const QList<QString> &other)
Constructs a copy of \a other.
@@ -218,6 +204,37 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn QStringList::QStringList(QList<QString> &&other)
+ \overload
+ \since 5.4
+
+ Move-constructs from QList<QString>.
+
+ After a successful construction, \a other will be empty.
+*/
+
+/*!
+ \fn QStringList &QStringList::operator=(const QList<QString> &other)
+ \since 5.4
+
+ Copy assignment operator from QList<QString>. Assigns the \a other
+ list of strings to this string list.
+
+ After the operation, \a other and \c *this will be equal.
+*/
+
+/*!
+ \fn QStringList &QStringList::operator=(QList<QString> &&other)
+ \overload
+ \since 5.4
+
+ Move assignment operator from QList<QString>. Moves the \a other
+ list of strings to this string list.
+
+ After the operation, \a other will be empty.
+*/
+
+/*!
\fn void QStringList::sort(Qt::CaseSensitivity cs)
Sorts the list of strings in ascending order.
@@ -235,9 +252,14 @@ QT_BEGIN_NAMESPACE
integer index.
*/
-static inline bool caseInsensitiveLessThan(const QString &s1, const QString &s2)
-{
- return s1.compare(s2, Qt::CaseInsensitive) < 0;
+namespace {
+struct CaseInsensitiveLessThan {
+ typedef bool result_type;
+ result_type operator()(const QString &s1, const QString &s2) const
+ {
+ return s1.compare(s2, Qt::CaseInsensitive) < 0;
+ }
+};
}
void QtPrivate::QStringList_sort(QStringList *that, Qt::CaseSensitivity cs)
@@ -245,7 +267,7 @@ void QtPrivate::QStringList_sort(QStringList *that, Qt::CaseSensitivity cs)
if (cs == Qt::CaseSensitive)
std::sort(that->begin(), that->end());
else
- std::sort(that->begin(), that->end(), caseInsensitiveLessThan);
+ std::sort(that->begin(), that->end(), CaseInsensitiveLessThan());
}
@@ -457,7 +479,7 @@ QString QtPrivate::QStringList_join(const QStringList *that, const QChar *sep, i
if (totalLength == 0)
return res;
res.reserve(totalLength);
- for (int i = 0; i < that->size(); ++i) {
+ for (int i = 0; i < size; ++i) {
if (i)
res.append(sep, seplen);
res += that->at(i);
@@ -492,6 +514,16 @@ QString QtPrivate::QStringList_join(const QStringList *that, const QChar *sep, i
the latter string list.
*/
+/*!
+ \fn QStringList &QStringList::operator<<(const QList<QString> &other)
+ \since 5.4
+
+ \overload
+
+ Appends the \a other string list to the string list and returns a reference to
+ the latter string list.
+*/
+
#ifndef QT_NO_DATASTREAM
/*!
\fn QDataStream &operator>>(QDataStream &in, QStringList &list)
@@ -725,7 +757,7 @@ int QtPrivate::QStringList_removeDuplicates(QStringList *that)
continue;
seen.insert(s);
if (j != i)
- (*that)[j] = s;
+ that->swap(i, j);
++j;
}
if (n != j)
diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h
index a962b7c528..7f06be3ca0 100644
--- a/src/corelib/tools/qstringlist.h
+++ b/src/corelib/tools/qstringlist.h
@@ -63,12 +63,21 @@ class QStringList : public QList<QString>
public:
inline QStringList() { }
inline explicit QStringList(const QString &i) { append(i); }
- inline QStringList(const QStringList &l) : QList<QString>(l) { }
inline QStringList(const QList<QString> &l) : QList<QString>(l) { }
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QStringList(QList<QString> &&l) : QList<QString>(std::move(l)) { }
+#endif
#ifdef Q_COMPILER_INITIALIZER_LISTS
inline QStringList(std::initializer_list<QString> args) : QList<QString>(args) { }
#endif
+ QStringList &operator=(const QList<QString> &other)
+ { QList<QString>::operator=(other); return *this; }
+#ifdef Q_COMPILER_RVALUE_REFS
+ QStringList &operator=(QList<QString> &&other)
+ { QList<QString>::operator=(std::move(other)); return *this; }
+#endif
+
inline void sort(Qt::CaseSensitivity cs = Qt::CaseSensitive);
inline int removeDuplicates();
@@ -86,6 +95,8 @@ public:
{ append(str); return *this; }
inline QStringList &operator<<(const QStringList &l)
{ *this += l; return *this; }
+ inline QStringList &operator<<(const QList<QString> &l)
+ { *this += l; return *this; }
#ifndef QT_NO_REGEXP
inline QStringList filter(const QRegExp &rx) const;
diff --git a/src/corelib/tools/qtimezoneprivate.cpp b/src/corelib/tools/qtimezoneprivate.cpp
index 4286119586..4658b91dd3 100644
--- a/src/corelib/tools/qtimezoneprivate.cpp
+++ b/src/corelib/tools/qtimezoneprivate.cpp
@@ -558,8 +558,8 @@ template<> QTimeZonePrivate *QSharedDataPointer<QTimeZonePrivate>::clone()
// Create default UTC time zone
QUtcTimeZonePrivate::QUtcTimeZonePrivate()
{
- const QString name = QStringLiteral("UTC");
- init(QByteArrayLiteral("UTC"), 0, name, name, QLocale::AnyCountry, name);
+ const QString name = utcQString();
+ init(utcQByteArray(), 0, name, name, QLocale::AnyCountry, name);
}
// Create a named UTC time zone
@@ -583,7 +583,7 @@ QUtcTimeZonePrivate::QUtcTimeZonePrivate(qint32 offsetSeconds)
QString utcId;
if (offsetSeconds == 0)
- utcId = QStringLiteral("UTC");
+ utcId = utcQString();
else
utcId = isoOffsetFormat(offsetSeconds);
@@ -675,7 +675,7 @@ qint32 QUtcTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
QByteArray QUtcTimeZonePrivate::systemTimeZoneId() const
{
- return QByteArrayLiteral("UTC");
+ return utcQByteArray();
}
QSet<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds() const
diff --git a/src/corelib/tools/qtimezoneprivate_p.h b/src/corelib/tools/qtimezoneprivate_p.h
index 417ee2efbf..e8d250784a 100644
--- a/src/corelib/tools/qtimezoneprivate_p.h
+++ b/src/corelib/tools/qtimezoneprivate_p.h
@@ -154,6 +154,17 @@ public:
static QList<QByteArray> windowsIdToIanaIds(const QByteArray &windowsId,
QLocale::Country country);
+ // returns "UTC" QString and QByteArray
+ static inline QString utcQString() Q_REQUIRED_RESULT
+ {
+ return QStringLiteral("UTC");
+ }
+
+ static inline QByteArray utcQByteArray() Q_REQUIRED_RESULT
+ {
+ return QByteArrayLiteral("UTC");
+ }
+
protected:
QByteArray m_id;
};
diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp
index b4ea91e626..2c7b00f653 100644
--- a/src/corelib/tools/qtimezoneprivate_tz.cpp
+++ b/src/corelib/tools/qtimezoneprivate_tz.cpp
@@ -958,7 +958,7 @@ QByteArray QTzTimeZonePrivate::systemTimeZoneId() const
// Give up for now and return UTC
if (ianaId.isEmpty())
- ianaId = QByteArrayLiteral("UTC");
+ ianaId = utcQByteArray();
return ianaId;
}
diff --git a/src/corelib/tools/qtimezoneprivate_win.cpp b/src/corelib/tools/qtimezoneprivate_win.cpp
index 052e584855..6e2c6b47b2 100644
--- a/src/corelib/tools/qtimezoneprivate_win.cpp
+++ b/src/corelib/tools/qtimezoneprivate_win.cpp
@@ -249,7 +249,7 @@ static QByteArray windowsSystemZoneId()
}
// If we can't determine the current ID use UTC
- return QByteArrayLiteral("UTC");
+ return QTimeZonePrivate::utcQByteArray();
}
static QDate calculateTransitionLocalDate(const SYSTEMTIME &rule, int year)
@@ -635,7 +635,7 @@ QByteArray QWinTimeZonePrivate::systemTimeZoneId() const
ianaId = windowsIdToDefaultIanaId(windowsId);
// If no global default then probably an unknown Windows ID so return UTC
if (ianaId.isEmpty())
- return QByteArrayLiteral("UTC");
+ return utcQByteArray();
}
return ianaId;
}
diff --git a/src/corelib/tools/qtools_p.h b/src/corelib/tools/qtools_p.h
index b00343dd39..38073a6e30 100644
--- a/src/corelib/tools/qtools_p.h
+++ b/src/corelib/tools/qtools_p.h
@@ -58,7 +58,7 @@
QT_BEGIN_NAMESPACE
// implemented in qbytearray.cpp
-int Q_CORE_EXPORT qAllocMore(int alloc, int extra);
+int Q_CORE_EXPORT qAllocMore(int alloc, int extra) Q_DECL_NOTHROW;
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qunicodetables.cpp b/src/corelib/tools/qunicodetables.cpp
index 41a22a779a..a351533a98 100644
--- a/src/corelib/tools/qunicodetables.cpp
+++ b/src/corelib/tools/qunicodetables.cpp
@@ -6920,24 +6920,24 @@ static const Properties uc_properties[] = {
{ 12, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 12, 0 }
};
-static inline const Properties *qGetProp(uint ucs4)
+Q_DECL_CONST_FUNCTION static inline const Properties *qGetProp(uint ucs4)
{
const int index = GET_PROP_INDEX(ucs4);
return uc_properties + index;
}
-static inline const Properties *qGetProp(ushort ucs2)
+Q_DECL_CONST_FUNCTION static inline const Properties *qGetProp(ushort ucs2)
{
const int index = GET_PROP_INDEX_UCS2(ucs2);
return uc_properties + index;
}
-Q_CORE_EXPORT const Properties * QT_FASTCALL properties(uint ucs4)
+Q_DECL_CONST_FUNCTION Q_CORE_EXPORT const Properties * QT_FASTCALL properties(uint ucs4)
{
return qGetProp(ucs4);
}
-Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2)
+Q_DECL_CONST_FUNCTION Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2)
{
return qGetProp(ucs2);
}
diff --git a/src/corelib/tools/qvector.cpp b/src/corelib/tools/qvector.cpp
index 89396540e0..e1a451f953 100644
--- a/src/corelib/tools/qvector.cpp
+++ b/src/corelib/tools/qvector.cpp
@@ -180,11 +180,11 @@
/*!
\fn QVector<T> QVector::mid(int pos, int length = -1) const
- Returns a vector whose elements are copied from this vector,
+ Returns a sub-vector which contains elements from this vector,
starting at position \a pos. If \a length is -1 (the default), all
- elements after \a pos are copied; otherwise \a length elements (or
+ elements after \a pos are included; otherwise \a length elements (or
all remaining elements if there are less than \a length elements)
- are copied.
+ are included.
*/
@@ -576,6 +576,28 @@
\sa remove(), QList::removeAt()
*/
+/*! \fn int QVector::removeAll(const T &t)
+ \since 5.4
+
+ Removes all elements that compare equal to \a t from the
+ vector. Returns the number of elements removed, if any.
+
+ Provided for compatibility with QList.
+
+ \sa removeOne(), QList::removeAll()
+*/
+
+/*! \fn bool QVector::removeOne(const T &t)
+ \since 5.4
+
+ Removes the first element that compares equal to \a t from the
+ vector. Returns whether an element was, in fact, removed.
+
+ Provided for compatibility with QList.
+
+ \sa removeAll(), QList::removeOne()
+*/
+
/*! \fn int QVector::length() const
\since 5.2
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index 6f7c534085..f09f1a3c41 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -156,6 +156,24 @@ public:
// QList compatibility
void removeAt(int i) { remove(i); }
+ int removeAll(const T &t)
+ {
+ const const_iterator ce = this->cend(), cit = std::find(this->cbegin(), ce, t);
+ if (cit == ce)
+ return 0;
+ const iterator e = end(), it = std::remove(c2m(cit), e, t);
+ const int result = std::distance(it, e);
+ erase(it, e);
+ return result;
+ }
+ bool removeOne(const T &t)
+ {
+ const int i = indexOf(t);
+ if (i < 0)
+ return false;
+ remove(i);
+ return true;
+ }
int length() const { return size(); }
T takeAt(int i) { T t = at(i); remove(i); return t; }
@@ -252,6 +270,7 @@ private:
{
return (i <= d->end()) && (d->begin() <= i);
}
+ iterator c2m(const_iterator it) { return begin() + (it - cbegin()); }
class AlignmentDummy { Data header; T array[1]; };
};
@@ -791,29 +810,30 @@ bool QVector<T>::contains(const T &t) const
template <typename T>
int QVector<T>::count(const T &t) const
{
- int c = 0;
- T* b = d->begin();
- T* i = d->end();
- while (i != b)
- if (*--i == t)
- ++c;
- return c;
+ return int(std::count(cbegin(), cend(), t));
}
template <typename T>
Q_OUTOFLINE_TEMPLATE QVector<T> QVector<T>::mid(int pos, int len) const
{
- if (len < 0)
- len = size() - pos;
- if (pos == 0 && len == size())
+ using namespace QtPrivate;
+ switch (QContainerImplHelper::mid(d->size, &pos, &len)) {
+ case QContainerImplHelper::Null:
+ case QContainerImplHelper::Empty:
+ return QVector<T>();
+ case QContainerImplHelper::Full:
return *this;
- if (pos + len > size())
- len = size() - pos;
- QVector<T> copy;
- copy.reserve(len);
- for (int i = pos; i < pos + len; ++i)
- copy += at(i);
- return copy;
+ case QContainerImplHelper::Subset:
+ break;
+ }
+
+ QVector<T> midResult;
+ midResult.reallocData(0, len);
+ T *srcFrom = d->begin() + pos;
+ T *srcTo = d->begin() + pos + len;
+ midResult.copyConstruct(srcFrom, srcTo, midResult.data());
+ midResult.d->size = len;
+ return midResult;
}
template <typename T>
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index 57a9591060..d1208a1fe6 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -43,7 +43,6 @@ HEADERS += \
tools/qqueue.h \
tools/qrect.h \
tools/qregexp.h \
- tools/qregularexpression.h \
tools/qringbuffer_p.h \
tools/qrefcount.h \
tools/qscopedpointer.h \
@@ -100,7 +99,6 @@ SOURCES += \
tools/qcontiguouscache.cpp \
tools/qrect.cpp \
tools/qregexp.cpp \
- tools/qregularexpression.cpp \
tools/qrefcount.cpp \
tools/qshareddata.cpp \
tools/qsharedpointer.cpp \
@@ -176,10 +174,15 @@ contains(QT_CONFIG,icu) {
SOURCES += tools/qcollator_posix.cpp
}
-pcre {
- include($$PWD/../../3rdparty/pcre.pri)
-} else {
- LIBS_PRIVATE += -lpcre16
+!contains(QT_DISABLED_FEATURES, regularexpression) {
+ HEADERS += tools/qregularexpression.h
+ SOURCES += tools/qregularexpression.cpp
+
+ pcre {
+ include($$PWD/../../3rdparty/pcre.pri)
+ } else {
+ LIBS_PRIVATE += -lpcre16
+ }
}
INCLUDEPATH += ../3rdparty/harfbuzz/src
@@ -207,3 +210,4 @@ TR_EXCLUDE += ../3rdparty/*
# MIPS DSP
MIPS_DSP_ASM += tools/qstring_mips_dsp_asm.S
MIPS_DSP_HEADERS += ../gui/painting/qt_mips_asm_dsp_p.h
+CONFIG += simd
diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp
index 83d0c73ae1..69049aaccf 100644
--- a/src/corelib/xml/qxmlstream.cpp
+++ b/src/corelib/xml/qxmlstream.cpp
@@ -1631,7 +1631,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 redefined."));
+ raiseWellFormedError(QXmlStream::tr("Attribute '%1' redefined.").arg(attribute.qualifiedName().toString()));
}
}
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index 499e9dbd82..468859fdec 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -42,6 +42,7 @@
#include "qdbusintegrator_p.h"
#include <qcoreapplication.h>
+#include <qelapsedtimer.h>
#include <qdebug.h>
#include <qmetaobject.h>
#include <qobject.h>
@@ -1932,9 +1933,95 @@ int QDBusConnectionPrivate::send(const QDBusMessage& message)
return serial;
}
+// small helper to note long running blocking dbus calls.
+// these are generally a sign of fragile software (too long a call can either
+// lead to bad user experience, if it's running on the GUI thread for instance)
+// or break completely under load (hitting the call timeout).
+//
+// as a result, this is something we want to watch for.
+class QDBusBlockingCallWatcher
+{
+public:
+ QDBusBlockingCallWatcher(const QDBusMessage &message)
+ : m_message(message), m_maxCallTimeoutMs(0)
+ {
+#if defined(QT_NO_DEBUG)
+ // when in a release build, we default these to off.
+ // this means that we only affect code that explicitly enables the warning.
+ static int mainThreadWarningAmount = -1;
+ static int otherThreadWarningAmount = -1;
+#else
+ static int mainThreadWarningAmount = 200;
+ static int otherThreadWarningAmount = 500;
+#endif
+ static bool initializedAmounts = false;
+ static QBasicMutex initializeMutex;
+ QMutexLocker locker(&initializeMutex);
+
+ if (!initializedAmounts) {
+ int tmp = 0;
+ QByteArray env;
+ bool ok = true;
+
+ env = qgetenv("Q_DBUS_BLOCKING_CALL_MAIN_THREAD_WARNING_MS");
+ if (!env.isEmpty()) {
+ tmp = env.toInt(&ok);
+ if (ok)
+ mainThreadWarningAmount = tmp;
+ else
+ qWarning("QDBusBlockingCallWatcher: Q_DBUS_BLOCKING_CALL_MAIN_THREAD_WARNING_MS must be an integer; value ignored");
+ }
+
+ env = qgetenv("Q_DBUS_BLOCKING_CALL_OTHER_THREAD_WARNING_MS");
+ if (!env.isEmpty()) {
+ tmp = env.toInt(&ok);
+ if (ok)
+ otherThreadWarningAmount = tmp;
+ else
+ qWarning("QDBusBlockingCallWatcher: Q_DBUS_BLOCKING_CALL_OTHER_THREAD_WARNING_MS must be an integer; value ignored");
+ }
+
+ initializedAmounts = true;
+ }
+
+ locker.unlock();
+
+ // if this call is running on the main thread, we have a much lower
+ // tolerance for delay because any long-term delay will wreck user
+ // interactivity.
+ if (qApp && qApp->thread() == QThread::currentThread())
+ m_maxCallTimeoutMs = mainThreadWarningAmount;
+ else
+ m_maxCallTimeoutMs = otherThreadWarningAmount;
+
+ m_callTimer.start();
+ }
+
+ ~QDBusBlockingCallWatcher()
+ {
+ if (m_maxCallTimeoutMs < 0)
+ return; // disabled
+
+ if (m_callTimer.elapsed() >= m_maxCallTimeoutMs) {
+ qWarning("QDBusConnection: warning: blocking call took a long time (%d ms, max for this thread is %d ms) to service \"%s\" path \"%s\" interface \"%s\" member \"%s\"",
+ int(m_callTimer.elapsed()), m_maxCallTimeoutMs,
+ qPrintable(m_message.service()), qPrintable(m_message.path()),
+ qPrintable(m_message.interface()), qPrintable(m_message.member()));
+ }
+ }
+
+private:
+ QDBusMessage m_message;
+ int m_maxCallTimeoutMs;
+ QElapsedTimer m_callTimer;
+};
+
+
QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message,
int sendMode, int timeout)
{
+ QDBusBlockingCallWatcher watcher(message);
+
checkThread();
if ((sendMode == QDBus::BlockWithGui || sendMode == QDBus::Block)
&& isServiceRegisteredByThread(message.service()))
@@ -2266,7 +2353,7 @@ QDBusConnectionPrivate::disconnectSignal(SignalHookHash::Iterator &it)
watchedServices.erase(sit);
disconnectSignal(dbusServiceString(), QString(), dbusInterfaceString(),
QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(),
- this, SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
+ this, SLOT(serviceOwnerChangedNoLock(QString,QString,QString)));
}
}
}
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index 954c8564f0..3398fa0cb8 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -97,6 +97,15 @@ QT_BEGIN_NAMESPACE
Accessibility, and the Unix/X11 AT-SPI standard. Other backends
can be supported using QAccessibleBridge.
+ In the Unix/X11 AT-SPI implementation, applications become accessible
+ when two conditions are met:
+ \list
+ \li org.a11y.Status.IsEnabled DBus property is true
+ \li org.a11y.Status.ScreenReaderEnabled DBus property is true
+ \endlist
+ An alternative to setting the DBus AT-SPI properties is to set
+ the QT_LINUX_ACCESSIBILITY_ALWAYS_ON environment variable.
+
In addition to QAccessible's static functions, Qt offers one
generic interface, QAccessibleInterface, that can be used to wrap
all widgets and objects (e.g., QPushButton). This single
@@ -167,7 +176,7 @@ QT_BEGIN_NAMESPACE
\value readOnly The object can usually be edited, but is explicitly set to read-only.
\value selectable The object is selectable.
\value selectableText The object has text which can be selected. This is different from selectable which refers to the object's children.
- \value selected The object is selected.
+ \value selected The object is selected, this is independent of text selection.
\value selfVoicing The object describes itself through speech or sound.
\value sizeable The object can be resized, e.g. top-level windows.
\value summaryElement The object summarizes the state of the window and should be treated with priority.
@@ -317,8 +326,8 @@ QT_BEGIN_NAMESPACE
\value Desktop The object represents the desktop or workspace.
\value Dial An object that represents a dial or knob.
\value Dialog A dialog box.
- \value Document A document window, usually in an MDI environment.
- \value EditableText Editable text
+ \value Document A document, for example in an office application.
+ \value EditableText Editable text such as a line or text edit.
\value Equation An object that represents a mathematical equation.
\value Graphic A graphic or picture, e.g. an icon.
\value Grip A grip that the user can drag to change the size of widgets.
@@ -335,6 +344,7 @@ QT_BEGIN_NAMESPACE
\value NoRole The object has no role. This usually indicates an invalid object.
\value PageTab A page tab that the user can select to switch to a different page in a dialog.
\value PageTabList A list of page tabs.
+ \value Paragraph A paragraph of text (usually found in documents).
\value Pane A generic container.
\value PopupMenu A menu which lists options that the user can select to perform an action.
\value ProgressBar The object displays the progress of an operation in progress.
@@ -344,6 +354,7 @@ QT_BEGIN_NAMESPACE
\value Row A row of cells, usually within a table.
\value RowHeader A header for a row of data.
\value ScrollBar A scroll bar, which allows the user to scroll the visible area.
+ \value Section A section (in a document).
\value Separator A separator that divides space into logical areas.
\value Slider A slider that allows the user to select a value within a given range.
\value Sound An object that represents a sound.
@@ -359,6 +370,7 @@ QT_BEGIN_NAMESPACE
\value Tree A list of items in a tree structure.
\value TreeItem An item in a tree structure.
\value UserRole The first value to be used for user defined roles.
+ \value WebDocument HTML document, usually in a browser.
\value Whitespace Blank space between other objects.
\value Window A top level window.
*/
@@ -2060,7 +2072,6 @@ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoun
\class QAccessibleEditableTextInterface
\ingroup accessibility
\inmodule QtGui
- \internal
\brief The QAccessibleEditableTextInterface class implements support for objects with editable text.
@@ -2478,6 +2489,23 @@ struct QAccessibleActionStrings
const QString showMenuAction;
const QString setFocusAction;
const QString toggleAction;
+
+ QString localizedDescription(const QString &actionName)
+ {
+ if (actionName == pressAction)
+ return QAccessibleActionInterface::tr("Triggers the action");
+ else if (actionName == increaseAction)
+ return QAccessibleActionInterface::tr("Increase the value");
+ else if (actionName == decreaseAction)
+ return QAccessibleActionInterface::tr("Decrease the value");
+ else if (actionName == showMenuAction)
+ return QAccessibleActionInterface::tr("Shows the menu");
+ else if (actionName == setFocusAction)
+ return QAccessibleActionInterface::tr("Sets the focus");
+ else if (actionName == toggleAction)
+ return QAccessibleActionInterface::tr("Toggles the state");
+ return QString();
+ }
};
Q_GLOBAL_STATIC(QAccessibleActionStrings, accessibleActionStrings)
@@ -2489,21 +2517,7 @@ QString QAccessibleActionInterface::localizedActionName(const QString &actionNam
QString QAccessibleActionInterface::localizedActionDescription(const QString &actionName) const
{
- const QAccessibleActionStrings *strings = accessibleActionStrings();
- if (actionName == strings->pressAction)
- return tr("Triggers the action");
- else if (actionName == strings->increaseAction)
- return tr("Increase the value");
- else if (actionName == strings->decreaseAction)
- return tr("Decrease the value");
- else if (actionName == strings->showMenuAction)
- return tr("Shows the menu");
- else if (actionName == strings->setFocusAction)
- return tr("Sets the focus");
- else if (actionName == strings->toggleAction)
- return tr("Toggles the state");
-
- return QString();
+ return accessibleActionStrings()->localizedDescription(actionName);
}
/*!
@@ -2560,6 +2574,13 @@ const QString &QAccessibleActionInterface::toggleAction()
return accessibleActionStrings()->toggleAction;
}
+/*! \internal */
+QString qAccessibleLocalizedActionDescription(const QString &actionName)
+{
+ return accessibleActionStrings()->localizedDescription(actionName);
+}
+
+
#endif
QT_END_NAMESPACE
diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h
index 25ce161940..2da7cf62bf 100644
--- a/src/gui/accessible/qaccessible.h
+++ b/src/gui/accessible/qaccessible.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -65,7 +65,6 @@ class QAccessibleEvent;
class QWindow;
class QTextCursor;
-// We need to inherit QObject to expose the enums to QML.
class Q_GUI_EXPORT QAccessible
{
Q_GADGET
@@ -297,6 +296,9 @@ public:
LayeredPane = 0x00000080,
Terminal = 0x00000081,
Desktop = 0x00000082,
+ Paragraph = 0x00000083,
+ WebDocument = 0x00000084,
+ Section = 0x00000085,
UserRole = 0x0000ffff
};
@@ -889,6 +891,7 @@ Q_DECLARE_INTERFACE(QAccessibleInterface, QAccessibleInterface_iid)
Q_GUI_EXPORT const char *qAccessibleRoleString(QAccessible::Role role);
Q_GUI_EXPORT const char *qAccessibleEventString(QAccessible::Event event);
+Q_GUI_EXPORT QString qAccessibleLocalizedActionDescription(const QString &actionName);
#ifndef QT_NO_DEBUG_STREAM
Q_GUI_EXPORT QDebug operator<<(QDebug d, const QAccessibleInterface *iface);
diff --git a/src/gui/accessible/qaccessiblebridge.cpp b/src/gui/accessible/qaccessiblebridge.cpp
index 60bc1ae0d1..1250666cd9 100644
--- a/src/gui/accessible/qaccessiblebridge.cpp
+++ b/src/gui/accessible/qaccessiblebridge.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
diff --git a/src/gui/accessible/qaccessiblebridge.h b/src/gui/accessible/qaccessiblebridge.h
index 0a0002af2c..164582af2c 100644
--- a/src/gui/accessible/qaccessiblebridge.h
+++ b/src/gui/accessible/qaccessiblebridge.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
diff --git a/src/gui/accessible/qaccessiblecache.cpp b/src/gui/accessible/qaccessiblecache.cpp
index 09c155515e..96dde1ea3f 100644
--- a/src/gui/accessible/qaccessiblecache.cpp
+++ b/src/gui/accessible/qaccessiblecache.cpp
@@ -121,7 +121,7 @@ void QAccessibleCache::deleteInterface(QAccessible::Id id, QObject *obj)
objectToId.remove(obj);
delete iface;
-#ifdef Q_OS_MACX
+#ifdef Q_OS_MAC
removeCocoaElement(id);
#endif
}
diff --git a/src/gui/accessible/qaccessiblecache_mac.mm b/src/gui/accessible/qaccessiblecache_mac.mm
index 6ed461d371..97c0c7e097 100644
--- a/src/gui/accessible/qaccessiblecache_mac.mm
+++ b/src/gui/accessible/qaccessiblecache_mac.mm
@@ -41,27 +41,23 @@
#include "qaccessiblecache_p.h"
-#ifdef Q_OS_OSX
-
QT_BEGIN_NAMESPACE
-void QAccessibleCache::insertElement(QAccessible::Id axid, QT_MANGLE_NAMESPACE(QCocoaAccessibleElement) *element) const
+void QAccessibleCache::insertElement(QAccessible::Id axid, QT_MANGLE_NAMESPACE(QMacAccessibilityElement) *element) const
{
cocoaElements[axid] = element;
}
void QAccessibleCache::removeCocoaElement(QAccessible::Id axid)
{
- QT_MANGLE_NAMESPACE(QCocoaAccessibleElement) *element = elementForId(axid);
+ QT_MANGLE_NAMESPACE(QMacAccessibilityElement) *element = elementForId(axid);
[element invalidate];
cocoaElements.remove(axid);
}
-QT_MANGLE_NAMESPACE(QCocoaAccessibleElement) *QAccessibleCache::elementForId(QAccessible::Id axid) const
+QT_MANGLE_NAMESPACE(QMacAccessibilityElement) *QAccessibleCache::elementForId(QAccessible::Id axid) const
{
return cocoaElements.value(axid);
}
QT_END_NAMESPACE
-
-#endif
diff --git a/src/gui/accessible/qaccessiblecache_p.h b/src/gui/accessible/qaccessiblecache_p.h
index 933c6f7313..643cbe5667 100644
--- a/src/gui/accessible/qaccessiblecache_p.h
+++ b/src/gui/accessible/qaccessiblecache_p.h
@@ -59,7 +59,7 @@
#include "qaccessible.h"
-Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QCocoaAccessibleElement));
+Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QMacAccessibilityElement));
QT_BEGIN_NAMESPACE
@@ -73,9 +73,9 @@ public:
QAccessible::Id insert(QObject *object, QAccessibleInterface *iface) const;
void deleteInterface(QAccessible::Id id, QObject *obj = 0);
-#ifdef Q_OS_OSX
- QT_MANGLE_NAMESPACE(QCocoaAccessibleElement) *elementForId(QAccessible::Id axid) const;
- void insertElement(QAccessible::Id axid, QT_MANGLE_NAMESPACE(QCocoaAccessibleElement) *element) const;
+#ifdef Q_OS_MAC
+ QT_MANGLE_NAMESPACE(QMacAccessibilityElement) *elementForId(QAccessible::Id axid) const;
+ void insertElement(QAccessible::Id axid, QT_MANGLE_NAMESPACE(QMacAccessibilityElement) *element) const;
#endif
private Q_SLOTS:
@@ -87,9 +87,9 @@ private:
mutable QHash<QAccessible::Id, QAccessibleInterface *> idToInterface;
mutable QHash<QObject *, QAccessible::Id> objectToId;
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MAC
void removeCocoaElement(QAccessible::Id axid);
- mutable QHash<QAccessible::Id, QT_MANGLE_NAMESPACE(QCocoaAccessibleElement) *> cocoaElements;
+ mutable QHash<QAccessible::Id, QT_MANGLE_NAMESPACE(QMacAccessibilityElement) *> cocoaElements;
#endif
friend class QAccessible;
diff --git a/src/gui/accessible/qaccessibleobject.cpp b/src/gui/accessible/qaccessibleobject.cpp
index b01c8e45db..44ebd5709a 100644
--- a/src/gui/accessible/qaccessibleobject.cpp
+++ b/src/gui/accessible/qaccessibleobject.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
diff --git a/src/gui/accessible/qaccessibleobject.h b/src/gui/accessible/qaccessibleobject.h
index 5cc71a121b..233a43f804 100644
--- a/src/gui/accessible/qaccessibleobject.h
+++ b/src/gui/accessible/qaccessibleobject.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
diff --git a/src/gui/accessible/qaccessibleplugin.cpp b/src/gui/accessible/qaccessibleplugin.cpp
index 17b3f52805..4d12d9ec73 100644
--- a/src/gui/accessible/qaccessibleplugin.cpp
+++ b/src/gui/accessible/qaccessibleplugin.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
diff --git a/src/gui/accessible/qaccessibleplugin.h b/src/gui/accessible/qaccessibleplugin.h
index ac56c83f98..08160f244d 100644
--- a/src/gui/accessible/qaccessibleplugin.h
+++ b/src/gui/accessible/qaccessibleplugin.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
diff --git a/src/gui/accessible/qplatformaccessibility.cpp b/src/gui/accessible/qplatformaccessibility.cpp
index 490fb7a407..1e5f8928ad 100644
--- a/src/gui/accessible/qplatformaccessibility.cpp
+++ b/src/gui/accessible/qplatformaccessibility.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
diff --git a/src/gui/accessible/qplatformaccessibility.h b/src/gui/accessible/qplatformaccessibility.h
index f86a9b6157..6b8056918d 100644
--- a/src/gui/accessible/qplatformaccessibility.h
+++ b/src/gui/accessible/qplatformaccessibility.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
diff --git a/src/gui/doc/images/qpixelformat-argb32buffer.png b/src/gui/doc/images/qpixelformat-argb32buffer.png
new file mode 100644
index 0000000000..5888f0b03d
--- /dev/null
+++ b/src/gui/doc/images/qpixelformat-argb32buffer.png
Binary files differ
diff --git a/src/gui/doc/qtgui.qdocconf b/src/gui/doc/qtgui.qdocconf
index b1707e1eef..e2194839d2 100644
--- a/src/gui/doc/qtgui.qdocconf
+++ b/src/gui/doc/qtgui.qdocconf
@@ -2,7 +2,6 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = QtGui
description = Qt GUI Reference Documentation
-url = http://qt-project.org/doc/qt-$QT_VER
version = $QT_VERSION
examplesinstallpath = gui
diff --git a/src/gui/doc/src/dnd.qdoc b/src/gui/doc/src/dnd.qdoc
index 9f7fdc7fbf..844848c76c 100644
--- a/src/gui/doc/src/dnd.qdoc
+++ b/src/gui/doc/src/dnd.qdoc
@@ -399,13 +399,15 @@
On X11, the public \l{http://www.newplanetsoftware.com/xdnd/}{XDND
protocol} is used, while on Windows Qt uses the OLE standard, and
- Qt for Mac OS X uses the Cocoa Drag Manager. On X11, XDND uses MIME,
+ Qt for OS X uses the Cocoa Drag Manager. On X11, XDND uses MIME,
so no translation is necessary. The Qt API is the same regardless of
the platform. On Windows, MIME-aware applications can communicate by
using clipboard format names that are MIME types. Already some
Windows applications use MIME naming conventions for their
- clipboard formats. Internally, Qt uses QWindowsMime and
- QMacPasteboardMime for translating proprietary clipboard formats
- to and from MIME types.
+ clipboard formats.
+
+ Custom classes for translating proprietary clipboard formats can be
+ registered by reimplementing QWinMime on Windows or
+ QMacPasteboardMime on OS X.
*/
diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri
index bbdd0f3da7..7022a6efd0 100644
--- a/src/gui/image/image.pri
+++ b/src/gui/image/image.pri
@@ -78,12 +78,8 @@ contains(QT_CONFIG, jpeg):include($$PWD/qjpeghandler.pri)
contains(QT_CONFIG, gif):include($$PWD/qgifhandler.pri)
# SIMD
-contains(QT_CPU_FEATURES.$$QT_ARCH, neon) {
- SOURCES += image/qimage_neon.cpp
-}
-contains(QT_CPU_FEATURES.$$QT_ARCH, sse2) {
- SOURCES += image/qimage_sse2.cpp
- SSSE3_SOURCES += image/qimage_ssse3.cpp
-}
+SSE2_SOURCES += image/qimage_sse2.cpp
+SSSE3_SOURCES += image/qimage_ssse3.cpp
+NEON_SOURCES += image/qimage_neon.cpp
MIPS_DSPR2_SOURCES += image/qimage_mips_dspr2.cpp
MIPS_DSPR2_ASM += image/qimage_mips_dspr2_asm.S
diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp
index bb79a139b3..036d0615e3 100644
--- a/src/gui/image/qbmphandler.cpp
+++ b/src/gui/image/qbmphandler.cpp
@@ -798,6 +798,8 @@ bool QBmpHandler::write(const QImage &img)
case QImage::Format_ARGB4444_Premultiplied:
case QImage::Format_RGBA8888:
case QImage::Format_RGBA8888_Premultiplied:
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_A2RGB30_Premultiplied:
image = img.convertToFormat(QImage::Format_ARGB32);
break;
case QImage::Format_RGB16:
@@ -806,6 +808,8 @@ bool QBmpHandler::write(const QImage &img)
case QImage::Format_RGB555:
case QImage::Format_RGB444:
case QImage::Format_RGBX8888:
+ case QImage::Format_BGR30:
+ case QImage::Format_RGB30:
image = img.convertToFormat(QImage::Format_RGB32);
break;
default:
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index 681e7e3f79..ac95222c99 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -1321,8 +1321,20 @@ QDataStream &operator>>(QDataStream &s, QIcon &icon)
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QIcon &i)
{
- dbg.nospace() << "QIcon(" << i.name() << ')';
- return dbg.space();
+ QDebugStateSaver saver(dbg);
+ dbg.resetFormat();
+ dbg.nospace();
+ dbg << "QIcon(";
+ if (i.isNull()) {
+ dbg << "null";
+ } else {
+ if (!i.name().isEmpty())
+ dbg << i.name() << ',';
+ dbg << "availableSizes[normal,Off]=" << i.availableSizes()
+ << ",cacheKey=" << showbase << hex << i.cacheKey() << dec << noshowbase;
+ }
+ dbg << ')';
+ return dbg;
}
#endif
diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h
index 68cd4a5452..eb94457f48 100644
--- a/src/gui/image/qicon_p.h
+++ b/src/gui/image/qicon_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -129,7 +129,7 @@ private:
QPixmapIconEngineEntry *tryMatch(const QSize &size, QIcon::Mode mode, QIcon::State state);
QVector<QPixmapIconEngineEntry> pixmaps;
- friend QDataStream &operator<<(QDataStream &s, const QIcon &icon);
+ friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &s, const QIcon &icon);
friend class QIconThemeEngine;
};
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 273c1c922e..8c7c446e96 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -222,6 +222,16 @@ bool QImageData::checkForAlphaPixels() const
}
} break;
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_A2RGB30_Premultiplied: {
+ uchar *bits = data;
+ for (int y=0; y<height && !has_alpha_pixels; ++y) {
+ for (int x=0; x<width; ++x)
+ has_alpha_pixels |= (((uint *)bits)[x] & 0xc0000000) != 0xc0000000;
+ bits += bytes_per_line;
+ }
+ } break;
+
case QImage::Format_ARGB8555_Premultiplied:
case QImage::Format_ARGB8565_Premultiplied: {
uchar *bits = data;
@@ -701,6 +711,10 @@ bool QImageData::checkForAlphaPixels() const
is the same on any architecture if read as bytes 0xRR,0xGG,0xBB,0xAA.
\value Format_RGBA8888_Premultiplied The image is stored using a
premultiplied 32-bit byte-ordered RGBA format (8-8-8-8).
+ \value Format_BGR30 The image is stored using a 32-bit BGR format (x-10-10-10).
+ \value Format_A2BGR30_Premultiplied The image is stored using a 32-bit premultiplied ABGR format (2-10-10-10).
+ \value Format_RGB30 The image is stored using a 32-bit RGB format (x-10-10-10).
+ \value Format_A2RGB30_Premultiplied The image is stored using a 32-bit premultiplied ARGB format (2-10-10-10).
\note Drawing into a QImage with QImage::Format_Indexed8 is not
supported.
@@ -708,6 +722,9 @@ bool QImageData::checkForAlphaPixels() const
\note Do not render into ARGB32 images using QPainter. Using
QImage::Format_ARGB32_Premultiplied is significantly faster.
+ \note Formats with more than 8 bit per color channel will only be processed by the raster engine using 8 bit
+ per color.
+
\sa format(), convertToFormat()
*/
@@ -1670,6 +1687,8 @@ void QImage::fill(uint pixel)
#else
pixel |= 0x000000ff;
#endif
+ if (d->format == Format_BGR30 || d->format == Format_RGB30)
+ pixel |= 0xc0000000;
qt_rectfill<uint>(reinterpret_cast<uint*>(d->data), pixel,
0, 0, d->width, d->height, d->bytes_per_line);
@@ -1736,6 +1755,14 @@ void QImage::fill(const QColor &color)
case QImage::Format_RGBA8888_Premultiplied:
fill(ARGB2RGBA(qPremultiply(color.rgba())));
break;
+ case QImage::Format_BGR30:
+ case QImage::Format_A2BGR30_Premultiplied:
+ fill(qConvertArgb32ToA2rgb30<PixelOrderBGR>(color.rgba()));
+ break;
+ case QImage::Format_RGB30:
+ case QImage::Format_A2RGB30_Premultiplied:
+ fill(qConvertArgb32ToA2rgb30<PixelOrderRGB>(color.rgba()));
+ break;
case QImage::Format_RGB16:
fill((uint) qConvertRgb32To16(color.rgba()));
break;
@@ -2142,6 +2169,12 @@ QRgb QImage::pixel(int x, int y) const
case Format_RGBA8888: // Match ARGB32 behavior.
case Format_RGBA8888_Premultiplied:
return RGBA2ARGB(reinterpret_cast<const quint32 *>(s)[x]);
+ case Format_BGR30:
+ case Format_A2BGR30_Premultiplied:
+ return qConvertA2rgb30ToArgb32<PixelOrderBGR>(reinterpret_cast<const quint32 *>(s)[x]);
+ case Format_RGB30:
+ case Format_A2RGB30_Premultiplied:
+ return qConvertA2rgb30ToArgb32<PixelOrderRGB>(reinterpret_cast<const quint32 *>(s)[x]);
case Format_RGB16:
return qConvertRgb16To32(reinterpret_cast<const quint16 *>(s)[x]);
default:
@@ -2232,6 +2265,18 @@ void QImage::setPixel(int x, int y, uint index_or_rgb)
case Format_RGBA8888_Premultiplied:
((uint *)s)[x] = ARGB2RGBA(index_or_rgb);
return;
+ case Format_BGR30:
+ ((uint *)s)[x] = qConvertRgb32ToRgb30<PixelOrderBGR>(index_or_rgb);
+ return;
+ case Format_A2BGR30_Premultiplied:
+ ((uint *)s)[x] = qConvertArgb32ToA2rgb30<PixelOrderBGR>(index_or_rgb);
+ return;
+ case Format_RGB30:
+ ((uint *)s)[x] = qConvertRgb32ToRgb30<PixelOrderRGB>(index_or_rgb);
+ return;
+ case Format_A2RGB30_Premultiplied:
+ ((uint *)s)[x] = qConvertArgb32ToA2rgb30<PixelOrderRGB>(index_or_rgb);
+ return;
case Format_Invalid:
case NImageFormats:
Q_ASSERT(false);
@@ -2959,6 +3004,23 @@ QImage QImage::rgbSwapped_helper() const
}
}
break;
+ case Format_BGR30:
+ case Format_A2BGR30_Premultiplied:
+ case Format_RGB30:
+ case Format_A2RGB30_Premultiplied:
+ res = QImage(d->width, d->height, d->format);
+ QIMAGE_SANITYCHECK_MEMORY(res);
+ for (int i = 0; i < d->height; i++) {
+ uint *q = (uint*)res.scanLine(i);
+ const uint *p = (const uint*)constScanLine(i);
+ const uint *end = p + d->width;
+ while (p < end) {
+ *q = qRgbSwapRgb30(*p);
+ p++;
+ q++;
+ }
+ }
+ break;
default:
res = QImage(d->width, d->height, d->format);
rgbSwapped_generic(d->width, d->height, this, &res, &qPixelLayouts[d->format]);
@@ -3019,6 +3081,19 @@ void QImage::rgbSwapped_inplace()
}
}
break;
+ case Format_BGR30:
+ case Format_A2BGR30_Premultiplied:
+ case Format_RGB30:
+ case Format_A2RGB30_Premultiplied:
+ for (int i = 0; i < d->height; i++) {
+ uint *p = (uint*)scanLine(i);
+ uint *end = p + d->width;
+ while (p < end) {
+ *p = qRgbSwapRgb30(*p);
+ p++;
+ }
+ }
+ break;
default:
rgbSwapped_generic(d->width, d->height, this, this, &qPixelLayouts[d->format]);
break;
@@ -4044,6 +4119,8 @@ bool QImage::hasAlphaChannel() const
|| d->format == Format_ARGB4444_Premultiplied
|| d->format == Format_RGBA8888
|| d->format == Format_RGBA8888_Premultiplied
+ || d->format == Format_A2BGR30_Premultiplied
+ || d->format == Format_A2RGB30_Premultiplied
|| (d->has_alpha_clut && (d->format == Format_Indexed8
|| d->format == Format_Mono
|| d->format == Format_MonoLSB)));
@@ -4069,6 +4146,10 @@ int QImage::bitPlaneCount() const
switch (d->format) {
case QImage::Format_Invalid:
break;
+ case QImage::Format_BGR30:
+ case QImage::Format_RGB30:
+ bpc = 30;
+ break;
case QImage::Format_RGB32:
case QImage::Format_RGBX8888:
bpc = 24;
@@ -4122,6 +4203,10 @@ static QImage rotated90(const QImage &image) {
case QImage::Format_RGBX8888:
case QImage::Format_RGBA8888:
case QImage::Format_RGBA8888_Premultiplied:
+ case QImage::Format_BGR30:
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_RGB30:
+ case QImage::Format_A2RGB30_Premultiplied:
qt_memrotate270(reinterpret_cast<const quint32*>(image.bits()),
w, h, image.bytesPerLine(),
reinterpret_cast<quint32*>(out.bits()),
@@ -4184,6 +4269,10 @@ static QImage rotated270(const QImage &image) {
case QImage::Format_RGBX8888:
case QImage::Format_RGBA8888:
case QImage::Format_RGBA8888_Premultiplied:
+ case QImage::Format_BGR30:
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_RGB30:
+ case QImage::Format_A2RGB30_Premultiplied:
qt_memrotate90(reinterpret_cast<const quint32*>(image.bits()),
w, h, image.bytesPerLine(),
reinterpret_cast<quint32*>(out.bits()),
@@ -4332,6 +4421,12 @@ QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode
case QImage::Format_RGBX8888:
target_format = Format_RGBA8888_Premultiplied;
break;
+ case QImage::Format_BGR30:
+ target_format = Format_A2BGR30_Premultiplied;
+ break;
+ case QImage::Format_RGB30:
+ target_format = Format_A2RGB30_Premultiplied;
+ break;
default:
target_format = Format_ARGB32_Premultiplied;
break;
@@ -4455,8 +4550,21 @@ bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFla
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QImage &i)
{
- dbg.nospace() << "QImage(" << i.size() << ')';
- return dbg.space();
+ QDebugStateSaver saver(dbg);
+ dbg.resetFormat();
+ dbg.nospace();
+ dbg << "QImage(";
+ if (i.isNull()) {
+ dbg << "null";
+ } else {
+ dbg << i.size() << ",format=" << i.format() << ",depth=" << i.depth();
+ if (i.colorCount())
+ dbg << ",colorCount=" << i.colorCount();
+ dbg << ",devicePixelRatio=" << i.devicePixelRatio()
+ << ",bytesPerLine=" << i.bytesPerLine() << ",byteCount=" << i.byteCount();
+ }
+ dbg << ')';
+ return dbg;
}
#endif
@@ -4504,4 +4612,325 @@ QDebug operator<<(QDebug dbg, const QImage &i)
\sa textKeys()
*/
+static const QPixelFormat pixelformats[] = {
+ //QImage::Format_Invalid:
+ QPixelFormat(),
+ //QImage::Format_Mono:
+ QPixelFormat(QPixelFormat::Grayscale,
+ /*RED*/ 1,
+ /*GREEN*/ 0,
+ /*BLUE*/ 0,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 0,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedByte,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_MonoLSB:
+ QPixelFormat(QPixelFormat::Grayscale,
+ /*RED*/ 1,
+ /*GREEN*/ 0,
+ /*BLUE*/ 0,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 0,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedByte,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_Indexed8:
+ QPixelFormat(QPixelFormat::Indexed,
+ /*RED*/ 8,
+ /*GREEN*/ 0,
+ /*BLUE*/ 0,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 0,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedByte,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGB32:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 8,
+ /*GREEN*/ 8,
+ /*BLUE*/ 8,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 8,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_ARGB32:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 8,
+ /*GREEN*/ 8,
+ /*BLUE*/ 8,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 8,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_ARGB32_Premultiplied:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 8,
+ /*GREEN*/ 8,
+ /*BLUE*/ 8,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 8,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGB16:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 5,
+ /*GREEN*/ 6,
+ /*BLUE*/ 5,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 0,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedShort,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_ARGB8565_Premultiplied:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 5,
+ /*GREEN*/ 6,
+ /*BLUE*/ 5,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 8,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGB666:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 6,
+ /*GREEN*/ 6,
+ /*BLUE*/ 6,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 0,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_ARGB6666_Premultiplied:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 6,
+ /*GREEN*/ 6,
+ /*BLUE*/ 6,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 6,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGB555:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 5,
+ /*GREEN*/ 5,
+ /*BLUE*/ 5,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 0,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedShort,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_ARGB8555_Premultiplied:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 5,
+ /*GREEN*/ 5,
+ /*BLUE*/ 5,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 8,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGB888:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 8,
+ /*GREEN*/ 8,
+ /*BLUE*/ 8,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 0,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGB444:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 4,
+ /*GREEN*/ 4,
+ /*BLUE*/ 4,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 0,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedShort,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_ARGB4444_Premultiplied:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 4,
+ /*GREEN*/ 4,
+ /*BLUE*/ 4,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 4,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedShort,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBX8888:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 8,
+ /*GREEN*/ 8,
+ /*BLUE*/ 8,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 8,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedByte,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBA8888:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 8,
+ /*GREEN*/ 8,
+ /*BLUE*/ 8,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 8,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedByte,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBA8888_Premultiplied:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 8,
+ /*GREEN*/ 8,
+ /*BLUE*/ 8,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 8,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedByte,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_BGR30:
+ QPixelFormat(QPixelFormat::BGR,
+ /*RED*/ 10,
+ /*GREEN*/ 10,
+ /*BLUE*/ 10,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 2,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_A2BGR30_Premultiplied:
+ QPixelFormat(QPixelFormat::BGR,
+ /*RED*/ 10,
+ /*GREEN*/ 10,
+ /*BLUE*/ 10,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 2,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGB30:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 10,
+ /*GREEN*/ 10,
+ /*BLUE*/ 10,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 2,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_A2RGB30_Premultiplied:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 10,
+ /*GREEN*/ 10,
+ /*BLUE*/ 10,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 2,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+};
+Q_STATIC_ASSERT(sizeof(pixelformats) / sizeof(*pixelformats) == QImage::NImageFormats);
+
+/*!
+ Returns the QImage::Format as a QPixelFormat
+*/
+QPixelFormat QImage::pixelFormat() const Q_DECL_NOTHROW
+{
+ return toPixelFormat(format());
+}
+
+/*!
+ Converts \a format into a QPixelFormat
+*/
+QPixelFormat QImage::toPixelFormat(QImage::Format format) Q_DECL_NOTHROW
+{
+ Q_ASSERT(static_cast<int>(format) < NImageFormats);
+ return pixelformats[format];
+}
+
+/*!
+ Converts \a format into a QImage::Format
+*/
+QImage::Format QImage::toImageFormat(const QPixelFormat &format) Q_DECL_NOTHROW
+{
+ for (int i = 0; i < NImageFormats; i++) {
+ if (format == pixelformats[i])
+ return Format(i);
+ }
+ return Format_Invalid;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h
index 4326d5dbbc..62f9f5cce2 100644
--- a/src/gui/image/qimage.h
+++ b/src/gui/image/qimage.h
@@ -45,6 +45,7 @@
#include <QtGui/qtransform.h>
#include <QtGui/qpaintdevice.h>
#include <QtGui/qrgb.h>
+#include <QtGui/qpixelformat.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qrect.h>
#include <QtCore/qstring.h>
@@ -123,6 +124,10 @@ public:
Format_Grayscale2,
Format_Grayscale2LSB
#endif
+ Format_BGR30,
+ Format_A2BGR30_Premultiplied,
+ Format_RGB30,
+ Format_A2RGB30_Premultiplied,
#ifndef Q_QDOC
NImageFormats
#endif
@@ -305,6 +310,10 @@ public:
QString text(const QString &key = QString()) const;
void setText(const QString &key, const QString &value);
+ QPixelFormat pixelFormat() const Q_DECL_NOTHROW;
+ static QPixelFormat toPixelFormat(QImage::Format format) Q_DECL_NOTHROW;
+ static QImage::Format toImageFormat(const QPixelFormat &format) Q_DECL_NOTHROW;
+
#if QT_DEPRECATED_SINCE(5, 0)
QT_DEPRECATED inline QString text(const char* key, const char* lang=0) const;
QT_DEPRECATED inline QList<QImageTextKeyLang> textList() const;
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index 629a7c9b69..195b56afbe 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -172,6 +172,35 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
return true;
}
+static void convert_passthrough(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 2) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const quint32 *src_data = (quint32 *) src->data;
+ quint32 *dest_data = (quint32 *) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ const quint32 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = *src_data;
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+template<QImage::Format Format>
+static bool convert_passthrough_inplace(QImageData *data, Qt::ImageConversionFlags)
+{
+ data->format = Format;
+ return true;
+}
+
static void convert_ARGB_to_ARGB_PM(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
Q_ASSERT(src->format == QImage::Format_ARGB32 || src->format == QImage::Format_RGBA8888);
@@ -404,6 +433,292 @@ static bool convert_RGBA_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversio
return true;
}
+template<QtPixelOrder PixelOrder>
+static void convert_RGB_to_RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+
+ Q_ASSERT(src->format == QImage::Format_RGB32 || src->format == QImage::Format_ARGB32);
+ Q_ASSERT(dest->format == QImage::Format_BGR30 || dest->format == QImage::Format_A2BGR30_Premultiplied
+ || dest->format == QImage::Format_RGB30 || dest->format == QImage::Format_A2RGB30_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 2) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const quint32 *src_data = (quint32 *) src->data;
+ quint32 *dest_data = (quint32 *) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ const quint32 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = qConvertRgb32ToRgb30<PixelOrder>(*src_data);
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+template<QtPixelOrder PixelOrder>
+static void convert_RGB30_to_RGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_BGR30 || src->format == QImage::Format_RGB30);
+ Q_ASSERT(dest->format == QImage::Format_RGB32 || dest->format == QImage::Format_ARGB32 || dest->format == QImage::Format_ARGB32_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 2) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const quint32 *src_data = (quint32 *) src->data;
+ quint32 *dest_data = (quint32 *) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ const quint32 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = qConvertA2rgb30ToArgb32<PixelOrder>(*src_data);
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+template<QtPixelOrder PixelOrder>
+static void convert_A2RGB30_PM_to_RGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_A2RGB30_Premultiplied || src->format == QImage::Format_A2BGR30_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_RGB32);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 2) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const quint32 *src_data = (quint32 *) src->data;
+ quint32 *dest_data = (quint32 *) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ const quint32 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = 0xff000000 | qUnpremultiply(qConvertA2rgb30ToArgb32<PixelOrder>(*src_data));
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+template<QtPixelOrder PixelOrder>
+static void convert_ARGB_PM_to_RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_ARGB32_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_BGR30 || dest->format == QImage::Format_RGB30);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 2) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const quint32 *src_data = (quint32 *) src->data;
+ quint32 *dest_data = (quint32 *) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ const quint32 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = qConvertRgb32ToRgb30<PixelOrder>(qUnpremultiply(*src_data));
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+template<QtPixelOrder PixelOrder>
+static void convert_ARGB_to_A2RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_ARGB32_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_A2BGR30_Premultiplied || dest->format == QImage::Format_A2RGB30_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 2) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const quint32 *src_data = (quint32 *) src->data;
+ quint32 *dest_data = (quint32 *) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ const quint32 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = qConvertArgb32ToA2rgb30<PixelOrder>(*src_data);
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+template<QtPixelOrder PixelOrder>
+static void convert_A2RGB30_to_ARGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_A2BGR30_Premultiplied || src->format == QImage::Format_A2RGB30_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_ARGB32_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 2) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const quint32 *src_data = (quint32 *) src->data;
+ quint32 *dest_data = (quint32 *) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ const quint32 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = qConvertA2rgb30ToArgb32<PixelOrder>(*src_data);
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+static inline uint qUnpremultiplyRgb30(uint rgb30)
+{
+ const uint a = rgb30 >> 30;
+ switch (a) {
+ case 0:
+ return 0;
+ case 1: {
+ uint rgb = rgb30 & 0x3fffffff;
+ rgb *= 3;
+ return (a << 30) | rgb;
+ }
+ case 2: {
+ uint rgb = rgb30 & 0x3fffffff;
+ rgb += rgb >> 1;
+ return (a << 30) | rgb;
+ }
+ case 3:
+ return rgb30;
+ }
+ Q_UNREACHABLE();
+ return 0;
+}
+
+static void convert_A2RGB30_PM_to_RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_A2RGB30_Premultiplied || src->format == QImage::Format_A2BGR30_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_RGB30 || dest->format == QImage::Format_BGR30);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 2) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const quint32 *src_data = (quint32 *) src->data;
+ quint32 *dest_data = (quint32 *) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ const quint32 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = 0xc0000000 | qUnpremultiplyRgb30(*src_data);
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+static bool convert_A2RGB30_PM_to_RGB30_inplace(QImageData *data, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(data->format == QImage::Format_A2RGB30_Premultiplied || data->format == QImage::Format_A2BGR30_Premultiplied);
+
+ const int pad = (data->bytes_per_line >> 2) - data->width;
+ uint *rgb_data = (uint *) data->data;
+
+ for (int i = 0; i < data->height; ++i) {
+ const uint *end = rgb_data + data->width;
+ while (rgb_data < end) {
+ *rgb_data = 0xc0000000 | qUnpremultiplyRgb30(*rgb_data);
+ ++rgb_data;
+ }
+ rgb_data += pad;
+ }
+
+ if (data->format == QImage::Format_A2RGB30_Premultiplied)
+ data->format = QImage::Format_RGB30;
+ else
+ data->format = QImage::Format_BGR30;
+ return true;
+}
+
+static void convert_BGR30_to_RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_RGB30 || src->format == QImage::Format_BGR30 ||
+ src->format == QImage::Format_A2RGB30_Premultiplied || src->format == QImage::Format_A2BGR30_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_RGB30 || dest->format == QImage::Format_BGR30 ||
+ dest->format == QImage::Format_A2RGB30_Premultiplied || dest->format == QImage::Format_A2BGR30_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 2) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const quint32 *src_data = (quint32 *) src->data;
+ quint32 *dest_data = (quint32 *) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ const quint32 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = qRgbSwapRgb30(*src_data);
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+static bool convert_BGR30_to_RGB30_inplace(QImageData *data, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(data->format == QImage::Format_RGB30 || data->format == QImage::Format_BGR30 ||
+ data->format == QImage::Format_A2RGB30_Premultiplied || data->format == QImage::Format_A2BGR30_Premultiplied);
+
+ const int pad = (data->bytes_per_line >> 2) - data->width;
+ uint *rgb_data = (uint *) data->data;
+
+ for (int i = 0; i < data->height; ++i) {
+ const uint *end = rgb_data + data->width;
+ while (rgb_data < end) {
+ *rgb_data = qRgbSwapRgb30(*rgb_data);
+ ++rgb_data;
+ }
+ rgb_data += pad;
+ }
+
+ switch (data->format) {
+ case QImage::Format_BGR30:
+ data->format = QImage::Format_RGB30;
+ break;
+ case QImage::Format_A2BGR30_Premultiplied:
+ data->format = QImage::Format_A2RGB30_Premultiplied;
+ break;
+ case QImage::Format_RGB30:
+ data->format = QImage::Format_BGR30;
+ break;
+ case QImage::Format_A2RGB30_Premultiplied:
+ data->format = QImage::Format_A2BGR30_Premultiplied;
+ break;
+ default:
+ Q_UNREACHABLE();
+ data->format = QImage::Format_Invalid;
+ return false;
+ }
+ return true;
+}
+
static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversionFlags)
{
Q_ASSERT(data->format == QImage::Format_Indexed8);
@@ -1557,7 +1872,7 @@ static void convert_Mono_to_Indexed8(QImageData *dest, const QImageData *src, Qt
Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormats] =
{
{
- 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,
@@ -1578,7 +1893,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_Mono
{
@@ -1600,7 +1915,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_MonoLSB
{
@@ -1622,7 +1937,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_Indexed8
{
@@ -1644,7 +1959,11 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
convert_RGB_to_RGBA,
convert_RGB_to_RGBA,
- convert_RGB_to_RGBA
+ convert_RGB_to_RGBA,
+ convert_RGB_to_RGB30<PixelOrderBGR>,
+ convert_RGB_to_RGB30<PixelOrderBGR>,
+ convert_RGB_to_RGB30<PixelOrderRGB>,
+ convert_RGB_to_RGB30<PixelOrderRGB>,
}, // Format_RGB32
{
@@ -1667,6 +1986,10 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_ARGB_to_RGBx,
convert_ARGB_to_RGBA,
convert_ARGB_to_RGBA_PM,
+ convert_RGB_to_RGB30<PixelOrderBGR>,
+ 0,
+ convert_RGB_to_RGB30<PixelOrderRGB>,
+ 0,
}, // Format_ARGB32
{
@@ -1689,6 +2012,10 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_ARGB_PM_to_RGBx,
convert_ARGB_PM_to_RGBA,
convert_ARGB_to_RGBA,
+ convert_ARGB_PM_to_RGB30<PixelOrderBGR>,
+ convert_ARGB_to_A2RGB30<PixelOrderBGR>,
+ convert_ARGB_PM_to_RGB30<PixelOrderRGB>,
+ convert_ARGB_to_A2RGB30<PixelOrderRGB>,
}, // Format_ARGB32_Premultiplied
{
@@ -1710,7 +2037,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_RGB16
{
@@ -1732,7 +2059,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_ARGB8565_Premultiplied
{
@@ -1754,7 +2081,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_RGB666
{
@@ -1776,7 +2103,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_ARGB6666_Premultiplied
{
@@ -1798,7 +2125,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_RGB555
{
@@ -1820,7 +2147,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_ARGB8555_Premultiplied
{
@@ -1842,7 +2169,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_RGB888
{
@@ -1864,7 +2191,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_RGB444
{
@@ -1885,7 +2212,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_ARGB4444_Premultiplied
{
0,
@@ -1907,6 +2234,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
mask_alpha_converter_RGBx,
mask_alpha_converter_RGBx,
+ 0, 0, 0, 0
}, // Format_RGBX8888
{
0,
@@ -1933,6 +2261,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0
#endif
+ 0, 0, 0, 0
}, // Format_RGBA8888
{
@@ -1961,19 +2290,121 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0
#endif
- } // Format_RGBA8888_Premultiplied
+ 0, 0, 0, 0
+ }, // Format_RGBA8888_Premultiplied
+
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_RGB30_to_RGB<PixelOrderBGR>,
+ convert_RGB30_to_RGB<PixelOrderBGR>,
+ convert_RGB30_to_RGB<PixelOrderBGR>,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_passthrough,
+ convert_BGR30_to_RGB30,
+ convert_BGR30_to_RGB30
+ }, // Format_BGR30
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_A2RGB30_PM_to_RGB<PixelOrderBGR>,
+ 0,
+ convert_A2RGB30_to_ARGB<PixelOrderBGR>,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_A2RGB30_PM_to_RGB30,
+ 0,
+ 0,
+ convert_BGR30_to_RGB30
+ }, // Format_BGR30A2_Premultiplied
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_RGB30_to_RGB<PixelOrderRGB>,
+ convert_RGB30_to_RGB<PixelOrderRGB>,
+ convert_RGB30_to_RGB<PixelOrderRGB>,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_BGR30_to_RGB30,
+ convert_BGR30_to_RGB30,
+ 0,
+ 0,
+ convert_passthrough,
+ }, // Format_RGB30
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_A2RGB30_PM_to_RGB<PixelOrderRGB>,
+ 0,
+ convert_A2RGB30_to_ARGB<PixelOrderRGB>,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_BGR30_to_RGB30,
+ convert_A2RGB30_PM_to_RGB30,
+ 0,
+ }, // Format_RGB30A2_Premultiplied
};
InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats] =
{
{
- 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
}, // Format_Mono
{
- 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
}, // Format_MonoLSB
{
0,
@@ -1994,7 +2425,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
- 0,
+ 0, 0, 0, 0, 0
}, // Format_Indexed8
{
0,
@@ -2015,7 +2446,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
- 0,
+ 0, 0, 0, 0, 0
}, // Format_RGB32
{
0,
@@ -2040,7 +2471,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
convert_ARGB_to_RGBA_inplace,
- 0,
+ 0, 0, 0, 0, 0
}, // Format_ARGB32
{
0,
@@ -2061,34 +2492,35 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
- convert_ARGB_to_RGBA_inplace
+ convert_ARGB_to_RGBA_inplace,
+ 0, 0, 0, 0
}, // Format_ARGB32_Premultiplied
{
- 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
}, // Format_RGB16
{
- 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
}, // Format_ARGB8565_Premultiplied
{
- 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
}, // Format_RGB666
{
- 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
}, // Format_ARGB6666_Premultiplied
{
- 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
}, // Format_RGB555
{
- 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
}, // Format_ARGB8555_Premultiplied
{
- 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
}, // Format_RGB888
{
- 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
}, // Format_RGB444
{
- 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
}, // Format_ARGB4444_Premultiplied
{
0,
@@ -2108,8 +2540,9 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
- 0,
- 0,
+ convert_passthrough_inplace<QImage::Format_RGBA8888>,
+ convert_passthrough_inplace<QImage::Format_RGBA8888_Premultiplied>,
+ 0, 0, 0, 0
}, // Format_RGBX8888
{
0,
@@ -2131,6 +2564,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
+ 0, 0, 0, 0
}, // Format_RGBA8888
{
0,
@@ -2152,7 +2586,108 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
- } // Format_RGBA8888_Premultiplied
+ 0, 0, 0, 0
+ }, // Format_RGBA8888_Premultiplied
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_passthrough_inplace<QImage::Format_A2BGR30_Premultiplied>,
+ convert_BGR30_to_RGB30_inplace,
+ convert_BGR30_to_RGB30_inplace
+ }, // Format_BGR30
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_A2RGB30_PM_to_RGB30_inplace,
+ 0,
+ 0,
+ convert_BGR30_to_RGB30_inplace
+ }, // Format_BGR30A2_Premultiplied
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_BGR30_to_RGB30_inplace,
+ convert_BGR30_to_RGB30_inplace,
+ 0,
+ convert_passthrough_inplace<QImage::Format_A2RGB30_Premultiplied>
+ }, // Format_RGB30
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_BGR30_to_RGB30_inplace,
+ convert_A2RGB30_PM_to_RGB30_inplace,
+ 0
+ }, // Format_RGB30A2_Premultiplied
};
void qInitImageConversions()
@@ -2174,9 +2709,15 @@ void qInitImageConversions()
#endif
#ifdef QT_COMPILER_SUPPORTS_MIPS_DSPR2
- extern bool convert_ARGB_to_ARGB_PM_inplace_mips_dspr2(QImageData *data, Qt::ImageConversionFlags);
- inplace_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_inplace_mips_dspr2;
- return;
+ if (qCpuHasFeature(DSPR2)) {
+ extern bool convert_ARGB_to_ARGB_PM_inplace_mips_dspr2(QImageData *data, Qt::ImageConversionFlags);
+ qimage_inplace_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_inplace_mips_dspr2;
+
+ extern void convert_RGB888_to_RGB32_mips_dspr2(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
+ qimage_converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_mips_dspr2;
+ qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_mips_dspr2;
+ qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32_Premultiplied] = convert_RGB888_to_RGB32_mips_dspr2;
+ }
#endif
}
diff --git a/src/gui/image/qimage_mips_dspr2.cpp b/src/gui/image/qimage_mips_dspr2.cpp
index a1c40a16df..f61a2262d2 100644
--- a/src/gui/image/qimage_mips_dspr2.cpp
+++ b/src/gui/image/qimage_mips_dspr2.cpp
@@ -66,4 +66,24 @@ bool convert_ARGB_to_ARGB_PM_inplace_mips_dspr2(QImageData *data, Qt::ImageConve
return true;
}
+extern "C" void qt_convert_rgb888_to_rgb32_mips_dspr2_asm(uint *dst, const uchar *src, int len);
+
+void convert_RGB888_to_RGB32_mips_dspr2(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_RGB888);
+ Q_ASSERT(dest->format == QImage::Format_RGB32 || dest->format == QImage::Format_ARGB32 || dest->format == QImage::Format_ARGB32_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const uchar *src_data = (const uchar*) src->data;
+ quint32 *dest_data = (quint32*) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ qt_convert_rgb888_to_rgb32_mips_dspr2_asm(dest_data, src_data, src->width);
+ src_data += src->bytes_per_line;
+ dest_data = (quint32*) ((uchar*) dest_data + dest->bytes_per_line);
+ }
+}
+
QT_END_NAMESPACE
+
diff --git a/src/gui/image/qimage_mips_dspr2_asm.S b/src/gui/image/qimage_mips_dspr2_asm.S
index 1f03b72dd4..df626586dc 100644
--- a/src/gui/image/qimage_mips_dspr2_asm.S
+++ b/src/gui/image/qimage_mips_dspr2_asm.S
@@ -205,3 +205,95 @@ LEAF_MIPS_DSPR2(premultiply_argb_inplace_mips_asm)
END(premultiply_argb_inplace_mips_asm)
+
+LEAF_MIPS_DSPR2(qt_convert_rgb888_to_rgb32_mips_dspr2_asm)
+/*
+ * Parameters:
+ * a0 - dst *a8r8g8b8
+ * a1 - src *r8g8b8
+ * a2 - len
+ *
+ * R G B r g b R G B r g b R G B r g b . . . -- input
+ * ------- ------- ------- ------- -------
+ * _ R G B _ r g b _ R G B _ r g b _ R G . . -- output
+ *
+ * Register usage:
+ * a2 - tail (len % 4) == (len & 0x3)
+ * t0 - batches (len / 4) == (len >> 2)
+ * t1-t7, s1-s3 - temporary
+ */
+
+ srl t0, a2, 2 /* batches = len / 4 */
+ andi a2, a2, 0x3 /* tail = len % 4 */
+
+ beqz t0, 5f /* if !batches: tail */
+ lui t7, 0xff00 /* [FF 00 00 00] */
+ SAVE_REGS_ON_STACK 8, s1, s2, s3, s0, v0, v1
+
+1: pref 4, 0 (a1) /* hint: read-streamed */
+ pref 5, 0 (a0) /* hint: prepare-write */
+ addiu t0, t0, -1 /* batches-- */
+
+ lbu t1, 0 (a1) /* [__ __ __ R1] */
+ lbu t2, 1 (a1) /* [__ __ __ G1] */
+ lbu t3, 2 (a1) /* [__ __ __ B1] */
+
+ lbu t4, 3 (a1) /* [__ __ __ r2] */
+ lbu t5, 4 (a1) /* [__ __ __ g2] */
+ lbu t6, 5 (a1) /* [__ __ __ b2] */
+
+ lbu s1, 6 (a1) /* [__ __ __ R3] */
+ lbu s2, 7 (a1) /* [__ __ __ G3] */
+ lbu s3, 8 (a1) /* [__ __ __ B3] */
+
+ lbu s0, 9 (a1) /* [__ __ __ r4] */
+ lbu v0, 10 (a1) /* [__ __ __ g4] */
+ lbu v1, 11 (a1) /* [__ __ __ b4] */
+
+ append t1, t2, 8 /* [__ __ R1 G1] */
+ append t4, t5, 8 /* [__ __ r2 g2] */
+ append s1, s2, 8 /* [__ __ R3 G3] */
+ append s0, v0, 8 /* [__ __ r4 g4] */
+ append t1, t3, 8 /* [__ R1 G1 B1] */
+ append t4, t6, 8 /* [__ r2 g2 b2] */
+ append s1, s3, 8 /* [__ R3 G4 B3] */
+ append s0, v1, 8 /* [__ r4 g4 b4] */
+ or t1, t1, t7 /* [FF R1 G1 B1] */
+ or t4, t4, t7 /* [FF r2 g2 b2] */
+ or s1, s1, t7 /* [FF R3 G3 B3] */
+ or s0, s0, t7 /* [FF r4 g4 b4] */
+
+ sw t1, 0 (a0)
+ sw t4, 4 (a0)
+ sw s1, 8 (a0)
+ sw s0, 12 (a0)
+
+ addiu a1, a1, 12 /* src += 4*3 */
+ bnez t0, 1b /* if batches: loop */
+ addiu a0, a0, 16 /* dst += 4 */
+
+ RESTORE_REGS_FROM_STACK 8, s1, s2, s3, s0, v0, v1
+
+ /* handle remaining "tail" (a2) items */
+5: beqz a2, 0f
+ lui t0, 0xff00 /* [FF __ __ __] */
+
+1: lbu t1, 0 (a1) /* [__ __ __ RR] */
+ lbu t2, 1 (a1) /* [__ __ __ GG] */
+ lbu t3, 2 (a1) /* [__ __ __ BB] */
+ sll t1, t1, 16 /* [__ RR __ __] */
+ sll t2, t2, 8 /* [__ __ GG __] */
+ or t0, t0, t1 /* [FF RR __ __] */
+ or t2, t2, t3 /* [__ __ GG BB] */
+ addi a2, a2, -1 /* len-- */
+ or t0, t0, t2 /* [FF RR GG BB] */
+ addiu a1, a1, 3 /* src += 3 */
+ sw t0, 0 (a0)
+ addiu a0, a0, 4 /* dst++ */
+ bnez a2, 1b /* if tail: loop */
+ lui t0, 0xff00 /* [FF __ __ __] */
+
+0: jr ra
+ nop
+
+END(qt_convert_rgb888_to_rgb32_mips_dspr2_asm)
diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h
index 81730b92f2..a22e207812 100644
--- a/src/gui/image/qimage_p.h
+++ b/src/gui/image/qimage_p.h
@@ -130,7 +130,7 @@ inline int qt_depthForFormat(QImage::Format format)
switch(format) {
case QImage::Format_Invalid:
case QImage::NImageFormats:
- Q_ASSERT(false);
+ Q_UNREACHABLE();
case QImage::Format_Mono:
case QImage::Format_MonoLSB:
depth = 1;
@@ -144,6 +144,10 @@ inline int qt_depthForFormat(QImage::Format format)
case QImage::Format_RGBX8888:
case QImage::Format_RGBA8888:
case QImage::Format_RGBA8888_Premultiplied:
+ case QImage::Format_BGR30:
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_RGB30:
+ case QImage::Format_A2RGB30_Premultiplied:
depth = 32;
break;
case QImage::Format_RGB555:
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index a10198a006..d3edf40acc 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -125,7 +125,6 @@
#include <qimageiohandler.h>
#include <qlist.h>
#include <qrect.h>
-#include <qset.h>
#include <qsize.h>
#include <qcolor.h>
#include <qvariant.h>
@@ -568,7 +567,7 @@ bool QImageReaderPrivate::initHandler()
// check some preconditions
if (!device || (!deleteDevice && !device->isOpen() && !device->open(QIODevice::ReadOnly))) {
imageReaderError = QImageReader::DeviceError;
- errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "Invalid device"));
+ errorString = QImageReader::tr("Invalid device");
return false;
}
@@ -595,7 +594,7 @@ bool QImageReaderPrivate::initHandler()
if (!device->isOpen()) {
imageReaderError = QImageReader::FileNotFoundError;
- errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "File not found"));
+ errorString = QImageReader::tr("File not found");
file->setFileName(fileName); // restore the old file name
return false;
}
@@ -604,7 +603,7 @@ bool QImageReaderPrivate::initHandler()
// assign a handler
if (!handler && (handler = createReadHandlerHelper(device, format, autoDetectImageFormat, ignoresFormatAndExtension)) == 0) {
imageReaderError = QImageReader::UnsupportedFormatError;
- errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "Unsupported image format"));
+ errorString = QImageReader::tr("Unsupported image format");
return false;
}
return true;
@@ -1191,7 +1190,7 @@ bool QImageReader::read(QImage *image)
// read the image
if (!d->handler->read(image)) {
d->imageReaderError = InvalidDataError;
- d->errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "Unable to read image data"));
+ d->errorString = QImageReader::tr("Unable to read image data");
return false;
}
@@ -1384,7 +1383,7 @@ QImageReader::ImageReaderError QImageReader::error() const
QString QImageReader::errorString() const
{
if (d->errorString.isEmpty())
- return QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "Unknown error"));
+ return QImageReader::tr("Unknown error");
return d->errorString;
}
@@ -1445,11 +1444,11 @@ QByteArray QImageReader::imageFormat(QIODevice *device)
#ifndef QT_NO_IMAGEFORMATPLUGIN
void supportedImageHandlerFormats(QFactoryLoader *loader,
QImageIOPlugin::Capability cap,
- QSet<QByteArray> *result);
+ QList<QByteArray> *result);
void supportedImageHandlerMimeTypes(QFactoryLoader *loader,
QImageIOPlugin::Capability cap,
- QSet<QByteArray> *result);
+ QList<QByteArray> *result);
#endif
/*!
@@ -1482,7 +1481,7 @@ void supportedImageHandlerMimeTypes(QFactoryLoader *loader,
QList<QByteArray> QImageReader::supportedImageFormats()
{
- QSet<QByteArray> formats;
+ QList<QByteArray> formats;
for (int i = 0; i < _qt_NumFormats; ++i)
formats << _qt_BuiltInFormats[i].extension;
@@ -1490,12 +1489,9 @@ QList<QByteArray> QImageReader::supportedImageFormats()
supportedImageHandlerFormats(loader(), QImageIOPlugin::CanRead, &formats);
#endif // QT_NO_IMAGEFORMATPLUGIN
- QList<QByteArray> sortedFormats;
- for (QSet<QByteArray>::ConstIterator it = formats.constBegin(); it != formats.constEnd(); ++it)
- sortedFormats << *it;
-
- std::sort(sortedFormats.begin(), sortedFormats.end());
- return sortedFormats;
+ std::sort(formats.begin(), formats.end());
+ formats.erase(std::unique(formats.begin(), formats.end()), formats.end());
+ return formats;
}
/*!
@@ -1509,7 +1505,7 @@ QList<QByteArray> QImageReader::supportedImageFormats()
QList<QByteArray> QImageReader::supportedMimeTypes()
{
- QSet<QByteArray> mimeTypes;
+ QList<QByteArray> mimeTypes;
for (int i = 0; i < _qt_NumFormats; ++i)
mimeTypes << _qt_BuiltInFormats[i].mimeType;
@@ -1517,12 +1513,9 @@ QList<QByteArray> QImageReader::supportedMimeTypes()
supportedImageHandlerMimeTypes(loader(), QImageIOPlugin::CanRead, &mimeTypes);
#endif // QT_NO_IMAGEFORMATPLUGIN
- QList<QByteArray> sortedMimeTypes;
- for (QSet<QByteArray>::ConstIterator it = mimeTypes.constBegin(); it != mimeTypes.constEnd(); ++it)
- sortedMimeTypes << *it;
-
- std::sort(sortedMimeTypes.begin(), sortedMimeTypes.end());
- return sortedMimeTypes;
+ std::sort(mimeTypes.begin(), mimeTypes.end());
+ mimeTypes.erase(std::unique(mimeTypes.begin(), mimeTypes.end()), mimeTypes.end());
+ return mimeTypes;
}
QT_END_NAMESPACE
diff --git a/src/gui/image/qimagereader.h b/src/gui/image/qimagereader.h
index 4f3c93af7d..8409545079 100644
--- a/src/gui/image/qimagereader.h
+++ b/src/gui/image/qimagereader.h
@@ -43,6 +43,7 @@
#define QIMAGEREADER_H
#include <QtCore/qbytearray.h>
+#include <QtCore/qcoreapplication.h>
#include <QtGui/qimage.h>
#include <QtGui/qimageiohandler.h>
@@ -58,6 +59,7 @@ class QStringList;
class QImageReaderPrivate;
class Q_GUI_EXPORT QImageReader
{
+ Q_DECLARE_TR_FUNCTIONS(QImageReader)
public:
enum ImageReaderError {
UnknownError,
diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp
index c12dbb6544..c003e56573 100644
--- a/src/gui/image/qimagewriter.cpp
+++ b/src/gui/image/qimagewriter.cpp
@@ -279,7 +279,7 @@ QImageWriterPrivate::QImageWriterPrivate(QImageWriter *qq)
compression = 0;
gamma = 0.0;
imageWriterError = QImageWriter::UnknownError;
- errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageWriter, "Unknown error"));
+ errorString = QImageWriter::tr("Unknown error");
q = qq;
}
@@ -288,19 +288,19 @@ bool QImageWriterPrivate::canWriteHelper()
{
if (!device) {
imageWriterError = QImageWriter::DeviceError;
- errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageWriter, "Device is not set"));
+ errorString = QImageWriter::tr("Device is not set");
return false;
}
if (!device->isOpen())
device->open(QIODevice::WriteOnly);
if (!device->isWritable()) {
imageWriterError = QImageWriter::DeviceError;
- errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageWriter, "Device not writable"));
+ errorString = QImageWriter::tr("Device not writable");
return false;
}
if (!handler && (handler = createWriteHandlerHelper(device, format)) == 0) {
imageWriterError = QImageWriter::UnsupportedFormatError;
- errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageWriter, "Unsupported image format"));
+ errorString = QImageWriter::tr("Unsupported image format");
return false;
}
return true;
@@ -667,7 +667,7 @@ bool QImageWriter::supportsOption(QImageIOHandler::ImageOption option) const
{
if (!d->handler && (d->handler = createWriteHandlerHelper(d->device, d->format)) == 0) {
d->imageWriterError = QImageWriter::UnsupportedFormatError;
- d->errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageWriter, "Unsupported image format"));
+ d->errorString = QImageWriter::tr("Unsupported image format");
return false;
}
@@ -678,7 +678,7 @@ bool QImageWriter::supportsOption(QImageIOHandler::ImageOption option) const
#ifndef QT_NO_IMAGEFORMATPLUGIN
void supportedImageHandlerFormats(QFactoryLoader *loader,
QImageIOPlugin::Capability cap,
- QSet<QByteArray> *result)
+ QList<QByteArray> *result)
{
typedef QMultiMap<int, QString> PluginKeyMap;
typedef PluginKeyMap::const_iterator PluginKeyMapConstIterator;
@@ -687,6 +687,7 @@ void supportedImageHandlerFormats(QFactoryLoader *loader,
const PluginKeyMapConstIterator cend = keyMap.constEnd();
int i = -1;
QImageIOPlugin *plugin = 0;
+ result->reserve(result->size() + keyMap.size());
for (PluginKeyMapConstIterator it = keyMap.constBegin(); it != cend; ++it) {
if (it.key() != i) {
i = it.key();
@@ -694,13 +695,13 @@ void supportedImageHandlerFormats(QFactoryLoader *loader,
}
const QByteArray key = it.value().toLatin1();
if (plugin && (plugin->capabilities(0, key) & cap) != 0)
- result->insert(key);
+ result->append(key);
}
}
void supportedImageHandlerMimeTypes(QFactoryLoader *loader,
QImageIOPlugin::Capability cap,
- QSet<QByteArray> *result)
+ QList<QByteArray> *result)
{
QList<QJsonObject> metaDataList = loader->metaData();
@@ -713,7 +714,7 @@ void supportedImageHandlerMimeTypes(QFactoryLoader *loader,
const int keyCount = keys.size();
for (int k = 0; k < keyCount; ++k) {
if (plugin && (plugin->capabilities(0, keys.at(k).toString().toLatin1()) & cap) != 0)
- result->insert(mimeTypes.at(k).toString().toLatin1());
+ result->append(mimeTypes.at(k).toString().toLatin1());
}
}
}
@@ -746,7 +747,7 @@ void supportedImageHandlerMimeTypes(QFactoryLoader *loader,
*/
QList<QByteArray> QImageWriter::supportedImageFormats()
{
- QSet<QByteArray> formats;
+ QList<QByteArray> formats;
#ifndef QT_NO_IMAGEFORMAT_BMP
formats << "bmp";
#endif
@@ -770,12 +771,9 @@ QList<QByteArray> QImageWriter::supportedImageFormats()
supportedImageHandlerFormats(loader(), QImageIOPlugin::CanWrite, &formats);
#endif // QT_NO_IMAGEFORMATPLUGIN
- QList<QByteArray> sortedFormats;
- for (QSet<QByteArray>::ConstIterator it = formats.constBegin(); it != formats.constEnd(); ++it)
- sortedFormats << *it;
-
- std::sort(sortedFormats.begin(), sortedFormats.end());
- return sortedFormats;
+ std::sort(formats.begin(), formats.end());
+ formats.erase(std::unique(formats.begin(), formats.end()), formats.end());
+ return formats;
}
/*!
@@ -788,7 +786,7 @@ QList<QByteArray> QImageWriter::supportedImageFormats()
*/
QList<QByteArray> QImageWriter::supportedMimeTypes()
{
- QSet<QByteArray> mimeTypes;
+ QList<QByteArray> mimeTypes;
#ifndef QT_NO_IMAGEFORMAT_BMP
mimeTypes << "image/bmp";
#endif
@@ -814,12 +812,9 @@ QList<QByteArray> QImageWriter::supportedMimeTypes()
supportedImageHandlerMimeTypes(loader(), QImageIOPlugin::CanWrite, &mimeTypes);
#endif // QT_NO_IMAGEFORMATPLUGIN
- QList<QByteArray> sortedMimeTypes;
- for (QSet<QByteArray>::ConstIterator it = mimeTypes.constBegin(); it != mimeTypes.constEnd(); ++it)
- sortedMimeTypes << *it;
-
- std::sort(sortedMimeTypes.begin(), sortedMimeTypes.end());
- return sortedMimeTypes;
+ std::sort(mimeTypes.begin(), mimeTypes.end());
+ mimeTypes.erase(std::unique(mimeTypes.begin(), mimeTypes.end()), mimeTypes.end());
+ return mimeTypes;
}
QT_END_NAMESPACE
diff --git a/src/gui/image/qimagewriter.h b/src/gui/image/qimagewriter.h
index 3f5cf9c454..024ad3aa5a 100644
--- a/src/gui/image/qimagewriter.h
+++ b/src/gui/image/qimagewriter.h
@@ -43,6 +43,7 @@
#define QIMAGEWRITER_H
#include <QtCore/qbytearray.h>
+#include <QtCore/qcoreapplication.h>
#include <QtCore/qlist.h>
#include <QtGui/qimageiohandler.h>
@@ -55,6 +56,7 @@ class QImage;
class QImageWriterPrivate;
class Q_GUI_EXPORT QImageWriter
{
+ Q_DECLARE_TR_FUNCTIONS(QImageWriter)
public:
enum ImageWriterError {
UnknownError,
diff --git a/src/gui/image/qjpeghandler.cpp b/src/gui/image/qjpeghandler.cpp
index 5008b1982b..c1d3ff9a85 100644
--- a/src/gui/image/qjpeghandler.cpp
+++ b/src/gui/image/qjpeghandler.cpp
@@ -856,6 +856,7 @@ bool QJpegHandlerPrivate::read(QImage *image)
Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_neon(quint32 *dst, const uchar *src, int len);
Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_ssse3(quint32 *dst, const uchar *src, int len);
+extern "C" void qt_convert_rgb888_to_rgb32_mips_dspr2_asm(quint32 *dst, const uchar *src, int len);
QJpegHandler::QJpegHandler()
: d(new QJpegHandlerPrivate(this))
@@ -874,6 +875,11 @@ QJpegHandler::QJpegHandler()
rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_ssse3;
}
#endif // QT_COMPILER_SUPPORTS_SSSE3
+#if defined(QT_COMPILER_SUPPORTS_MIPS_DSPR2)
+ if (qCpuHasFeature(DSPR2)) {
+ rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_mips_dspr2_asm;
+ }
+#endif // QT_COMPILER_SUPPORTS_DSPR2
}
QJpegHandler::~QJpegHandler()
diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp
index ec89b405b5..807746a26e 100644
--- a/src/gui/image/qpicture.cpp
+++ b/src/gui/image/qpicture.cpp
@@ -118,7 +118,7 @@ void qt_format_text(const QFont &fnt, const QRectF &_r,
*/
const char *qt_mfhdr_tag = "QPIC"; // header tag
-static const quint16 mfhdr_maj = 11; // major version #
+static const quint16 mfhdr_maj = QDataStream::Qt_DefaultCompiledVersion; // major version #
static const quint16 mfhdr_min = 0; // minor version #
/*!
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index c6d8d19bb1..2d41ca7e24 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -1511,7 +1511,8 @@ QBitmap QPixmap::mask() const
return QBitmap();
const QImage img = toImage();
- const QImage image = (img.depth() < 32 ? img.convertToFormat(QImage::Format_ARGB32_Premultiplied) : img);
+ 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();
@@ -1723,8 +1724,19 @@ QPlatformPixmap* QPixmap::handle() const
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QPixmap &r)
{
- dbg.nospace() << "QPixmap(" << r.size() << ')';
- return dbg.space();
+ QDebugStateSaver saver(dbg);
+ dbg.resetFormat();
+ dbg.nospace();
+ dbg << "QPixmap(";
+ if (r.isNull()) {
+ dbg << "null";
+ } else {
+ dbg << r.size() << ",depth=" << r.depth()
+ << ",devicePixelRatio=" << r.devicePixelRatio()
+ << ",cacheKey=" << showbase << hex << r.cacheKey() << dec << noshowbase;
+ }
+ dbg << ')';
+ return dbg;
}
#endif
diff --git a/src/gui/image/qppmhandler.cpp b/src/gui/image/qppmhandler.cpp
index 39f63a620c..64eaf7f19e 100644
--- a/src/gui/image/qppmhandler.cpp
+++ b/src/gui/image/qppmhandler.cpp
@@ -275,6 +275,8 @@ static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QBy
case QImage::Format_RGB888:
case QImage::Format_RGB444:
case QImage::Format_RGBX8888:
+ case QImage::Format_BGR30:
+ case QImage::Format_RGB30:
image = image.convertToFormat(QImage::Format_RGB32);
break;
case QImage::Format_ARGB8565_Premultiplied:
@@ -283,6 +285,8 @@ static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QBy
case QImage::Format_ARGB4444_Premultiplied:
case QImage::Format_RGBA8888:
case QImage::Format_RGBA8888_Premultiplied:
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_A2RGB30_Premultiplied:
image = image.convertToFormat(QImage::Format_ARGB32);
break;
default:
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
index e9e4a1d818..2aeea6288b 100644
--- a/src/gui/kernel/kernel.pri
+++ b/src/gui/kernel/kernel.pri
@@ -68,11 +68,10 @@ HEADERS += \
kernel/qplatformservices.h \
kernel/qplatformscreenpageflipper.h \
kernel/qplatformsystemtrayicon.h \
- kernel/qplatformsessionmanager.h
+ kernel/qplatformsessionmanager.h \
+ kernel/qpixelformat.h
SOURCES += \
- kernel/qclipboard_qpa.cpp \
- kernel/qcursor_qpa.cpp \
kernel/qgenericpluginfactory.cpp \
kernel/qgenericplugin.cpp \
kernel/qwindowsysteminterface.cpp \
@@ -109,7 +108,6 @@ SOURCES += \
kernel/qinputmethod.cpp \
kernel/qkeysequence.cpp \
kernel/qkeymapper.cpp \
- kernel/qkeymapper_qpa.cpp \
kernel/qpalette.cpp \
kernel/qguivariant.cpp \
kernel/qscreen.cpp \
@@ -120,9 +118,10 @@ SOURCES += \
kernel/qplatformdialoghelper.cpp \
kernel/qplatformservices.cpp \
kernel/qplatformscreenpageflipper.cpp \
- kernel/qplatformsystemtrayicon_qpa.cpp \
+ kernel/qplatformsystemtrayicon.cpp \
kernel/qplatformsessionmanager.cpp \
- kernel/qplatformmenu.cpp
+ kernel/qplatformmenu.cpp \
+ kernel/qpixelformat.cpp
contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles2) {
HEADERS += \
diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp
index 3c2d36ce86..672eb9eb65 100644
--- a/src/gui/kernel/qclipboard.cpp
+++ b/src/gui/kernel/qclipboard.cpp
@@ -50,6 +50,10 @@
#include "qimage.h"
#include "qtextcodec.h"
+#include "private/qguiapplication_p.h"
+#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformclipboard.h>
+
QT_BEGIN_NAMESPACE
/*!
@@ -438,6 +442,12 @@ void QClipboard::setPixmap(const QPixmap &pixmap, Mode mode)
\sa setMimeData()
*/
+const QMimeData* QClipboard::mimeData(Mode mode) const
+{
+ QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard();
+ if (!clipboard->supportsMode(mode)) return 0;
+ return clipboard->mimeData(mode);
+}
/*!
\fn void QClipboard::setMimeData(QMimeData *src, Mode mode)
@@ -458,6 +468,13 @@ void QClipboard::setPixmap(const QPixmap &pixmap, Mode mode)
\sa mimeData()
*/
+void QClipboard::setMimeData(QMimeData* src, Mode mode)
+{
+ QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard();
+ if (!clipboard->supportsMode(mode)) return;
+
+ clipboard->setMimeData(src,mode);
+}
/*!
\fn void QClipboard::clear(Mode mode)
@@ -472,7 +489,10 @@ void QClipboard::setPixmap(const QPixmap &pixmap, Mode mode)
\sa QClipboard::Mode, supportsSelection()
*/
-
+void QClipboard::clear(Mode mode)
+{
+ setMimeData(0, mode);
+}
/*!
Returns \c true if the clipboard supports mouse selection; otherwise
@@ -527,6 +547,11 @@ bool QClipboard::ownsFindBuffer() const
Returns \c true if the clipboard supports the clipboard mode speacified by \a mode;
otherwise returns \c false.
*/
+bool QClipboard::supportsMode(Mode mode) const
+{
+ QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard();
+ return clipboard->supportsMode(mode);
+}
/*!
\internal
@@ -534,6 +559,11 @@ bool QClipboard::ownsFindBuffer() const
Returns \c true if the clipboard supports the clipboard data speacified by \a mode;
otherwise returns \c false.
*/
+bool QClipboard::ownsMode(Mode mode) const
+{
+ QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard();
+ return clipboard->ownsMode(mode);
+}
/*!
\internal
diff --git a/src/gui/kernel/qclipboard_qpa.cpp b/src/gui/kernel/qclipboard_qpa.cpp
deleted file mode 100644
index ff8a210cba..0000000000
--- a/src/gui/kernel/qclipboard_qpa.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qclipboard.h"
-
-#ifndef QT_NO_CLIPBOARD
-
-#include "qmimedata.h"
-#include "private/qguiapplication_p.h"
-#include <qpa/qplatformclipboard.h>
-#include <qpa/qplatformintegration.h>
-
-QT_BEGIN_NAMESPACE
-
-QT_USE_NAMESPACE
-
-void QClipboard::clear(Mode mode)
-{
- setMimeData(0, mode);
-}
-
-const QMimeData* QClipboard::mimeData(Mode mode) const
-{
- QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard();
- if (!clipboard->supportsMode(mode)) return 0;
- return clipboard->mimeData(mode);
-}
-
-void QClipboard::setMimeData(QMimeData* src, Mode mode)
-{
- QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard();
- if (!clipboard->supportsMode(mode)) return;
-
- clipboard->setMimeData(src,mode);
-}
-
-bool QClipboard::supportsMode(Mode mode) const
-{
- QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard();
- return clipboard->supportsMode(mode);
-}
-
-bool QClipboard::ownsMode(Mode mode) const
-{
- QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard();
- return clipboard->ownsMode(mode);
-}
-
-#endif // QT_NO_CLIPBOARD
-
-QT_END_NAMESPACE
diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp
index a33b264704..87774b2056 100644
--- a/src/gui/kernel/qcursor.cpp
+++ b/src/gui/kernel/qcursor.cpp
@@ -51,6 +51,9 @@
#include <private/qcursor_p.h>
#include <qdebug.h>
+#include <qpa/qplatformcursor.h>
+#include <private/qguiapplication_p.h>
+
QT_BEGIN_NAMESPACE
/*!
@@ -172,6 +175,13 @@ QT_BEGIN_NAMESPACE
\sa setPos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal()
*/
+QPoint QCursor::pos(const QScreen *screen)
+{
+ if (screen)
+ if (const QPlatformCursor *cursor = screen->handle()->cursor())
+ return cursor->pos();
+ return QGuiApplicationPrivate::lastCursorPosition.toPoint();
+}
/*!
\fn QPoint QCursor::pos()
@@ -191,7 +201,10 @@ QT_BEGIN_NAMESPACE
\sa setPos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal(), QGuiApplication::primaryScreen()
*/
-
+QPoint QCursor::pos()
+{
+ return QCursor::pos(QGuiApplication::primaryScreen());
+}
/*!
\fn void QCursor::setPos(QScreen *screen, int x, int y)
@@ -214,6 +227,19 @@ QT_BEGIN_NAMESPACE
\sa pos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal()
*/
+void QCursor::setPos(QScreen *screen, int x, int y)
+{
+ if (screen) {
+ if (QPlatformCursor *cursor = screen->handle()->cursor()) {
+ const QPoint pos = QPoint(x, y);
+ // Need to check, since some X servers generate null mouse move
+ // events, causing looping in applications which call setPos() on
+ // every mouse move event.
+ if (pos != cursor->pos())
+ cursor->setPos(pos);
+ }
+ }
+}
/*!
\fn void QCursor::setPos(int x, int y)
@@ -226,6 +252,10 @@ QT_BEGIN_NAMESPACE
\sa pos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal(), QGuiApplication::primaryScreen()
*/
+void QCursor::setPos(int x, int y)
+{
+ QCursor::setPos(QGuiApplication::primaryScreen(), x, y);
+}
/*!
\fn void QCursor::setPos (const QPoint &p)
@@ -401,34 +431,6 @@ QCursor::QCursor(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
d = QCursorData::setBitmap(bitmap, mask, hotX, hotY);
}
-QCursorData *qt_cursorTable[Qt::LastCursor + 1];
-bool QCursorData::initialized = false;
-
-/*! \internal */
-void QCursorData::cleanup()
-{
- if(!QCursorData::initialized)
- return;
-
- for (int shape = 0; shape <= Qt::LastCursor; ++shape) {
- // In case someone has a static QCursor defined with this shape
- if (!qt_cursorTable[shape]->ref.deref())
- delete qt_cursorTable[shape];
- qt_cursorTable[shape] = 0;
- }
- QCursorData::initialized = false;
-}
-
-/*! \internal */
-void QCursorData::initialize()
-{
- if (QCursorData::initialized)
- return;
- for (int shape = 0; shape <= Qt::LastCursor; ++shape)
- qt_cursorTable[shape] = new QCursorData((Qt::CursorShape)shape);
- QCursorData::initialized = true;
-}
-
/*!
Constructs a cursor with the default arrow shape.
*/
@@ -602,6 +604,73 @@ QDebug operator<<(QDebug dbg, const QCursor &c)
}
#endif
+/*****************************************************************************
+ Internal QCursorData class
+ *****************************************************************************/
+
+QCursorData *qt_cursorTable[Qt::LastCursor + 1];
+bool QCursorData::initialized = false;
+
+QCursorData::QCursorData(Qt::CursorShape s)
+ : ref(1), cshape(s), bm(0), bmm(0), hx(0), hy(0)
+{
+}
+
+QCursorData::~QCursorData()
+{
+ delete bm;
+ delete bmm;
+}
+
+/*! \internal */
+void QCursorData::cleanup()
+{
+ if(!QCursorData::initialized)
+ return;
+
+ for (int shape = 0; shape <= Qt::LastCursor; ++shape) {
+ // In case someone has a static QCursor defined with this shape
+ if (!qt_cursorTable[shape]->ref.deref())
+ delete qt_cursorTable[shape];
+ qt_cursorTable[shape] = 0;
+ }
+ QCursorData::initialized = false;
+}
+
+/*! \internal */
+void QCursorData::initialize()
+{
+ if (QCursorData::initialized)
+ return;
+ for (int shape = 0; shape <= Qt::LastCursor; ++shape)
+ qt_cursorTable[shape] = new QCursorData((Qt::CursorShape)shape);
+ QCursorData::initialized = true;
+}
+
+QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
+{
+ if (!QCursorData::initialized)
+ QCursorData::initialize();
+ if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) {
+ qWarning("QCursor: Cannot create bitmap cursor; invalid bitmap(s)");
+ QCursorData *c = qt_cursorTable[0];
+ c->ref.ref();
+ return c;
+ }
+ QCursorData *d = new QCursorData;
+ d->bm = new QBitmap(bitmap);
+ d->bmm = new QBitmap(mask);
+ d->cshape = Qt::BitmapCursor;
+ d->hx = hotX >= 0 ? hotX : bitmap.width() / 2;
+ d->hy = hotY >= 0 ? hotY : bitmap.height() / 2;
+
+ return d;
+}
+
+void QCursorData::update()
+{
+}
+
QT_END_NAMESPACE
#endif // QT_NO_CURSOR
diff --git a/src/gui/kernel/qcursor_qpa.cpp b/src/gui/kernel/qcursor_qpa.cpp
deleted file mode 100644
index 0b19a47c69..0000000000
--- a/src/gui/kernel/qcursor_qpa.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qcursor.h>
-#include <qscreen.h>
-#include <private/qcursor_p.h>
-#include <qpa/qplatformcursor.h>
-#include <private/qguiapplication_p.h>
-#include <qbitmap.h>
-
-QT_BEGIN_NAMESPACE
-
-QT_USE_NAMESPACE
-
-#ifndef QT_NO_CURSOR
-
-/*****************************************************************************
- Internal QCursorData class
- *****************************************************************************/
-
-QCursorData::QCursorData(Qt::CursorShape s)
- : ref(1), cshape(s), bm(0), bmm(0), hx(0), hy(0)
-{
-}
-
-QCursorData::~QCursorData()
-{
- delete bm;
- delete bmm;
-}
-
-
-/*****************************************************************************
- Global cursors
- *****************************************************************************/
-
-extern QCursorData *qt_cursorTable[Qt::LastCursor + 1]; // qcursor.cpp
-
-QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
-{
- if (!QCursorData::initialized)
- QCursorData::initialize();
- if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) {
- qWarning("QCursor: Cannot create bitmap cursor; invalid bitmap(s)");
- QCursorData *c = qt_cursorTable[0];
- c->ref.ref();
- return c;
- }
- QCursorData *d = new QCursorData;
- d->bm = new QBitmap(bitmap);
- d->bmm = new QBitmap(mask);
- d->cshape = Qt::BitmapCursor;
- d->hx = hotX >= 0 ? hotX : bitmap.width() / 2;
- d->hy = hotY >= 0 ? hotY : bitmap.height() / 2;
-
- return d;
-}
-
-void QCursorData::update()
-{
-}
-
-#endif //QT_NO_CURSOR
-
-QPoint QCursor::pos()
-{
- return QCursor::pos(QGuiApplication::primaryScreen());
-}
-
-QPoint QCursor::pos(const QScreen *screen)
-{
- if (screen)
- if (const QPlatformCursor *cursor = screen->handle()->cursor())
- return cursor->pos();
- return QGuiApplicationPrivate::lastCursorPosition.toPoint();
-}
-
-void QCursor::setPos(QScreen *screen, int x, int y)
-{
- if (screen) {
- if (QPlatformCursor *cursor = screen->handle()->cursor()) {
- const QPoint pos = QPoint(x, y);
- // Need to check, since some X servers generate null mouse move
- // events, causing looping in applications which call setPos() on
- // every mouse move event.
- if (pos != cursor->pos())
- cursor->setPos(pos);
- }
- }
-}
-
-void QCursor::setPos(int x, int y)
-{
- QCursor::setPos(QGuiApplication::primaryScreen(), x, y);
-}
-
-QT_END_NAMESPACE
diff --git a/src/gui/kernel/qdnd.cpp b/src/gui/kernel/qdnd.cpp
index d34a135eb7..328ca389ed 100644
--- a/src/gui/kernel/qdnd.cpp
+++ b/src/gui/kernel/qdnd.cpp
@@ -142,6 +142,7 @@ Qt::DropAction QDragManager::drag(QDrag *o)
QGuiApplicationPrivate::instance()->notifyDragStarted(o);
const Qt::DropAction result = m_platformDrag->drag(m_object);
m_object = 0;
+ o->deleteLater();
return result;
}
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index d6741af152..492f2a11c9 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -287,6 +287,8 @@ QMouseEvent::~QMouseEvent()
\l Qt::MouseEventNotSynthesized is returned always.
\sa Qt::MouseEventSource
+ \sa QGraphicsSceneMouseEvent::source()
+ \sa QGraphicsSceneMouseEvent::setSource()
*/
Qt::MouseEventSource QMouseEvent::source() const
{
@@ -301,6 +303,8 @@ Qt::MouseEventSource QMouseEvent::source() const
The mouse event flags provide additional information about a mouse event.
\sa Qt::MouseEventFlag
+ \sa QGraphicsSceneMouseEvent::flags()
+ \sa QGraphicsSceneMouseEvent::setFlags()
*/
Qt::MouseEventFlags QMouseEvent::flags() const
{
@@ -1185,7 +1189,7 @@ Qt::FocusReason QFocusEvent::reason() const
The event contains a region() that needs to be updated, and a
rect() that is the bounding rectangle of that region. Both are
- provided because many widgets can't make much use of region(),
+ provided because many widgets cannot make much use of region(),
and rect() can be much faster than region().boundingRect().
\section1 Automatic Clipping
@@ -1977,40 +1981,63 @@ QVariant QInputMethodQueryEvent::value(Qt::InputMethodQuery query) const
\ingroup events
- Tablet Events are generated from a Wacom tablet. Most of the time you will
- want to deal with events from the tablet as if they were events from a
- mouse; for example, you would retrieve the cursor position with x(), y(),
- pos(), globalX(), globalY(), and globalPos(). In some situations you may
- wish to retrieve the extra information provided by the tablet device
- driver; for example, you might want to do subpixeling with higher
- resolution coordinates or you may want to adjust color brightness based on
- pressure. QTabletEvent allows you to read the pressure(), the xTilt(), and
- yTilt(), as well as the type of device being used with device() (see
- \l{TabletDevice}). It can also give you the minimum and maximum values for
- each device's pressure and high resolution coordinates.
-
- A tablet event contains a special accept flag that indicates whether the
- receiver wants the event. You should call QTabletEvent::accept() if you
- handle the tablet event; otherwise it will be sent to the parent widget.
- The exception are TabletEnterProximity and TabletLeaveProximity events,
- these are only sent to QApplication and don't check whether or not they are
- accepted.
-
- The QWidget::setEnabled() function can be used to enable or
- disable mouse and keyboard events for a widget.
-
- The event handler QWidget::tabletEvent() receives all three types of
- tablet events. Qt will first send a tabletEvent then, if it is not
- accepted, it will send a mouse event. This allows applications that
- don't utilize tablets to use a tablet like a mouse, while also
- enabling those who want to use both tablets and mouses differently.
+ \e{Tablet events} are generated from tablet peripherals such as Wacom
+ tablets and various other brands, and electromagnetic stylus devices
+ included with some types of tablet computers. (It is not the same as
+ \l QTouchEvent which a touchscreen generates, even when a passive stylus is
+ used on a touchscreen.)
+
+ Tablet events are similar to mouse events; for example, the \l x(), \l y(),
+ \l pos(), \l globalX(), \l globalY(), and \l globalPos() accessors provide
+ the cursor position, and you can see which \l buttons() are pressed
+ (pressing the stylus tip against the tablet surface is equivalent to a left
+ mouse button). But tablet events also pass through some extra information
+ that the tablet device driver provides; for example, you might want to do
+ subpixel rendering with higher resolution coordinates (\l hiResGlobalX()
+ and \l hiResGlobalY()), adjust color brightness based on the \l pressure()
+ of the tool against the tablet surface, use different brushes depending on
+ the type of tool in use (\l device()), modulate the brush shape in some way
+ according to the X-axis and Y-axis tilt of the tool with respect to the
+ tablet surface (\l xTilt() and \l yTilt()), and use a virtual eraser
+ instead of a brush if the user switches to the other end of a double-ended
+ stylus (\l pointerType()).
+
+ Every event contains an accept flag that indicates whether the receiver
+ wants the event. You should call QTabletEvent::accept() if you handle the
+ tablet event; otherwise it will be sent to the parent widget. The exception
+ are TabletEnterProximity and TabletLeaveProximity events: these are only
+ sent to QApplication and do not check whether or not they are accepted.
+
+ The QWidget::setEnabled() function can be used to enable or disable
+ mouse, tablet and keyboard events for a widget.
+
+ The event handler QWidget::tabletEvent() receives TabletPress,
+ TabletRelease and TabletMove events. Qt will first send a
+ tablet event, then if it is not accepted by any widget, it will send a
+ mouse event. This allows users of applications that are not designed for
+ tablets to use a tablet like a mouse. However high-resolution drawing
+ applications should handle the tablet events, because they can occur at a
+ higher frequency, which is a benefit for smooth and accurate drawing.
+ If the tablet events are rejected, the synthetic mouse events may be
+ compressed for efficiency.
+
+ New in Qt 5.4: QTabletEvent includes all information available from the
+ device, including \l QTabletEvent::buttons(). Previously it was not
+ possible to accept all tablet events and also know which stylus buttons
+ were pressed.
+
+ Note that pressing the stylus button while the stylus hovers over the
+ tablet will generate a button press on some types of tablets, while on
+ other types it will be necessary to press the stylus against the tablet
+ surface in order to register the simultaneous stylus button press.
\section1 Notes for X11 Users
- Qt uses the following hard-coded names to identify tablet
- devices from the xorg.conf file on X11 (apart from IRIX):
- 'stylus', 'pen', and 'eraser'. If the devices have other names,
- they will not be picked up Qt.
+ If the tablet is configured in xorg.conf to use the Wacom driver, there
+ will be separate XInput "devices" for the stylus, eraser, and (optionally)
+ cursor and touchpad. Qt recognizes these by their names. Otherwise, if the
+ tablet is configured to use the evdev driver, there will be only one device
+ and applications may not be able to distinguish the stylus from the eraser.
*/
/*!
@@ -2068,11 +2095,73 @@ QVariant QInputMethodQueryEvent::value(Qt::InputMethodQuery query) const
The \a tangentialPressure parameter contins the tangential pressure of an air
brush. If the device does not support tangential pressure, pass 0 here.
+ \a rotation contains the device's rotation in degrees. 4D mice and the Wacom
+ Art Pen support rotation. If the device does not support rotation, pass 0 here.
+
+ The \a button that caused the event is given as a value from the
+ \l Qt::MouseButton enum. If the event \a type is not \l TabletPress or
+ \l TabletRelease, the appropriate button for this event is \l Qt::NoButton.
+
+ \a buttons is the state of all buttons at the time of the event.
+
+ \sa pos(), globalPos(), device(), pressure(), xTilt(), yTilt(), uniqueId(), rotation(),
+ tangentialPressure(), z()
+*/
+
+QTabletEvent::QTabletEvent(Type type, const QPointF &pos, const QPointF &globalPos,
+ int device, int pointerType,
+ qreal pressure, int xTilt, int yTilt, qreal tangentialPressure,
+ qreal rotation, int z, Qt::KeyboardModifiers keyState, qint64 uniqueID,
+ Qt::MouseButton button, Qt::MouseButtons buttons)
+ : QInputEvent(type, keyState),
+ mPos(pos),
+ mGPos(globalPos),
+ mDev(device),
+ mPointerType(pointerType),
+ mXT(xTilt),
+ mYT(yTilt),
+ mZ(z),
+ mPress(pressure),
+ mTangential(tangentialPressure),
+ mRot(rotation),
+ mUnique(uniqueID),
+ mExtra(new QTabletEventPrivate(button, buttons))
+{
+}
+
+/*!
+ Construct a tablet event of the given \a type.
+
+ The \a pos parameter indicates where the event occurred in the
+ widget; \a globalPos is the corresponding position in absolute
+ coordinates.
+
+ \a pressure contains the pressure exerted on the \a device.
+
+ \a pointerType describes the type of pen that is being used.
+
+ \a xTilt and \a yTilt contain the device's degree of tilt from the
+ x and y axes respectively.
+
+ \a keyState specifies which keyboard modifiers are pressed (e.g.,
+ \uicontrol{Ctrl}).
+
+ The \a uniqueID parameter contains the unique ID for the current device.
+
+ The \a z parameter contains the coordinate of the device on the tablet, this
+ is usually given by a wheel on 4D mouse. If the device does not support a
+ Z-axis, pass zero here.
+
+ The \a tangentialPressure parameter contins the tangential pressure of an air
+ brush. If the device does not support tangential pressure, pass 0 here.
+
\a rotation contains the device's rotation in degrees. 4D mice support
rotation. If the device does not support rotation, pass 0 here.
\sa pos(), globalPos(), device(), pressure(), xTilt(), yTilt(), uniqueId(), rotation(),
tangentialPressure(), z()
+
+ \deprecated in 5.4: use the constructor with MouseButton status
*/
QTabletEvent::QTabletEvent(Type type, const QPointF &pos, const QPointF &globalPos,
@@ -2091,7 +2180,7 @@ QTabletEvent::QTabletEvent(Type type, const QPointF &pos, const QPointF &globalP
mTangential(tangentialPressure),
mRot(rotation),
mUnique(uniqueID),
- mExtra(0)
+ mExtra(new QTabletEventPrivate(Qt::NoButton, Qt::NoButton))
{
}
@@ -2103,6 +2192,34 @@ QTabletEvent::~QTabletEvent()
}
/*!
+ Returns the button that caused the event.
+
+ Note that the returned value is always Qt::NoButton for \l TabletMove,
+ \l TabletEnterProximity and \l TabletLeaveProximity events.
+
+ \sa buttons(), Qt::MouseButton
+*/
+Qt::MouseButton QTabletEvent::button() const
+{
+ return static_cast<QTabletEventPrivate *>(mExtra)->b;
+}
+
+/*!
+ Returns the button state when the event was generated. The button state is
+ a combination of buttons from the \l Qt::MouseButton enum using the OR
+ operator. For \l TabletMove events, this is all buttons that are pressed
+ down. For \l TabletPress events this includes the button that caused the
+ event. For \l TabletRelease events this excludes the button that caused the
+ event.
+
+ \sa button(), Qt::MouseButton
+*/
+Qt::MouseButtons QTabletEvent::buttons() const
+{
+ return static_cast<QTabletEventPrivate *>(mExtra)->buttonState;
+}
+
+/*!
\fn TabletDevices QTabletEvent::device() const
Returns the type of device that generated the event.
@@ -2132,7 +2249,7 @@ QTabletEvent::~QTabletEvent()
\fn qreal QTabletEvent::rotation() const
Returns the rotation of the current device in degress. This is usually
- given by a 4D Mouse. If the device doesn't support rotation this value is
+ given by a 4D Mouse. If the device does not support rotation this value is
always 0.0.
*/
@@ -3036,7 +3153,7 @@ QActionEvent::~QActionEvent()
If spontaneous() is true, the event originated outside the
application. In this case, the user hid the window using the
window manager controls, either by iconifying the window or by
- switching to another virtual desktop where the window isn't
+ switching to another virtual desktop where the window is not
visible. The window will become hidden but not withdrawn. If the
window was iconified, QWidget::isMinimized() returns \c true.
@@ -3265,6 +3382,61 @@ static inline void formatTouchEvent(QDebug d, const char *name, const QTouchEven
d << ')';
}
+static void formatUnicodeString(QDebug d, const QString &s)
+{
+ d << '"' << hex;
+ for (int i = 0; i < s.size(); ++i) {
+ if (i)
+ d << ',';
+ d << "U+" << s.at(i).unicode();
+ }
+ d << dec << '"';
+}
+
+static inline void formatInputMethodEvent(QDebug d, const QInputMethodEvent *e)
+{
+ d << "QInputMethodEvent(";
+ if (!e->preeditString().isEmpty()) {
+ d << "preedit=";
+ formatUnicodeString(d, e->preeditString());
+ }
+ if (!e->commitString().isEmpty()) {
+ d << ", commit=";
+ formatUnicodeString(d, e->commitString());
+ }
+ if (e->replacementLength()) {
+ d << ", replacementStart=" << e->replacementStart() << ", replacementLength="
+ << e->replacementLength();
+ }
+ if (const int attributeCount = e->attributes().size()) {
+ d << ", attributes= {";
+ for (int a = 0; a < attributeCount; ++a) {
+ const QInputMethodEvent::Attribute &at = e->attributes().at(a);
+ if (a)
+ d << ',';
+ d << "[type= " << at.type << ", start=" << at.start << ", length=" << at.length
+ << ", value=" << at.value << ']';
+ }
+ d << '}';
+ }
+ d << ')';
+}
+
+static inline void formatInputMethodQueryEvent(QDebug d, const QInputMethodQueryEvent *e)
+{
+ const Qt::InputMethodQueries queries = e->queries();
+ d << "QInputMethodQueryEvent(queries=" << showbase << hex << int(queries)
+ << noshowbase << dec << ", {";
+ for (unsigned mask = 1; mask <= Qt::ImTextAfterCursor; mask<<=1) {
+ if (queries & mask) {
+ const QVariant value = e->value(static_cast<Qt::InputMethodQuery>(mask));
+ if (value.isValid())
+ d << '[' << showbase << hex << mask << noshowbase << dec << '=' << value << "],";
+ }
+ }
+ d << "})";
+}
+
QDebug operator<<(QDebug dbg, const QEvent *e) {
// More useful event output could be added here
if (!e)
@@ -3302,6 +3474,8 @@ QDebug operator<<(QDebug dbg, const QEvent *e) {
<< ", " << hex << (int)me->modifiers() << dec;
if (const Qt::MouseEventSource source = me->source())
nsp << ", source = " << source;
+ if (const Qt::MouseEventFlags flags = me->flags())
+ nsp << ", flags = " << hex << int(flags) << dec;
nsp << ')';
}
return dbg.space();
@@ -3355,11 +3529,13 @@ QDebug operator<<(QDebug dbg, const QEvent *e) {
}
return dbg.space();
case QEvent::FocusIn:
- n = "FocusIn";
- break;
+ dbg.nospace() << "QFocusEvent(FocusIn, reason="
+ << static_cast<const QFocusEvent *>(e)->reason() << ')';
+ return dbg.space();
case QEvent::FocusOut:
- n = "FocusOut";
- break;
+ dbg.nospace() << "QFocusEvent(FocusOut, reason="
+ << static_cast<const QFocusEvent *>(e)->reason() << ')';
+ return dbg.space();
case QEvent::Enter:
n = "Enter";
break;
@@ -3381,12 +3557,24 @@ QDebug operator<<(QDebug dbg, const QEvent *e) {
case QEvent::Paint:
n = "Paint";
break;
- case QEvent::Move:
- n = "Move";
- break;
- case QEvent::Resize:
- n = "Resize";
- break;
+ case QEvent::Move: {
+ const QMoveEvent *me = static_cast<const QMoveEvent *>(e);
+ QDebug nospace = dbg.nospace();
+ nospace << "QMoveEvent(" << me->pos();
+ if (!me->spontaneous())
+ nospace << ", non-spontaneous";
+ nospace << ')';
+ }
+ return dbg.space();
+ case QEvent::Resize: {
+ const QResizeEvent *re = static_cast<const QResizeEvent *>(e);
+ QDebug nospace = dbg.nospace();
+ nospace << "QResizeEvent(" << re->size();
+ if (!re->spontaneous())
+ nospace << ", non-spontaneous";
+ nospace << ')';
+ }
+ return dbg.space();
case QEvent::Create:
n = "Create";
break;
@@ -3498,6 +3686,18 @@ QDebug operator<<(QDebug dbg, const QEvent *e) {
case QEvent::GraphicsSceneMove:
n = "GraphicsSceneMove";
break;
+ case QEvent::InputMethod: {
+ QDebugStateSaver saver(dbg);
+ dbg.nospace();
+ formatInputMethodEvent(dbg, static_cast<const QInputMethodEvent *>(e));
+ }
+ return dbg;
+ case QEvent::InputMethodQuery: {
+ QDebugStateSaver saver(dbg);
+ dbg.nospace();
+ formatInputMethodQueryEvent(dbg, static_cast<const QInputMethodQueryEvent *>(e));
+ }
+ return dbg;
case QEvent::CursorChange:
n = "CursorChange";
break;
@@ -3551,7 +3751,23 @@ QDebug operator<<(QDebug dbg, const QEvent *e) {
case QEvent::Gesture:
n = "Gesture";
break;
+ case QEvent::GestureOverride:
+ n = "GestureOverride";
+ break;
#endif
+ case QEvent::MetaCall:
+ n = "MetaCall";
+ break;
+ case QEvent::ApplicationStateChange:
+ dbg.nospace() << "QApplicationStateChangeEvent("
+ << static_cast<const QApplicationStateChangeEvent *>(e)->applicationState() << ')';
+ return dbg.space();
+ case QEvent::WindowTitleChange:
+ n = "WindowTitleChange";
+ break;
+ case QEvent::Expose:
+ n = "Expose";
+ break;
default:
dbg.nospace() << "QEvent(" << (const void *)e << ", type = " << e->type() << ')';
return dbg.space();
@@ -3570,7 +3786,7 @@ QDebug operator<<(QDebug dbg, const QEvent *e) {
\ingroup events
\inmodule QtGui
- Normally you don't need to use this class directly; QShortcut
+ Normally you do not need to use this class directly; QShortcut
provides a higher-level interface to handle shortcut keys.
\sa QShortcut
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index 0a826284c9..346c0a4ba0 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -230,7 +230,12 @@ public:
QTabletEvent(Type t, const QPointF &pos, const QPointF &globalPos,
int device, int pointerType, qreal pressure, int xTilt, int yTilt,
qreal tangentialPressure, qreal rotation, int z,
- Qt::KeyboardModifiers keyState, qint64 uniqueID);
+ Qt::KeyboardModifiers keyState, qint64 uniqueID); // ### remove in Qt 6
+ QTabletEvent(Type t, const QPointF &pos, const QPointF &globalPos,
+ int device, int pointerType, qreal pressure, int xTilt, int yTilt,
+ qreal tangentialPressure, qreal rotation, int z,
+ Qt::KeyboardModifiers keyState, qint64 uniqueID,
+ Qt::MouseButton button, Qt::MouseButtons buttons);
~QTabletEvent();
inline QPoint pos() const { return mPos.toPoint(); }
@@ -257,6 +262,8 @@ public:
inline qreal rotation() const { return mRot; }
inline int xTilt() const { return mXT; }
inline int yTilt() const { return mYT; }
+ Qt::MouseButton button() const;
+ Qt::MouseButtons buttons() const;
protected:
QPointF mPos, mGPos;
@@ -264,9 +271,8 @@ protected:
qreal mPress, mTangential, mRot;
qint64 mUnique;
- // I don't know what the future holds for tablets but there could be some
- // new devices coming along, and there seem to be "holes" in the
- // OS-specific events for this.
+ // QTabletEventPrivate for extra storage.
+ // ### Qt 6: QPointingEvent will have Buttons, QTabletEvent will inherit
void *mExtra;
};
#endif // QT_NO_TABLETEVENT
@@ -377,8 +383,6 @@ public:
inline const QRegion &region() const { return m_region; }
protected:
- friend class QApplication;
- friend class QCoreApplication;
QRect m_rect;
QRegion m_region;
bool m_erased;
@@ -395,7 +399,6 @@ public:
protected:
QPoint p, oldp;
friend class QApplication;
- friend class QCoreApplication;
};
class Q_GUI_EXPORT QExposeEvent : public QEvent
@@ -421,7 +424,6 @@ public:
protected:
QSize s, olds;
friend class QApplication;
- friend class QCoreApplication;
};
@@ -601,7 +603,6 @@ public:
inline void ignore(const QRect & r) { ignore(); rect = r; }
protected:
- friend class QApplication;
QRect rect;
};
diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h
index e01216e9f1..d24f3768a8 100644
--- a/src/gui/kernel/qevent_p.h
+++ b/src/gui/kernel/qevent_p.h
@@ -92,6 +92,20 @@ public:
QVector<QPointF> rawScreenPositions;
};
+#ifndef QT_NO_TABLETEVENT
+class QTabletEventPrivate
+{
+public:
+ inline QTabletEventPrivate(Qt::MouseButton button, Qt::MouseButtons buttons)
+ : b(button),
+ buttonState(buttons)
+ { }
+
+ Qt::MouseButton b;
+ Qt::MouseButtons buttonState;
+};
+#endif // QT_NO_TABLETEVENT
+
QT_END_NAMESPACE
#endif // QEVENT_P_H
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index f429ad2229..68e87a024f 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -114,7 +114,7 @@ Qt::KeyboardModifiers QGuiApplicationPrivate::modifier_buttons = Qt::NoModifier;
QPointF QGuiApplicationPrivate::lastCursorPosition(qInf(), qInf());
-bool QGuiApplicationPrivate::tabletState = false;
+Qt::MouseButtons QGuiApplicationPrivate::tabletState = Qt::NoButton;
QWindow *QGuiApplicationPrivate::tabletPressTarget = 0;
QWindow *QGuiApplicationPrivate::currentMouseWindow = 0;
@@ -503,6 +503,7 @@ static QWindowGeometrySpecification windowGeometrySpecification;
\li \c {-qwindowgeometry} \e geometry, specifies window geometry for
the main window using the X11-syntax. For example:
\c {-qwindowgeometry 100x100+50+50}
+ \li \c {-qwindowicon}, sets the default window icon
\li \c {-qwindowtitle}, sets the title of the first window
\li \c{-reverse}, sets the application's layout direction to
Qt::RightToLeft. This option is intended to aid debugging and should
@@ -896,7 +897,19 @@ QList<QScreen *> QGuiApplication::screens()
This signal is emitted whenever a new screen \a screen has been added to the system.
- \sa screens(), primaryScreen()
+ \sa screens(), primaryScreen(), screenRemoved()
+*/
+
+/*!
+ \fn void QGuiApplication::screenRemoved(QScreen *screen)
+
+ This signal is emitted whenever a \a screen is removed from the system. It
+ provides an opportunity to manage the windows on the screen before Qt falls back
+ to moving them to the primary screen.
+
+ \sa screens(), screenAdded(), QObject::destroyed(), QWindow::setScreen()
+
+ \since 5.4
*/
@@ -1108,12 +1121,15 @@ void QGuiApplicationPrivate::createPlatformIntegration()
// Get command line params
+ QString icon;
+
int j = argc ? 1 : 0;
for (int i=1; i<argc; i++) {
if (argv[i] && *argv[i] != '-') {
argv[j++] = argv[i];
continue;
}
+ const bool isXcb = platformName == "xcb";
QByteArray arg = argv[i];
if (arg.startsWith("--"))
arg.remove(0, 1);
@@ -1126,12 +1142,16 @@ void QGuiApplicationPrivate::createPlatformIntegration()
} else if (arg == "-platformtheme") {
if (++i < argc)
platformThemeName = QString::fromLocal8Bit(argv[i]);
- } else if (arg == "-qwindowgeometry" || (platformName == "xcb" && arg == "-geometry")) {
+ } else if (arg == "-qwindowgeometry" || (isXcb && arg == "-geometry")) {
if (++i < argc)
windowGeometrySpecification = QWindowGeometrySpecification::fromArgument(argv[i]);
- } else if (arg == "-qwindowtitle" || (platformName == "xcb" && arg == "-title")) {
+ } else if (arg == "-qwindowtitle" || (isXcb && arg == "-title")) {
if (++i < argc)
firstWindowTitle = QString::fromLocal8Bit(argv[i]);
+ } else if (arg == "-qwindowicon" || (isXcb && arg == "-icon")) {
+ if (++i < argc) {
+ icon = QString::fromLocal8Bit(argv[i]);
+ }
} else {
argv[j++] = argv[i];
}
@@ -1144,6 +1164,8 @@ void QGuiApplicationPrivate::createPlatformIntegration()
init_platform(QLatin1String(platformName), platformPluginPath, platformThemeName, argc, argv);
+ if (!icon.isEmpty())
+ forcedWindowIcon = QDir::isAbsolutePath(icon) ? QIcon(icon) : QIcon::fromTheme(icon);
}
/*!
@@ -1426,6 +1448,20 @@ QPlatformNativeInterface *QGuiApplication::platformNativeInterface()
}
/*!
+ Returns a function pointer from the platformplugin matching \a function
+*/
+QFunctionPointer QGuiApplication::platformFunction(const QByteArray &function)
+{
+ QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration();
+ if (!pi) {
+ qWarning() << "QGuiApplication::platformFunction(): Must construct a QGuiApplication before accessing a platform function";
+ return Q_NULLPTR;
+ }
+
+ return pi->nativeInterface() ? pi->nativeInterface()->platformFunction(function) : Q_NULLPTR;
+}
+
+/*!
Enters the main event loop and waits until exit() is called, and then
returns the value that was set to exit() (which is 0 if exit() is called
via quit()).
@@ -1548,8 +1584,9 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv
case QWindowSystemInterfacePrivate::WindowScreenChanged:
QGuiApplicationPrivate::processWindowScreenChangedEvent(static_cast<QWindowSystemInterfacePrivate::WindowScreenChangedEvent *>(e));
break;
- case QWindowSystemInterfacePrivate::ApplicationStateChanged:
- QGuiApplicationPrivate::setApplicationState(static_cast<QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *>(e)->newState);
+ case QWindowSystemInterfacePrivate::ApplicationStateChanged: {
+ QWindowSystemInterfacePrivate::ApplicationStateChangedEvent * changeEvent = static_cast<QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *>(e);
+ QGuiApplicationPrivate::setApplicationState(changeEvent->newState, changeEvent->forcePropagate); }
break;
case QWindowSystemInterfacePrivate::FlushEvents:
QWindowSystemInterface::deferredFlushWindowSystemEvents();
@@ -1944,7 +1981,7 @@ void QGuiApplicationPrivate::processWindowScreenChangedEvent(QWindowSystemInterf
{
if (QWindow *window = wse->window.data()) {
if (QScreen *screen = wse->screen.data())
- window->d_func()->setScreen(screen, false /* recreate */);
+ window->d_func()->setTopLevelScreen(screen, false /* recreate */);
else // Fall back to default behavior, and try to find some appropriate screen
window->setScreen(0);
}
@@ -2030,10 +2067,8 @@ void QGuiApplicationPrivate::processTabletEvent(QWindowSystemInterfacePrivate::T
{
#ifndef QT_NO_TABLETEVENT
QEvent::Type type = QEvent::TabletMove;
- if (e->down != tabletState) {
- type = e->down ? QEvent::TabletPress : QEvent::TabletRelease;
- tabletState = e->down;
- }
+ if (e->buttons != tabletState)
+ type = (e->buttons > tabletState) ? QEvent::TabletPress : QEvent::TabletRelease;
QWindow *window = e->window.data();
modifier_buttons = e->modifiers;
@@ -2065,12 +2100,21 @@ void QGuiApplicationPrivate::processTabletEvent(QWindowSystemInterfacePrivate::T
QPointF delta = e->global - e->global.toPoint();
local = window->mapFromGlobal(e->global.toPoint()) + delta;
}
+ Qt::MouseButtons stateChange = e->buttons ^ tabletState;
+ Qt::MouseButton button = Qt::NoButton;
+ for (int check = Qt::LeftButton; check <= int(Qt::MaxMouseButton); check = check << 1) {
+ if (check & stateChange) {
+ button = Qt::MouseButton(check);
+ break;
+ }
+ }
QTabletEvent ev(type, local, e->global,
e->device, e->pointerType, e->pressure, e->xTilt, e->yTilt,
e->tangentialPressure, e->rotation, e->z,
- e->modifiers, e->uid);
+ e->modifiers, e->uid, button, e->buttons);
ev.setTimestamp(e->timestamp);
QGuiApplication::sendSpontaneousEvent(window, &ev);
+ tabletState = e->buttons;
#else
Q_UNUSED(e)
#endif
@@ -2082,7 +2126,7 @@ void QGuiApplicationPrivate::processTabletEnterProximityEvent(QWindowSystemInter
QTabletEvent ev(QEvent::TabletEnterProximity, QPointF(), QPointF(),
e->device, e->pointerType, 0, 0, 0,
0, 0, 0,
- Qt::NoModifier, e->uid);
+ Qt::NoModifier, e->uid, Qt::NoButton, tabletState);
ev.setTimestamp(e->timestamp);
QGuiApplication::sendSpontaneousEvent(qGuiApp, &ev);
#else
@@ -2096,7 +2140,7 @@ void QGuiApplicationPrivate::processTabletLeaveProximityEvent(QWindowSystemInter
QTabletEvent ev(QEvent::TabletLeaveProximity, QPointF(), QPointF(),
e->device, e->pointerType, 0, 0, 0,
0, 0, 0,
- Qt::NoModifier, e->uid);
+ Qt::NoModifier, e->uid, Qt::NoButton, tabletState);
ev.setTimestamp(e->timestamp);
QGuiApplication::sendSpontaneousEvent(qGuiApp, &ev);
#else
@@ -2628,6 +2672,15 @@ QClipboard * QGuiApplication::clipboard()
#endif
/*!
+ \since 5.4
+ \fn void QGuiApplication::paletteChanged(const QPalette &palette)
+
+ This signal is emitted when the \a palette of the application changes.
+
+ \sa palette()
+*/
+
+/*!
Returns the default application palette.
\sa setPalette()
@@ -2653,6 +2706,7 @@ void QGuiApplication::setPalette(const QPalette &pal)
else
*QGuiApplicationPrivate::app_pal = pal;
applicationResourceFlags |= ApplicationPaletteExplicitlySet;
+ emit qGuiApp->paletteChanged(*QGuiApplicationPrivate::app_pal);
}
QRect QGuiApplicationPrivate::applyWindowGeometrySpecification(const QRect &windowGeometry, const QWindow *window)
@@ -2862,9 +2916,9 @@ Qt::ApplicationState QGuiApplication::applicationState()
\sa applicationState()
*/
-void QGuiApplicationPrivate::setApplicationState(Qt::ApplicationState state)
+void QGuiApplicationPrivate::setApplicationState(Qt::ApplicationState state, bool forcePropagate)
{
- if (applicationState == state)
+ if ((applicationState == state) && !forcePropagate)
return;
applicationState = state;
@@ -3065,6 +3119,8 @@ void QGuiApplicationPrivate::saveState()
On system start-up, the default layout direction depends on the
application's language.
+ The notifier signal was introduced in Qt 5.4.
+
\sa QWidget::layoutDirection, isLeftToRight(), isRightToLeft()
*/
@@ -3075,7 +3131,10 @@ void QGuiApplication::setLayoutDirection(Qt::LayoutDirection direction)
layout_direction = direction;
- QGuiApplicationPrivate::self->notifyLayoutDirectionChange();
+ if (qGuiApp) {
+ emit qGuiApp->layoutDirectionChanged(direction);
+ QGuiApplicationPrivate::self->notifyLayoutDirectionChange();
+ }
}
Qt::LayoutDirection QGuiApplication::layoutDirection()
diff --git a/src/gui/kernel/qguiapplication.h b/src/gui/kernel/qguiapplication.h
index 6d9a4b2376..6e751e1275 100644
--- a/src/gui/kernel/qguiapplication.h
+++ b/src/gui/kernel/qguiapplication.h
@@ -75,7 +75,7 @@ class Q_GUI_EXPORT QGuiApplication : public QCoreApplication
Q_OBJECT
Q_PROPERTY(QIcon windowIcon READ windowIcon WRITE setWindowIcon)
Q_PROPERTY(QString applicationDisplayName READ applicationDisplayName WRITE setApplicationDisplayName)
- Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection)
+ Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
Q_PROPERTY(QString platformName READ platformName STORED false)
Q_PROPERTY(bool quitOnLastWindowClosed READ quitOnLastWindowClosed WRITE setQuitOnLastWindowClosed)
@@ -143,6 +143,8 @@ public:
static QPlatformNativeInterface *platformNativeInterface();
+ static QFunctionPointer platformFunction(const QByteArray &function);
+
static void setQuitOnLastWindowClosed(bool quit);
static bool quitOnLastWindowClosed();
@@ -163,14 +165,17 @@ public:
Q_SIGNALS:
void fontDatabaseChanged();
void screenAdded(QScreen *screen);
+ void screenRemoved(QScreen *screen);
void lastWindowClosed();
void focusObjectChanged(QObject *focusObject);
void focusWindowChanged(QWindow *focusWindow);
void applicationStateChanged(Qt::ApplicationState state);
+ void layoutDirectionChanged(Qt::LayoutDirection direction);
#ifndef QT_NO_SESSIONMANAGER
void commitDataRequest(QSessionManager &sessionManager);
void saveStateRequest(QSessionManager &sessionManager);
#endif
+ void paletteChanged(const QPalette &pal);
protected:
bool event(QEvent *);
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index 1ec808ec27..5f9f6ad9f2 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -207,7 +207,7 @@ public:
static int mousePressY;
static int mouse_double_click_distance;
static QPointF lastCursorPosition;
- static bool tabletState;
+ static Qt::MouseButtons tabletState;
static QWindow *tabletPressTarget;
static QWindow *currentMouseWindow;
static Qt::ApplicationState applicationState;
@@ -234,6 +234,7 @@ public:
QInputMethod *inputMethod;
QString firstWindowTitle;
+ QIcon forcedWindowIcon;
static QList<QObject *> generic_plugin_list;
#ifndef QT_NO_SHORTCUT
@@ -288,7 +289,7 @@ public:
static QRect applyWindowGeometrySpecification(const QRect &windowGeometry, const QWindow *window);
- static void setApplicationState(Qt::ApplicationState state);
+ static void setApplicationState(Qt::ApplicationState state, bool forcePropagate = false);
protected:
virtual void notifyThemeChanged();
diff --git a/src/gui/kernel/qkeymapper.cpp b/src/gui/kernel/qkeymapper.cpp
index 0e150a9c1e..2ec72fd2d0 100644
--- a/src/gui/kernel/qkeymapper.cpp
+++ b/src/gui/kernel/qkeymapper.cpp
@@ -45,6 +45,9 @@
#include <private/qobject_p.h>
#include "qkeymapper_p.h"
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
+
QT_BEGIN_NAMESPACE
/*!
@@ -117,4 +120,32 @@ QKeyMapperPrivate *qt_keymapper_private()
return QKeyMapper::instance()->d_func();
}
+QKeyMapperPrivate::QKeyMapperPrivate()
+{
+ keyboardInputLocale = QLocale::system();
+ keyboardInputDirection = keyboardInputLocale.textDirection();
+}
+
+QKeyMapperPrivate::~QKeyMapperPrivate()
+{
+ // clearMappings();
+}
+
+void QKeyMapperPrivate::clearMappings()
+{
+}
+
+QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent *e)
+{
+ QList<int> result = QGuiApplicationPrivate::platformIntegration()->possibleKeys(e);
+ if (!result.isEmpty())
+ return result;
+
+ if (e->key() && (e->key() != Qt::Key_unknown))
+ result << int(e->key() + e->modifiers());
+ else if (!e->text().isEmpty())
+ result << int(e->text().at(0).unicode() + e->modifiers());
+ return result;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qoffscreensurface.cpp b/src/gui/kernel/qoffscreensurface.cpp
index 1625909843..003e3a0cc9 100644
--- a/src/gui/kernel/qoffscreensurface.cpp
+++ b/src/gui/kernel/qoffscreensurface.cpp
@@ -171,6 +171,9 @@ void QOffscreenSurface::create()
if (QThread::currentThread() != qGuiApp->thread())
qWarning("Attempting to create QWindow-based QOffscreenSurface outside the gui thread. Expect failures.");
d->offscreenWindow = new QWindow(d->screen);
+ // Remove this window from the global list since we do not want it to be destroyed when closing the app.
+ // The QOffscreenSurface has to be usable even after exiting the event loop.
+ QGuiApplicationPrivate::window_list.removeOne(d->offscreenWindow);
d->offscreenWindow->setSurfaceType(QWindow::OpenGLSurface);
d->offscreenWindow->setFormat(d->requestedFormat);
d->offscreenWindow->setGeometry(0, 0, d->size.width(), d->size.height());
diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp
index be592153d2..c7f4e6455c 100644
--- a/src/gui/kernel/qopenglcontext.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -63,6 +63,7 @@
#ifndef QT_OPENGL_ES_2
#include <QOpenGLFunctions_1_0>
+#include <QOpenGLFunctions_3_2_Core>
#endif
QT_BEGIN_NAMESPACE
@@ -370,9 +371,25 @@ int QOpenGLContextPrivate::maxTextureSize()
GLint size;
GLint next = 64;
funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
- QOpenGLFunctions_1_0 *gl1funcs = q->versionFunctions<QOpenGLFunctions_1_0>();
- gl1funcs->initializeOpenGLFunctions();
- gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size);
+
+ QOpenGLFunctions_1_0 *gl1funcs = 0;
+ QOpenGLFunctions_3_2_Core *gl3funcs = 0;
+
+ if (q->format().profile() == QSurfaceFormat::CoreProfile) {
+ gl3funcs = q->versionFunctions<QOpenGLFunctions_3_2_Core>();
+ gl3funcs->initializeOpenGLFunctions();
+ } else {
+ gl1funcs = q->versionFunctions<QOpenGLFunctions_1_0>();
+ gl1funcs->initializeOpenGLFunctions();
+ }
+
+ Q_ASSERT(gl1funcs || gl3funcs);
+
+ if (gl1funcs)
+ gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size);
+ else
+ gl3funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size);
+
if (size == 0) {
return max_texture_size;
}
@@ -383,7 +400,11 @@ int QOpenGLContextPrivate::maxTextureSize()
if (next > max_texture_size)
break;
funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
- gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next);
+ if (gl1funcs)
+ gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next);
+ else
+ gl3funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next);
+
} while (next > size);
max_texture_size = size;
@@ -486,6 +507,64 @@ void QOpenGLContext::setScreen(QScreen *screen)
}
/*!
+ Set the native handles for this context. When create() is called and a
+ native handle is set, configuration settings, like format(), are ignored
+ since this QOpenGLContext will wrap an already created native context
+ instead of creating a new one from scratch.
+
+ On some platforms the native context handle is not sufficient and other
+ related handles (for example, for a window or display) have to be provided
+ in addition. Therefore \a handle is variant containing a platform-specific
+ value type. These classes can be found in the QtPlatformHeaders module.
+
+ When create() is called with native handles set, the handles' ownership are
+ not taken, meaning that destroy() will not destroy the native context.
+
+ \note Some frameworks track the current context and surfaces internally.
+ Making the adopted QOpenGLContext current via Qt will have no effect on such
+ other frameworks' internal state. Therefore a subsequent makeCurrent done
+ via the other framework may have no effect. It is therefore advisable to
+ make explicit calls to make no context and surface current to reset the
+ other frameworks' internal state after performing OpenGL operations via Qt.
+
+ \note Using foreign contexts with Qt windows and Qt contexts with windows
+ and surfaces created by other frameworks may give unexpected results,
+ depending on the platform, due to potential mismatches in context and window
+ pixel formats. To make sure this does not happen, avoid making contexts and
+ surfaces from different frameworks current together. Instead, prefer
+ approaches based on context sharing where OpenGL resources like textures are
+ accessible both from Qt's and the foreign framework's contexts.
+
+ \since 5.4
+ \sa nativeHandle()
+*/
+void QOpenGLContext::setNativeHandle(const QVariant &handle)
+{
+ Q_D(QOpenGLContext);
+ d->nativeHandle = handle;
+}
+
+/*!
+ Returns the native handle for the context.
+
+ This function provides access to the QOpenGLContext's underlying native
+ context. The returned variant contains a platform-specific value type. These
+ classes can be found in the module QtPlatformHeaders.
+
+ On platforms where retrieving the native handle is not supported, or if
+ neither create() nor setNativeHandle() was called, a null variant is
+ returned.
+
+ \since 5.4
+ \sa setNativeHandle()
+ */
+QVariant QOpenGLContext::nativeHandle() const
+{
+ Q_D(const QOpenGLContext);
+ return d->nativeHandle;
+}
+
+/*!
Attempts to create the OpenGL context with the current configuration.
The current configuration includes the format, the share context, and the
@@ -506,7 +585,8 @@ void QOpenGLContext::setScreen(QScreen *screen)
*/
bool QOpenGLContext::create()
{
- destroy();
+ if (isValid())
+ destroy();
Q_D(QOpenGLContext);
d->platformGLContext = QGuiApplicationPrivate::platformIntegration()->createPlatformOpenGLContext(this);
@@ -556,6 +636,7 @@ void QOpenGLContext::destroy()
d->versionFunctionsBackend.clear();
delete d->textureFunctions;
d->textureFunctions = 0;
+ d->nativeHandle = QVariant();
}
/*!
diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h
index 19aecee75a..99f2fece51 100644
--- a/src/gui/kernel/qopenglcontext.h
+++ b/src/gui/kernel/qopenglcontext.h
@@ -64,6 +64,7 @@
#include <QtCore/qhash.h>
#include <QtCore/qpair.h>
+#include <QtCore/qvariant.h>
QT_BEGIN_NAMESPACE
@@ -153,6 +154,7 @@ public:
void setFormat(const QSurfaceFormat &format);
void setShareContext(QOpenGLContext *shareContext);
void setScreen(QScreen *screen);
+ void setNativeHandle(const QVariant &handle);
bool create();
bool isValid() const;
@@ -161,6 +163,7 @@ public:
QOpenGLContext *shareContext() const;
QOpenGLContextGroup *shareGroup() const;
QScreen *screen() const;
+ QVariant nativeHandle() const;
GLuint defaultFramebufferObject() const;
@@ -242,4 +245,4 @@ QT_END_NAMESPACE
#endif // QT_NO_OPENGL
-#endif // QGUIGLCONTEXT_H
+#endif // QOPENGLCONTEXT_H
diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h
index 711a3b1b2f..77e3605a4b 100644
--- a/src/gui/kernel/qopenglcontext_p.h
+++ b/src/gui/kernel/qopenglcontext_p.h
@@ -205,7 +205,6 @@ public:
, surface(0)
, functions(0)
, textureFunctions(0)
- , current_fbo(0)
, max_texture_size(-1)
, workaround_brokenFBOReadBack(false)
, workaround_brokenTexSubImage(false)
@@ -236,7 +235,6 @@ public:
mutable QSet<QByteArray> extensionNames;
QOpenGLTextureHelper* textureFunctions;
- GLuint current_fbo;
GLint max_texture_size;
bool workaround_brokenFBOReadBack;
@@ -245,6 +243,8 @@ public:
QPaintEngineEx *active_engine;
+ QVariant nativeHandle;
+
static QOpenGLContext *setCurrentContext(QOpenGLContext *context);
static void setGlobalShareContext(QOpenGLContext *context);
diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp
index f284c20af5..62e555b821 100644
--- a/src/gui/kernel/qpalette.cpp
+++ b/src/gui/kernel/qpalette.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -1141,9 +1141,33 @@ Q_GUI_EXPORT QPalette qt_fusionPalette()
}
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QPalette &)
+QDebug operator<<(QDebug dbg, const QPalette &p)
{
- dbg.nospace() << "QPalette()";
+ const char *colorGroupNames[] = {"Active", "Disabled", "Inactive"};
+ const char *colorRoleNames[] =
+ {"WindowText", "Button", "Light", "Midlight", "Dark", "Mid", "Text",
+ "BrightText", "ButtonText", "Base", "Window", "Shadow", "Highlight",
+ "HighlightedText", "Link", "LinkVisited", "AlternateBase", "NoRole",
+ "ToolTipBase","ToolTipText" };
+ QDebug nospace = dbg.nospace();
+ const uint mask = p.resolve();
+ nospace << "QPalette(resolve=" << hex << showbase << mask << ',';
+ for (int role = 0; role < (int)QPalette::NColorRoles; ++role) {
+ if (mask & (1<<role)) {
+ if (role)
+ nospace << ',';
+ nospace << colorRoleNames[role] << ":[";
+ for (int group = 0; group < (int)QPalette::NColorGroups; ++group) {
+ if (group)
+ nospace << ',';
+ const QRgb color = p.color(static_cast<QPalette::ColorGroup>(group),
+ static_cast<QPalette::ColorRole>(role)).rgba();
+ nospace << colorGroupNames[group] << ':' << color;
+ }
+ nospace << ']';
+ }
+ }
+ nospace << ')' << noshowbase << dec;
return dbg.space();
}
#endif
diff --git a/src/gui/kernel/qpixelformat.cpp b/src/gui/kernel/qpixelformat.cpp
new file mode 100644
index 0000000000..1e3345ee7a
--- /dev/null
+++ b/src/gui/kernel/qpixelformat.cpp
@@ -0,0 +1,630 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpixelformat.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QPixelFormat
+ \inmodule QtGui
+ \since 5.4
+ \brief QPixelFormat is a class for describing different pixel
+ layouts in graphics buffers
+
+ In Qt there is a often a need to represent the layout of the pixels in a
+ graphics buffer. Internally QPixelFormat stores everything in a 64 bit
+ datastructure. This gives performance but also some limitations.
+
+ QPixelFormat can describe 5 color channels and 1 alpha channel, each can use
+ 6 bits to describe the size of the color channel.
+
+ The position of the alpha channel is described with a separate enum. This is
+ to make it possible to describe QImage formats like ARGB32, and also
+ describe typical OpenGL formats like RBGA8888.
+
+ How pixels are suppose to be read is determined by the TypeInterpretation
+ enum. It describes if color values are suppose to be read byte per byte,
+ or if a pixel is suppose to be read as a complete int and then masked.
+ \sa TypeInterpretation
+
+ There is no support for describing YUV's macro pixels. Instead a list of YUV
+ formats has been made. When a QPixelFormat is describing a YUV format, the
+ bitsPerPixel value has been deduced by the YUV Layout enum. Also, the color
+ channels should all be set to zero except the fifth color channel that
+ should store the bitsPerPixel value.
+*/
+
+/*!
+ \enum QPixelFormat::ColorModel
+
+ This enum type is used to describe the color model of the pixelformat.
+
+ \value RGB The color model is RGB.
+
+ \value BGR This is logically the opposite endian version of RGB. However,
+ for ease of use it has its own model.
+
+ \value Indexed The color model uses a color palette.
+
+ \value Grayscale The color model is Grayscale.
+
+ \value CMYK The color model is CMYK.
+
+ \value HSL The color model is HSL.
+
+ \value HSV The color model is HSV.
+
+ \value YUV The color model is YUV.
+*/
+
+/*!
+ \enum QPixelFormat::AlphaUsage
+
+ This enum describes if the alpha channel is used or not. Sometimes the
+ pixelformat will have a size for the alpha channel, but the pixel format
+ does actually not use the alpha channel. For example RGB32 is such a
+ format. The RGB channels are 8 bits each, and there is no alpha channel.
+ But the complete size for each pixel is 32. Therefore the alpha channel size
+ is 8, but the alpha channel is ignored. Its important to note that in such
+ situations the position of the alpha channel is significant.
+
+ \value IgnoresAlpha The alpha channel is not used.
+
+ \value UsesAlpha The alpha channel is used.
+*/
+
+/*!
+ \enum QPixelFormat::AlphaPosition
+
+ This enum type is used to describe the alpha channels position relative to the
+ color channels.
+
+ \value AtBeginning The alpha channel will be put in front of the color
+ channels . E.g. ARGB.
+
+ \value AtEnd The alpha channel will be put in the back of the color
+ channels. E.g. RGBA.
+*/
+
+/*!
+ \enum QPixelFormat::AlphaPremultiplied
+
+ This enum type describes the boolean state if the alpha channel is multiplied
+ into the color channels or not.
+
+ \value NotPremultiplied The alpha channel is not multiplied into the color channels.
+
+ \value Premultiplied The alpha channel is multiplied into the color channels.
+*/
+
+/*!
+ \enum QPixelFormat::TypeInterpretation
+
+ This enum describes how each pixel is interpreted. If a pixel is read as a
+ full 32 bit unsigned integer and then each channel is masked out, or if
+ each byte is read as unsigned char values. Typically QImage formats
+ interpret one pixel as an unsigned integer and then the color channels are
+ masked out. OpenGL on the other hand typically interpreted pixels "one byte
+ after the other", Ie. unsigned byte.
+
+ QImage also have the format Format_RGBA8888 (and its derivatives), where
+ the pixels are interpreted as unsigned bytes. OpenGL has extensions that makes it
+ possible to upload pixel buffers in an unsigned integer format.
+
+ \image qpixelformat-argb32buffer.png An unsigned integer ARGB32 pixel.
+
+ The image above shows a ARGB pixel in memory read as an unsigned integer.
+ However, if this pixel was read byte for byte on a little endian system the
+ first byte would be the byte containing the B-channel. The next byte would
+ be the G-channel, then the R-channel and finally the A-channel. This shows
+ that on little endian systems, how each pixel is interpreted is significant
+ for integer formats. This is not the case on big endian systems.
+
+ \value UnsignedInteger
+ \value UnsignedShort
+ \value UnsignedByte
+ \value FloatingPoint
+*/
+
+/*!
+ \enum QPixelFormat::ByteOrder
+
+ This enum describes the ByteOrder of the pixel format. This enum is mostly
+ ignored but have some use cases for YUV formats. BGR formats have their own
+ color model, and should not be described by using the opposite endianness
+ on an RGB format.
+
+ \value LittleEndian The byte order is little endian.
+ \value BigEndian The byte order is big endian.
+ \value CurrentSystemEndian This enum will not be stored, but is converted in
+ the constructor to the endian enum that matches
+ the enum of the current system.
+
+*/
+
+/*!
+ \enum QPixelFormat::YUVLayout
+
+ YUV is not represented by describing the size of the color channels. This is
+ because YUV often use macro pixels, making the concept of sperate color channels
+ invalid. Instead the different YUV layouts are described with this enum.
+
+ \value YUV444
+ \value YUV422
+ \value YUV411
+ \value YUV420P
+ \value YUV420SP
+ \value YV12
+ \value UYVY
+ \value YUYV
+ \value NV12
+ \value NV21
+ \value IMC1
+ \value IMC2
+ \value IMC3
+ \value IMC4
+ \value Y8
+ \value Y16
+*/
+
+/*!
+ \fn QPixelFormat::QPixelFormat()
+
+ Creates a null pixelformat. This format maps to QImage::Format_Invalid.
+*/
+
+/*!
+ \fn QPixelFormat::QPixelFormat(ColorModel colorModel,
+ uchar firstSize,
+ uchar secondSize,
+ uchar thirdSize,
+ uchar fourthSize,
+ uchar fifthSize,
+ uchar alphaSize,
+ AlphaUsage alphaUsage,
+ AlphaPosition alphaPosition,
+ AlphaPremultiplied premultiplied,
+ TypeInterpretation typeInterpretation,
+ ByteOrder byteOrder = CurrentSystemEndian,
+ uchar subEnum = 0)
+
+ Creates a QPixelFormat which assigns its data to the attributes.
+ \a colorModel will be put into a buffer which is 4 bits long.
+
+ \a firstSize \a secondSize \a thirdSize \a fourthSize \a fifthSize \a
+ alphaSize are all meant to represent the size of a channel. The channels will
+ be used for different uses dependent on the \a colorModel. For RGB the
+ firstSize will represent the Red channel. On CMYK it will represent the
+ value of the Cyan channel.
+
+ \a alphaUsage represents if the alpha channel is used or not.
+
+ \a alphaPosition is the position of the alpha channel.
+
+ \a premultiplied represents if the alpha channel is already multiplied with
+ the color channels.
+
+ \a typeInterpretation is how the pixel is interpreted.
+
+ \a byteOrder represents the endianness of the pixelformat. This defaults to
+ CurrentSystemEndian.
+
+ \a subEnum is used for colorModels that have to store some extra
+ information with supplying an extra enum. This is used by YUV to store the
+ YUV type The default value is 0.
+*/
+
+Q_STATIC_ASSERT(sizeof(QPixelFormatRgb) == sizeof(QPixelFormat));
+
+/*!
+ \class QPixelFormatRgb
+ \inmodule QtGui
+ \since 5.4
+ \brief QPixelFormatRgb is a helper class for creating pixel formats with
+ the rgb color model
+
+ The size of QPixelFormatRgb is guaranteed to be the size of QPixelFormat.
+*/
+
+/*!
+ \fn QPixelFormatRgb::QPixelFormatRgb(uchar redSize,
+ uchar greenSize,
+ uchar blueSize,
+ uchar alphaSize,
+ AlphaUsage alphaUsage,
+ AlphaPosition alphaPosition,
+ AlphaPremultiplied premultiplied = NotPremultiplied,
+ TypeInterpretation typeInterpretation = UnsignedInteger)
+
+ Constructor making an RGB pixelformat. \a redSize \a greenSize \a
+ blueSize represent the size of each color channel. \a alphaSize describes
+ the alpha channel size and its position is described with \a alphaPosition.
+ \a alphaUsage is used to determine if the alpha channel is used or not.
+ Setting the alpha channel size to 8 and alphaUsage to IgnoresAlpha is how
+ it is possible to create a 32 bit format where the rgb channels only use 24
+ bits combined. \a premultiplied \a typeInterpretation are
+ accessible with accessors with the same name.
+
+ \sa TypeInterpretation
+*/
+
+Q_STATIC_ASSERT(sizeof(QPixelFormatGrayScale) == sizeof(QPixelFormat));
+/*!
+ \class QPixelFormatGrayScale
+ \inmodule QtGui
+ \since 5.4
+ \brief QPixelFormatGrayScale is a helper class for creating pixel formats with
+ the gray scale color model.
+
+ The size of QPixelFormatGrayScale is guaranteed to be the size of QPixelFormat.
+*/
+
+/*!
+ \fn QPixelFormatGrayScale::QPixelFormatGrayScale(uchar channelSize,
+ TypeInterpretation typeInterpretation = UnsignedInteger)
+
+ Constructor for creating a Grayscale format. Monochrome formats can be
+ described by passing 1 to \a channelSize. Its also possible to define very
+ accurate greyscale formats using doubles to describe each pixel by passing 8
+ as \a channelSize and FloatingPoint as \a typeInterpretation.
+
+ \sa TypeInterpretation
+*/
+
+Q_STATIC_ASSERT(sizeof(QPixelFormatCmyk) == sizeof(QPixelFormat));
+/*!
+ \class QPixelFormatCmyk
+ \inmodule QtGui
+ \since 5.4
+ \brief QPixelFormatCmyk is a helper class for creating pixel formats with
+ the CMYK color model
+
+ The size of QPixelFormatCmyk is guaranteed to be the size of QPixelFormat.
+*/
+
+/*!
+ \fn QPixelFormatCmyk::QPixelFormatCmyk(uchar channelSize,
+ uchar alphaSize = 0,
+ AlphaUsage alphaUsage = IgnoresAlpha,
+ AlphaPosition alphaPosition = AtBeginning,
+ TypeInterpretation typeInterpretation = UnsignedInteger)
+
+ Constructor for creating CMYK formats. The channel count will be 4 or
+ 5 depending on if \a alphaSize is bigger than zero or not. The CMYK color
+ channels will all be set to the value of \a channelSize.
+
+ \a alphaUsage \a alphaPosition and \a typeInterpretation are all accessible with
+ the accessors with the same name.
+
+ \sa TypeInterpretation
+*/
+
+Q_STATIC_ASSERT(sizeof(QPixelFormatHsl) == sizeof(QPixelFormat));
+/*!
+ \class QPixelFormatHsl
+ \inmodule QtGui
+ \since 5.4
+ \brief QPixelFormatHsl is a helper class for creating pixel formats with
+ the HSL color model.
+
+ The size of QPixelFormatHsl is guaranteed to be the size of QPixelFormat.
+*/
+
+/*!
+ \fn QPixelFormatHsl::QPixelFormatHsl(uchar channelSize,
+ uchar alphaSize = 0,
+ AlphaUsage alphaUsage = IgnoresAlpha,
+ AlphaPosition alphaPosition = AtBeginning,
+ TypeInterpretation typeInterpretation = FloatingPoint)
+
+ Constructor for creating HSL formats. The channel count will be 3 or 4
+ depending on if \a alphaSize is bigger than 0.
+
+ \a channelSize will set the hueSize saturationSize and lightnessSize to the same value.
+
+ \a alphaUsage \a alphaPosition and \a typeInterpretation are all accessible with
+ the accessors with the same name.
+*/
+
+Q_STATIC_ASSERT(sizeof(QPixelFormatHsv) == sizeof(QPixelFormat));
+/*!
+ \class QPixelFormatHsv
+ \inmodule QtGui
+ \since 5.4
+ \brief QPixelFormatHsv is a helper class for creating pixel formats with
+ the HSV color model.
+
+ The size of QPixelFormatHsv is guaranteed to be the size of QPixelFormat.
+*/
+
+/*!
+ \fn QPixelFormatHsv::QPixelFormatHsv(uchar channelSize,
+ uchar alphaSize = 0,
+ AlphaUsage alphaUsage = IgnoresAlpha,
+ AlphaPosition alphaPosition = AtBeginning,
+ TypeInterpretation typeInterpretation = FloatingPoint)
+
+ Constructor for creating HSV formats. The channel count will be 3 or 4
+ depending on if \a alphaSize is bigger than 0.
+
+ \a channelSize will set the hueSize saturationSize and brightnessSize to the same value.
+
+ \a alphaUsage \a alphaPosition and \a typeInterpretation are all accessible with
+ the accessors with the same name.
+*/
+
+Q_STATIC_ASSERT(sizeof(QPixelFormatYuv) == sizeof(QPixelFormat));
+/*!
+ \class QPixelFormatYuv
+ \inmodule QtGui
+ \since 5.4
+ \brief QPixelFormatYuv is a helper class for creating pixel formats with
+ the YUV color model.
+
+ The size of QPixelFormatYuv is guaranteed to be the size of QPixelFormat.
+*/
+
+/*!
+ \fn QPixelFormatYuv::QPixelFormatYuv(YUVLayout yuvLayout,
+ uchar alphaSize = 0,
+ AlphaUsage alphaUsage = IgnoresAlpha,
+ AlphaPosition alphaPosition = AtBeginning,
+ AlphaPremultiplied premultiplied = NotPremultiplied,
+ TypeInterpretation typeInterpretation = UnsignedByte,
+ ByteOrder byteOrder = LittleEndian)
+
+ Constructor for creating a QPixelFormat describing a YUV format with
+ \a yuvLayout. \a alphaSize describes the size of a potential alpha channel
+ and is position is described with \a alphaPosition. The "first" "second" ..
+ "fifth" channels are all set to 0. \a alphaUsage \a premultiplied \a
+ typeInterpretation and \a byteOrder will work as with other formats.
+*/
+
+/*!
+ \fn ColorModel QPixelFormat::colorModel() const
+
+ Accessor function for getting the colorModel.
+*/
+
+/*!
+ \fn uchar QPixelFormat::channelCount() const
+
+ Accessor function for getting the channelCount. Channel Count is deduced
+ by color channels with a size > 0 and if the size of the alpha channel is > 0.
+*/
+
+/*!
+ \fn uchar QPixelFormat::redSize() const
+
+ Accessor function for the size of the red color channel.
+*/
+
+/*!
+ \fn uchar QPixelFormat::greenSize() const
+
+ Accessor function for the size of the green color channel.
+*/
+
+/*!
+ \fn uchar QPixelFormat::blueSize() const
+
+ Accessor function for the size of the blue color channel.
+*/
+
+/*!
+ \fn uchar QPixelFormat::cyanSize() const
+
+ Accessor function for the cyan color channel.
+*/
+
+/*!
+ \fn uchar QPixelFormat::magentaSize() const
+
+ Accessor function for the megenta color channel.
+*/
+
+/*!
+ \fn uchar QPixelFormat::yellowSize() const
+
+ Accessor function for the yellow color channel.
+*/
+
+/*!
+ \fn uchar QPixelFormat::blackSize() const
+
+ Accessor function for the black/key color channel.
+*/
+
+/*!
+ \fn uchar QPixelFormat::hueSize() const
+
+ Accessor function for the hue channel size.
+*/
+
+/*!
+ \fn uchar QPixelFormat::saturationSize() const
+
+ Accessor function for the saturation channel size.
+*/
+
+/*!
+ \fn uchar QPixelFormat::lightnessSize() const
+
+ Accessor function for the lightness channel size.
+*/
+
+/*!
+ \fn uchar QPixelFormat::brightnessSize() const
+
+ Accessor function for the brightness channel size.
+*/
+
+/*!
+ \fn uchar QPixelFormat::alphaSize() const
+
+ Accessor function for the alpha channel size.
+*/
+
+/*!
+ \fn uchar QPixelFormat::bitsPerPixel() const
+
+ Accessor function for the bits used per pixel. This function returns the
+ sum of the color channels + the size of the alpha channel.
+*/
+
+/*!
+ \fn AlphaPremultiplied QPixelFormat::premultiplied() const
+
+ Accessor function for the AlphaPremultiplied enum. This indicates if the
+ alpha channel is multiplied in to the color channels.
+
+*/
+
+/*!
+ \fn TypeInterpretation QPixelFormat::typeInterpretation() const
+
+ Accessor function for the type representation of a color channel or a pixel.
+
+ \sa TypeInterpretation
+*/
+
+/*!
+ \fn ByteOrder QPixelFormat::byteOrder() const
+
+ The byte order is almost always set the the byte order of the current
+ system. However, it can be useful to describe some YUV formats. This
+ function should never return QPixelFormat::CurrentSystemEndian as this
+ value is translated to a endian value in the constructor.
+*/
+
+/*!
+ \fn AlphaUsage QPixelFormat::alphaUsage() const
+
+ Accessor function for alphaUsage.
+*/
+
+/*!
+ \fn AlphaPosition QPixelFormat::alphaPosition() const
+
+ Accessor function for alphaPosition.
+*/
+
+/*!
+ \fn YUVLayout QPixelFormat::yuvLayout() const
+
+ Accessor function for the YUVLayout. It is difficult to describe the color
+ channels of a YUV pixel format since YUV color model uses macro pixels.
+ Instead the layout of the pixels are stored as an enum.
+*/
+
+/*!
+ \fn uchar QPixelFormat::subEnum() const
+
+ Accessor for the datapart which contains subEnums
+ This is the same as the yuvLayout() function.
+
+ \sa yuvLayout()
+ \internal
+*/
+
+Q_STATIC_ASSERT(sizeof(QPixelFormat) == sizeof(quint64));
+
+
+namespace QtPrivate {
+ QPixelFormat QPixelFormat_createYUV(QPixelFormat::YUVLayout yuvLayout,
+ uchar alphaSize,
+ QPixelFormat::AlphaUsage alphaUsage,
+ QPixelFormat::AlphaPosition alphaPosition,
+ QPixelFormat::AlphaPremultiplied premultiplied,
+ QPixelFormat::TypeInterpretation typeInterpretation,
+ QPixelFormat::ByteOrder byteOrder)
+ {
+ uchar bits_per_pixel = 0;
+ switch (yuvLayout) {
+ case QPixelFormat::YUV444:
+ bits_per_pixel = 24;
+ break;
+ case QPixelFormat::YUV422:
+ bits_per_pixel = 16;
+ break;
+ case QPixelFormat::YUV411:
+ case QPixelFormat::YUV420P:
+ case QPixelFormat::YUV420SP:
+ case QPixelFormat::YV12:
+ bits_per_pixel = 12;
+ break;
+ case QPixelFormat::UYVY:
+ case QPixelFormat::YUYV:
+ bits_per_pixel = 16;
+ break;
+ case QPixelFormat::NV12:
+ case QPixelFormat::NV21:
+ bits_per_pixel = 12;
+ break;
+ case QPixelFormat::IMC1:
+ case QPixelFormat::IMC2:
+ case QPixelFormat::IMC3:
+ case QPixelFormat::IMC4:
+ bits_per_pixel = 12;
+ break;
+ case QPixelFormat::Y8:
+ bits_per_pixel = 8;
+ break;
+ case QPixelFormat::Y16:
+ bits_per_pixel = 16;
+ break;
+ }
+
+ return QPixelFormat(QPixelFormat::YUV,
+ 0, 0, 0, 0,
+ bits_per_pixel,
+ alphaSize,
+ alphaUsage,
+ alphaPosition,
+ premultiplied,
+ typeInterpretation,
+ byteOrder,
+ yuvLayout);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qpixelformat.h b/src/gui/kernel/qpixelformat.h
new file mode 100644
index 0000000000..0e5df679f8
--- /dev/null
+++ b/src/gui/kernel/qpixelformat.h
@@ -0,0 +1,452 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPIXELFORMAT_H
+#define QPIXELFORMAT_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QPixelFormat
+{
+public:
+ enum ColorModel {
+ RGB,
+ BGR,
+ Indexed,
+ Grayscale,
+ CMYK,
+ HSL,
+ HSV,
+ YUV
+ };
+
+ enum AlphaUsage {
+ UsesAlpha,
+ IgnoresAlpha
+ };
+
+ enum AlphaPosition {
+ AtBeginning,
+ AtEnd
+ };
+
+ enum AlphaPremultiplied {
+ NotPremultiplied,
+ Premultiplied
+ };
+
+ enum TypeInterpretation {
+ UnsignedInteger,
+ UnsignedShort,
+ UnsignedByte,
+ FloatingPoint
+ };
+
+ enum YUVLayout {
+ YUV444,
+ YUV422,
+ YUV411,
+ YUV420P,
+ YUV420SP,
+ YV12,
+ UYVY,
+ YUYV,
+ NV12,
+ NV21,
+ IMC1,
+ IMC2,
+ IMC3,
+ IMC4,
+ Y8,
+ Y16
+ };
+
+ enum ByteOrder {
+ LittleEndian,
+ BigEndian,
+ CurrentSystemEndian
+ };
+
+ Q_DECL_CONSTEXPR inline QPixelFormat() Q_DECL_NOTHROW;
+ Q_DECL_CONSTEXPR inline QPixelFormat(ColorModel colorModel,
+ uchar firstSize,
+ uchar secondSize,
+ uchar thirdSize,
+ uchar fourthSize,
+ uchar fifthSize,
+ uchar alphaSize,
+ AlphaUsage alphaUsage,
+ AlphaPosition alphaPosition,
+ AlphaPremultiplied premultiplied,
+ TypeInterpretation typeInterpretation,
+ ByteOrder byteOrder = CurrentSystemEndian,
+ uchar subEnum = 0) Q_DECL_NOTHROW;
+
+ Q_DECL_CONSTEXPR inline ColorModel colorModel() const Q_DECL_NOTHROW { return ColorModel(model); }
+ Q_DECL_CONSTEXPR inline uchar channelCount() const Q_DECL_NOTHROW { return (first > 0) +
+ (second > 0) +
+ (third > 0) +
+ (fourth > 0) +
+ (fifth > 0) +
+ (alpha > 0); }
+
+ Q_DECL_CONSTEXPR inline uchar redSize() const Q_DECL_NOTHROW { return first; }
+ Q_DECL_CONSTEXPR inline uchar greenSize() const Q_DECL_NOTHROW { return second; }
+ Q_DECL_CONSTEXPR inline uchar blueSize() const Q_DECL_NOTHROW { return third; }
+
+ Q_DECL_CONSTEXPR inline uchar cyanSize() const Q_DECL_NOTHROW { return first; }
+ Q_DECL_CONSTEXPR inline uchar magentaSize() const Q_DECL_NOTHROW { return second; }
+ Q_DECL_CONSTEXPR inline uchar yellowSize() const Q_DECL_NOTHROW { return third; }
+ Q_DECL_CONSTEXPR inline uchar blackSize() const Q_DECL_NOTHROW { return fourth; }
+
+ Q_DECL_CONSTEXPR inline uchar hueSize() const Q_DECL_NOTHROW { return first; }
+ Q_DECL_CONSTEXPR inline uchar saturationSize() const Q_DECL_NOTHROW { return second; }
+ Q_DECL_CONSTEXPR inline uchar lightnessSize() const Q_DECL_NOTHROW { return third; }
+ Q_DECL_CONSTEXPR inline uchar brightnessSize() const Q_DECL_NOTHROW { return third; }
+
+ Q_DECL_CONSTEXPR inline uchar alphaSize() const Q_DECL_NOTHROW { return alpha; }
+
+ Q_DECL_CONSTEXPR inline uchar bitsPerPixel() const Q_DECL_NOTHROW { return first +
+ second +
+ third +
+ fourth +
+ fifth +
+ alpha; }
+
+ Q_DECL_CONSTEXPR inline AlphaUsage alphaUsage() const Q_DECL_NOTHROW { return AlphaUsage(alpha_usage); }
+ Q_DECL_CONSTEXPR inline AlphaPosition alphaPosition() const Q_DECL_NOTHROW { return AlphaPosition(alpha_position); }
+ Q_DECL_CONSTEXPR inline AlphaPremultiplied premultiplied() const Q_DECL_NOTHROW { return AlphaPremultiplied(premul); }
+ Q_DECL_CONSTEXPR inline TypeInterpretation typeInterpretation() const Q_DECL_NOTHROW { return TypeInterpretation(type_interpretation); }
+ Q_DECL_CONSTEXPR inline ByteOrder byteOrder() const Q_DECL_NOTHROW { return ByteOrder(byte_order); }
+
+ Q_DECL_CONSTEXPR inline YUVLayout yuvLayout() const Q_DECL_NOTHROW { return YUVLayout(sub_enum); }
+ Q_DECL_CONSTEXPR inline uchar subEnum() const Q_DECL_NOTHROW { return sub_enum; }
+
+protected:
+ quint64 model : 4;
+ quint64 first : 6;
+ quint64 second : 6;
+ quint64 third : 6;
+ quint64 fourth : 6;
+ quint64 fifth : 6;
+ quint64 alpha : 6;
+ quint64 alpha_usage : 1;
+ quint64 alpha_position : 1;
+ quint64 premul: 1;
+ quint64 type_interpretation : 4;
+ quint64 byte_order : 2;
+ quint64 sub_enum : 6;
+ quint64 unused : 8;
+
+ friend Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline bool operator==(const QPixelFormat &fmt1, const QPixelFormat &fmt2);
+ friend Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline bool operator!=(const QPixelFormat &fmt1, const QPixelFormat &fmt2);
+};
+Q_DECLARE_TYPEINFO(QPixelFormat, Q_PRIMITIVE_TYPE);
+
+class QPixelFormatRgb : public QPixelFormat
+{
+public:
+ Q_DECL_CONSTEXPR
+ inline QPixelFormatRgb(uchar redSize,
+ uchar greenSize,
+ uchar blueSize,
+ uchar alphaSize,
+ AlphaUsage alphaUsage,
+ AlphaPosition alphaPosition,
+ AlphaPremultiplied premultiplied = NotPremultiplied,
+ TypeInterpretation typeInterpretation = UnsignedInteger) Q_DECL_NOTHROW;
+};
+
+class QPixelFormatGrayScale : public QPixelFormat
+{
+public:
+ Q_DECL_CONSTEXPR
+ inline QPixelFormatGrayScale(uchar bufferSize,
+ TypeInterpretation typeInterpretation = UnsignedInteger) Q_DECL_NOTHROW;
+};
+
+class QPixelFormatCmyk : public QPixelFormat
+{
+public:
+ Q_DECL_CONSTEXPR
+ inline QPixelFormatCmyk(uchar channelSize,
+ uchar alphaSize = 0,
+ AlphaUsage alphaUsage = IgnoresAlpha,
+ AlphaPosition alphaPosition = AtBeginning,
+ TypeInterpretation typeInterpretation = UnsignedInteger) Q_DECL_NOTHROW;
+};
+
+class QPixelFormatHsl : public QPixelFormat
+{
+public:
+ Q_DECL_CONSTEXPR
+ inline QPixelFormatHsl(uchar channelSize,
+ uchar alphaSize = 0,
+ AlphaUsage alphaUsage = IgnoresAlpha,
+ AlphaPosition alphaPosition = AtBeginning,
+ TypeInterpretation typeInterpretation = FloatingPoint) Q_DECL_NOTHROW;
+};
+
+class QPixelFormatHsv : public QPixelFormat
+{
+public:
+ Q_DECL_CONSTEXPR
+ inline QPixelFormatHsv(uchar channelSize,
+ uchar alphaSize = 0,
+ AlphaUsage alphaUsage = IgnoresAlpha,
+ AlphaPosition alphaPosition = AtBeginning,
+ TypeInterpretation typeInterpretation = FloatingPoint) Q_DECL_NOTHROW;
+};
+
+namespace QtPrivate {
+ QPixelFormat Q_GUI_EXPORT QPixelFormat_createYUV(QPixelFormat::YUVLayout yuvLayout,
+ uchar alphaSize,
+ QPixelFormat::AlphaUsage alphaUsage,
+ QPixelFormat::AlphaPosition alphaPosition,
+ QPixelFormat::AlphaPremultiplied premultiplied,
+ QPixelFormat::TypeInterpretation typeInterpretation,
+ QPixelFormat::ByteOrder byteOrder);
+}
+
+class QPixelFormatYuv : public QPixelFormat
+{
+public:
+ inline QPixelFormatYuv(YUVLayout yuvLayout,
+ uchar alphaSize = 0,
+ AlphaUsage alphaUsage = IgnoresAlpha,
+ AlphaPosition alphaPosition = AtBeginning,
+ AlphaPremultiplied premultiplied = NotPremultiplied,
+ TypeInterpretation typeInterpretation = UnsignedByte,
+ ByteOrder byteOrder = LittleEndian);
+};
+
+Q_DECL_CONSTEXPR
+QPixelFormat::QPixelFormat() Q_DECL_NOTHROW
+ : model(0)
+ , first(0)
+ , second(0)
+ , third(0)
+ , fourth(0)
+ , fifth(0)
+ , alpha(0)
+ , alpha_usage(0)
+ , alpha_position(0)
+ , premul(0)
+ , type_interpretation(0)
+ , byte_order(0)
+ , sub_enum(0)
+ , unused(0)
+{
+}
+
+Q_DECL_CONSTEXPR
+QPixelFormat::QPixelFormat(ColorModel mdl,
+ uchar firstSize,
+ uchar secondSize,
+ uchar thirdSize,
+ uchar fourthSize,
+ uchar fifthSize,
+ uchar alfa,
+ AlphaUsage usage,
+ AlphaPosition position,
+ AlphaPremultiplied premult,
+ TypeInterpretation typeInterp,
+ ByteOrder b_order,
+ uchar s_enum) Q_DECL_NOTHROW
+ : model(mdl)
+ , first(firstSize)
+ , second(secondSize)
+ , third(thirdSize)
+ , fourth(fourthSize)
+ , fifth(fifthSize)
+ , alpha(alfa)
+ , alpha_usage(usage)
+ , alpha_position(position)
+ , premul(premult)
+ , type_interpretation(typeInterp)
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ , byte_order(b_order == CurrentSystemEndian ? LittleEndian : b_order)
+#else
+ , byte_order(b_order == CurrentSystemEndian ? BigEndian : b_order)
+#endif
+ , sub_enum(s_enum)
+ , unused(0)
+{
+}
+
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline bool operator==(const QPixelFormat &fmt1, const QPixelFormat &fmt2)
+{
+ return fmt1.model == fmt2.model
+ && fmt1.first == fmt2.first
+ && fmt1.second == fmt2.second
+ && fmt1.third == fmt2.third
+ && fmt1.fourth == fmt2.fourth
+ && fmt1.fifth == fmt2.fifth
+ && fmt1.alpha == fmt2.alpha
+ && fmt1.alpha_usage == fmt2.alpha_usage
+ && fmt1.alpha_position == fmt2.alpha_position
+ && fmt1.premul == fmt2.premul
+ && fmt1.type_interpretation == fmt2.type_interpretation
+ && fmt1.byte_order == fmt2.byte_order
+ && fmt1.sub_enum == fmt2.sub_enum
+ && fmt1.unused == fmt2.unused;
+}
+
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline bool operator!=(const QPixelFormat &fmt1, const QPixelFormat &fmt2)
+{ return !(fmt1 == fmt2); }
+
+Q_DECL_CONSTEXPR
+QPixelFormatRgb::QPixelFormatRgb(uchar red,
+ uchar green,
+ uchar blue,
+ uchar alfa,
+ AlphaUsage usage,
+ AlphaPosition position,
+ AlphaPremultiplied pmul,
+ TypeInterpretation typeInt) Q_DECL_NOTHROW
+ : QPixelFormat(RGB,
+ red,
+ green,
+ blue,
+ 0,
+ 0,
+ alfa,
+ usage,
+ position,
+ pmul,
+ typeInt)
+{ }
+
+Q_DECL_CONSTEXPR
+QPixelFormatGrayScale::QPixelFormatGrayScale(uchar channelSize,
+ TypeInterpretation typeInt) Q_DECL_NOTHROW
+ : QPixelFormat(Grayscale,
+ channelSize,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ IgnoresAlpha,
+ AtBeginning,
+ NotPremultiplied,
+ typeInt)
+{ }
+
+Q_DECL_CONSTEXPR
+QPixelFormatCmyk::QPixelFormatCmyk(uchar channelSize,
+ uchar alfa,
+ AlphaUsage usage,
+ AlphaPosition position,
+ TypeInterpretation typeInt) Q_DECL_NOTHROW
+ : QPixelFormat(CMYK,
+ channelSize,
+ channelSize,
+ channelSize,
+ channelSize,
+ 0,
+ alfa,
+ usage,
+ position,
+ NotPremultiplied,
+ typeInt)
+{ }
+
+Q_DECL_CONSTEXPR
+QPixelFormatHsl::QPixelFormatHsl(uchar channelSize,
+ uchar alfa,
+ AlphaUsage usage,
+ AlphaPosition position,
+ TypeInterpretation typeInt) Q_DECL_NOTHROW
+ : QPixelFormat(HSL,
+ channelSize,
+ channelSize,
+ channelSize,
+ 0,
+ 0,
+ alfa,
+ usage,
+ position,
+ NotPremultiplied,
+ typeInt)
+{ }
+
+Q_DECL_CONSTEXPR
+QPixelFormatHsv::QPixelFormatHsv(uchar channelSize,
+ uchar alfa,
+ AlphaUsage usage,
+ AlphaPosition position,
+ TypeInterpretation typeInt) Q_DECL_NOTHROW
+ : QPixelFormat(HSV,
+ channelSize,
+ channelSize,
+ channelSize,
+ 0,
+ 0,
+ alfa,
+ usage,
+ position,
+ NotPremultiplied,
+ typeInt)
+{ }
+
+QPixelFormatYuv::QPixelFormatYuv(YUVLayout layout,
+ uchar alfa,
+ AlphaUsage usage,
+ AlphaPosition position,
+ AlphaPremultiplied p_mul,
+ TypeInterpretation typeInt,
+ ByteOrder b_order)
+ : QPixelFormat(QtPrivate::QPixelFormat_createYUV(layout,
+ alfa,
+ usage,
+ position,
+ p_mul,
+ typeInt,
+ b_order))
+
+{ }
+
+QT_END_NAMESPACE
+
+#endif //QPIXELFORMAT_H
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
index da192a8e25..f20482a859 100644
--- a/src/gui/kernel/qplatformintegration.cpp
+++ b/src/gui/kernel/qplatformintegration.cpp
@@ -271,13 +271,32 @@ QPlatformPixmap *QPlatformIntegration::createPlatformPixmap(QPlatformPixmap::Pix
}
#ifndef QT_NO_OPENGL
+/*!
+ Factory function for QPlatformOpenGLContext. The \a context parameter is a pointer to
+ the context for which a platform-specific context backend needs to be
+ created. Configuration settings like the format, share context and screen have to be
+ taken from this QOpenGLContext and the resulting platform context is expected to be
+ backed by a native context that fulfills these criteria.
+
+ If the context has native handles set, no new native context is expected to be created.
+ Instead, the provided handles have to be used. In this case the ownership of the handle
+ must not be taken and the platform implementation is not allowed to destroy the native
+ context. Configuration parameters like the format are also to be ignored. Instead, the
+ platform implementation is responsible for querying the configuriation from the provided
+ native context.
+
+ Returns a pointer to a QPlatformOpenGLContext instance or \c NULL if the context could
+ not be created.
+
+ \sa QOpenGLContext
+*/
QPlatformOpenGLContext *QPlatformIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
Q_UNUSED(context);
qWarning("This plugin does not support createPlatformOpenGLContext!");
return 0;
}
-#endif
+#endif // QT_NO_OPENGL
/*!
Factory function for QPlatformSharedGraphicsCache. This function will return 0 if the platform
diff --git a/src/gui/kernel/qplatformnativeinterface.cpp b/src/gui/kernel/qplatformnativeinterface.cpp
index 6571a47849..2e5485f1c2 100644
--- a/src/gui/kernel/qplatformnativeinterface.cpp
+++ b/src/gui/kernel/qplatformnativeinterface.cpp
@@ -118,6 +118,12 @@ QPlatformNativeInterface::NativeResourceForBackingStoreFunction QPlatformNativeI
return 0;
}
+QFunctionPointer QPlatformNativeInterface::platformFunction(const QByteArray &function) const
+{
+ Q_UNUSED(function);
+ return Q_NULLPTR;
+}
+
/*!
Contains generic window properties that the platform may utilize.
*/
diff --git a/src/gui/kernel/qplatformnativeinterface.h b/src/gui/kernel/qplatformnativeinterface.h
index eaa24a9e55..58d13c4320 100644
--- a/src/gui/kernel/qplatformnativeinterface.h
+++ b/src/gui/kernel/qplatformnativeinterface.h
@@ -85,6 +85,8 @@ public:
virtual NativeResourceForWindowFunction nativeResourceFunctionForWindow(const QByteArray &resource);
virtual NativeResourceForBackingStoreFunction nativeResourceFunctionForBackingStore(const QByteArray &resource);
+ virtual QFunctionPointer platformFunction(const QByteArray &function) const;
+
virtual QVariantMap windowProperties(QPlatformWindow *window) const;
virtual QVariant windowProperty(QPlatformWindow *window, const QString &name) const;
virtual QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const;
diff --git a/src/gui/kernel/qplatformsystemtrayicon_qpa.cpp b/src/gui/kernel/qplatformsystemtrayicon.cpp
index bc37f99210..bc37f99210 100644
--- a/src/gui/kernel/qplatformsystemtrayicon_qpa.cpp
+++ b/src/gui/kernel/qplatformsystemtrayicon.cpp
diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp
index faaf418522..bb7b690992 100644
--- a/src/gui/kernel/qplatformwindow.cpp
+++ b/src/gui/kernel/qplatformwindow.cpp
@@ -474,6 +474,29 @@ QString QPlatformWindow::formatWindowTitle(const QString &title, const QString &
}
/*!
+ Helper function for finding the new screen for \a newGeometry in response to
+ a geometry changed event. Returns the new screen if the window was moved to
+ another virtual sibling. If the screen changes, the platform plugin should call
+ QWindowSystemInterface::handleWindowScreenChanged().
+ \note: The current screen will always be returned for child windows since
+ they should never signal screen changes.
+
+ \since 5.4
+ \sa QWindowSystemInterface::handleWindowScreenChanged()
+*/
+QPlatformScreen *QPlatformWindow::screenForGeometry(const QRect &newGeometry) const
+{
+ QPlatformScreen *currentScreen = screen();
+ if (!parent() && !currentScreen->geometry().intersects(newGeometry)) {
+ Q_FOREACH (QPlatformScreen* screen, currentScreen->virtualSiblings()) {
+ if (screen->geometry().intersects(newGeometry))
+ return screen;
+ }
+ }
+ return currentScreen;
+}
+
+/*!
Reimplement this method to set whether the window demands attention
(for example, by flashing the taskbar icon) depending on \a enabled.
diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h
index 39bd8324a0..8f0e5ff352 100644
--- a/src/gui/kernel/qplatformwindow.h
+++ b/src/gui/kernel/qplatformwindow.h
@@ -139,6 +139,7 @@ public:
protected:
static QString formatWindowTitle(const QString &title, const QString &separator);
+ QPlatformScreen *screenForGeometry(const QRect &newGeometry) const;
QScopedPointer<QPlatformWindowPrivate> d_ptr;
private:
diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp
index 70ee631fc8..90f48d4593 100644
--- a/src/gui/kernel/qscreen.cpp
+++ b/src/gui/kernel/qscreen.cpp
@@ -74,6 +74,16 @@ QScreen::QScreen(QPlatformScreen *screen)
{
}
+
+/*!
+ Destroys the screen.
+ */
+QScreen::~QScreen()
+{
+ if (qApp)
+ Q_EMIT qApp->screenRemoved(this);
+}
+
/*!
Get the platform screen handle.
*/
diff --git a/src/gui/kernel/qscreen.h b/src/gui/kernel/qscreen.h
index bdd5939657..9e439f5a20 100644
--- a/src/gui/kernel/qscreen.h
+++ b/src/gui/kernel/qscreen.h
@@ -89,6 +89,7 @@ class Q_GUI_EXPORT QScreen : public QObject
Q_PROPERTY(qreal refreshRate READ refreshRate NOTIFY refreshRateChanged)
public:
+ ~QScreen();
QPlatformScreen *handle() const;
QString name() const;
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index d6f9fad070..8159b7746e 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -156,9 +156,7 @@ QWindow::QWindow(QScreen *targetScreen)
, QSurface(QSurface::Window)
{
Q_D(QWindow);
- d->screen = targetScreen;
- if (!d->screen)
- d->screen = QGuiApplication::primaryScreen();
+ d->connectToScreen(targetScreen ? targetScreen : QGuiApplication::primaryScreen());
d->init();
}
@@ -178,10 +176,8 @@ QWindow::QWindow(QWindow *parent)
{
Q_D(QWindow);
d->parentWindow = parent;
- if (parent)
- d->screen = parent->screen();
- if (!d->screen)
- d->screen = QGuiApplication::primaryScreen();
+ if (!parent)
+ d->connectToScreen(QGuiApplication::primaryScreen());
d->init();
}
@@ -203,10 +199,8 @@ QWindow::QWindow(QWindowPrivate &dd, QWindow *parent)
{
Q_D(QWindow);
d->parentWindow = parent;
- if (parent)
- d->screen = parent->screen();
- if (!d->screen)
- d->screen = QGuiApplication::primaryScreen();
+ if (!parent)
+ d->connectToScreen(QGuiApplication::primaryScreen());
d->init();
}
@@ -215,14 +209,8 @@ QWindow::QWindow(QWindowPrivate &dd, QWindow *parent)
*/
QWindow::~QWindow()
{
- if (QGuiApplicationPrivate::focus_window == this)
- QGuiApplicationPrivate::focus_window = 0;
- if (QGuiApplicationPrivate::currentMouseWindow == this)
- QGuiApplicationPrivate::currentMouseWindow = 0;
- if (QGuiApplicationPrivate::tabletPressTarget == this)
- QGuiApplicationPrivate::tabletPressTarget = 0;
- QGuiApplicationPrivate::window_list.removeAll(this);
destroy();
+ QGuiApplicationPrivate::window_list.removeAll(this);
}
void QWindowPrivate::init()
@@ -231,11 +219,10 @@ void QWindowPrivate::init()
// If your application aborts here, you are probably creating a QWindow
// before the screen list is populated.
- if (!screen) {
+ if (!parentWindow && !topLevelScreen) {
qFatal("Cannot create window: no screens available");
exit(1);
}
- QObject::connect(screen, SIGNAL(destroyed(QObject*)), q, SLOT(screenDestroyed(QObject*)));
QGuiApplicationPrivate::window_list.prepend(q);
}
@@ -353,23 +340,57 @@ void QWindowPrivate::updateVisibility()
emit q->visibilityChanged(visibility);
}
-void QWindowPrivate::setScreen(QScreen *newScreen, bool recreate)
+inline bool QWindowPrivate::windowRecreationRequired(QScreen *newScreen) const
+{
+ Q_Q(const QWindow);
+ const QScreen *oldScreen = q->screen();
+ return oldScreen != newScreen && platformWindow
+ && !(oldScreen && oldScreen->virtualSiblings().contains(newScreen));
+}
+
+inline void QWindowPrivate::disconnectFromScreen()
+{
+ if (topLevelScreen) {
+ Q_Q(QWindow);
+ QObject::disconnect(topLevelScreen, &QObject::destroyed, q, &QWindow::screenDestroyed);
+ topLevelScreen = 0;
+ }
+}
+
+void QWindowPrivate::connectToScreen(QScreen *screen)
{
Q_Q(QWindow);
- if (newScreen != screen) {
- const bool shouldRecreate = recreate && platformWindow != 0
- && !(screen && screen->virtualSiblings().contains(newScreen));
+ disconnectFromScreen();
+ topLevelScreen = screen;
+ if (topLevelScreen)
+ QObject::connect(topLevelScreen, &QObject::destroyed, q, &QWindow::screenDestroyed);
+}
+
+void QWindowPrivate::emitScreenChangedRecursion(QScreen *newScreen)
+{
+ Q_Q(QWindow);
+ emit q->screenChanged(newScreen);
+ foreach (QObject *child, q->children()) {
+ if (child->isWindowType())
+ static_cast<QWindow *>(child)->d_func()->emitScreenChangedRecursion(newScreen);
+ }
+}
+
+void QWindowPrivate::setTopLevelScreen(QScreen *newScreen, bool recreate)
+{
+ Q_Q(QWindow);
+ if (parentWindow) {
+ qWarning() << this << Q_FUNC_INFO << '(' << newScreen << "): Attempt to set a screen on a child window.";
+ return;
+ }
+ if (newScreen != topLevelScreen) {
+ const bool shouldRecreate = recreate && windowRecreationRequired(newScreen);
if (shouldRecreate)
q->destroy();
- if (screen)
- q->disconnect(screen, SIGNAL(destroyed(QObject*)), q, SLOT(screenDestroyed(QObject*)));
- screen = newScreen;
- if (newScreen) {
- q->connect(screen, SIGNAL(destroyed(QObject*)), q, SLOT(screenDestroyed(QObject*)));
- if (shouldRecreate)
- q->create();
- }
- emit q->screenChanged(newScreen);
+ connectToScreen(newScreen);
+ if (newScreen && shouldRecreate)
+ q->create();
+ emitScreenChangedRecursion(newScreen);
}
}
@@ -436,11 +457,14 @@ void QWindow::setVisible(bool visible)
QCoreApplication::removePostedEvents(qApp, QEvent::Quit);
if (type() == Qt::Window) {
- QString &firstWindowTitle = QGuiApplicationPrivate::instance()->firstWindowTitle;
+ 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);
}
QShowEvent showEvent;
@@ -549,8 +573,20 @@ QWindow *QWindow::parent() const
void QWindow::setParent(QWindow *parent)
{
Q_D(QWindow);
+ if (d->parentWindow == parent)
+ return;
+
+ QScreen *newScreen = parent ? parent->screen() : screen();
+ if (d->windowRecreationRequired(newScreen)) {
+ qWarning() << this << Q_FUNC_INFO << '(' << parent << "): Cannot change screens (" << screen() << newScreen << ')';
+ return;
+ }
QObject::setParent(parent);
+ if (parent)
+ d->disconnectFromScreen();
+ else
+ d->connectToScreen(newScreen);
if (d->platformWindow) {
if (parent && parent->d_func()->platformWindow) {
@@ -1524,21 +1560,36 @@ void QWindow::resize(const QSize &newSize)
void QWindow::destroy()
{
Q_D(QWindow);
+ if (!d->platformWindow)
+ return;
+
QObjectList childrenWindows = children();
for (int i = 0; i < childrenWindows.size(); i++) {
QObject *object = childrenWindows.at(i);
if (object->isWindowType()) {
QWindow *w = static_cast<QWindow*>(object);
- QGuiApplicationPrivate::window_list.removeAll(w);
w->destroy();
}
}
+
+ if (QGuiApplicationPrivate::focus_window == this)
+ QGuiApplicationPrivate::focus_window = parent();
+ if (QGuiApplicationPrivate::currentMouseWindow == this)
+ QGuiApplicationPrivate::currentMouseWindow = parent();
+ if (QGuiApplicationPrivate::tabletPressTarget == this)
+ QGuiApplicationPrivate::tabletPressTarget = parent();
+
+ bool wasVisible = isVisible();
+
setVisible(false);
delete d->platformWindow;
d->resizeEventPending = true;
d->receivedExpose = false;
d->exposed = false;
d->platformWindow = 0;
+
+ if (wasVisible)
+ d->maybeQuitOnLastWindowClosed();
}
/*!
@@ -1605,15 +1656,14 @@ bool QWindow::setMouseGrabEnabled(bool grab)
/*!
Returns the screen on which the window is shown.
- The value returned will not change when the window is moved
- between virtual screens (as returned by QScreen::virtualSiblings()).
+ For child windows, this returns the screen of the corresponding top level window.
\sa setScreen(), QScreen::virtualSiblings()
*/
QScreen *QWindow::screen() const
{
Q_D(const QWindow);
- return d->screen;
+ return d->parentWindow ? d->parentWindow->screen() : d->topLevelScreen;
}
/*!
@@ -1624,6 +1674,8 @@ QScreen *QWindow::screen() const
Note that if the screen is part of a virtual desktop of multiple screens,
the window can appear on any of the screens returned by QScreen::virtualSiblings().
+ This function only works for top level windows.
+
\sa screen(), QScreen::virtualSiblings()
*/
void QWindow::setScreen(QScreen *newScreen)
@@ -1631,13 +1683,15 @@ void QWindow::setScreen(QScreen *newScreen)
Q_D(QWindow);
if (!newScreen)
newScreen = QGuiApplication::primaryScreen();
- d->setScreen(newScreen, true /* recreate */);
+ d->setTopLevelScreen(newScreen, true /* recreate */);
}
void QWindow::screenDestroyed(QObject *object)
{
Q_D(QWindow);
- if (object == static_cast<QObject *>(d->screen)) {
+ if (d->parentWindow)
+ return;
+ if (object == static_cast<QObject *>(d->topLevelScreen)) {
const bool wasVisible = isVisible();
setScreen(0);
// destroy() might have hidden our window, show it again.
@@ -1793,15 +1847,13 @@ bool QWindow::close()
if (parent())
return false;
- if (QGuiApplicationPrivate::focus_window == this)
- QGuiApplicationPrivate::focus_window = 0;
- if (QGuiApplicationPrivate::currentMouseWindow == this)
- QGuiApplicationPrivate::currentMouseWindow = 0;
+ if (!d->platformWindow)
+ return true;
- QGuiApplicationPrivate::window_list.removeAll(this);
- destroy();
- d->maybeQuitOnLastWindowClosed();
- return true;
+ bool accepted = false;
+ QWindowSystemInterface::handleCloseEvent(this, &accepted);
+ QWindowSystemInterface::flushWindowSystemEvents();
+ return accepted;
}
/*!
@@ -1947,15 +1999,10 @@ bool QWindow::event(QEvent *ev)
break;
#endif
- case QEvent::Close: {
- Q_D(QWindow);
- bool wasVisible = isVisible();
- if (ev->isAccepted()) {
+ case QEvent::Close:
+ if (ev->isAccepted())
destroy();
- if (wasVisible)
- d->maybeQuitOnLastWindowClosed();
- }
- break; }
+ break;
case QEvent::Expose:
exposeEvent(static_cast<QExposeEvent *>(ev));
@@ -2167,8 +2214,10 @@ Q_GUI_EXPORT QWindowPrivate *qt_window_private(QWindow *window)
void QWindowPrivate::maybeQuitOnLastWindowClosed()
{
- Q_Q(QWindow);
+ if (!QCoreApplication::instance())
+ return;
+ Q_Q(QWindow);
// Attempt to close the application only if this has WA_QuitOnClose set and a non-visible parent
bool quitOnClose = QGuiApplication::quitOnLastWindowClosed() && !q->parent();
@@ -2327,7 +2376,7 @@ void QWindowPrivate::setCursor(const QCursor *newCursor)
hasCursor = false;
}
// Only attempt to set cursor and emit signal if there is an actual platform cursor
- if (screen->handle()->cursor()) {
+ if (q->screen()->handle()->cursor()) {
applyCursor();
QEvent event(QEvent::CursorChange);
QGuiApplication::sendEvent(q, &event);
@@ -2338,7 +2387,7 @@ void QWindowPrivate::applyCursor()
{
Q_Q(QWindow);
if (platformWindow) {
- if (QPlatformCursor *platformCursor = screen->handle()->cursor()) {
+ if (QPlatformCursor *platformCursor = q->screen()->handle()->cursor()) {
QCursor *c = QGuiApplication::overrideCursor();
if (!c && hasCursor)
c = &cursor;
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h
index 4305edea51..0c58745735 100644
--- a/src/gui/kernel/qwindow_p.h
+++ b/src/gui/kernel/qwindow_p.h
@@ -95,7 +95,7 @@ public:
, modality(Qt::NonModal)
, blockedByModalWindow(false)
, transientParent(0)
- , screen(0)
+ , topLevelScreen(0)
#ifndef QT_NO_CURSOR
, cursor(Qt::ArrowCursor)
, hasCursor(false)
@@ -131,7 +131,11 @@ public:
void updateVisibility();
void _q_clearAlert();
- void setScreen(QScreen *newScreen, bool recreate);
+ bool windowRecreationRequired(QScreen *newScreen) const;
+ void setTopLevelScreen(QScreen *newScreen, bool recreate);
+ void connectToScreen(QScreen *topLevelScreen);
+ void disconnectFromScreen();
+ void emitScreenChangedRecursion(QScreen *newScreen);
virtual void clearFocusObject();
@@ -165,7 +169,7 @@ public:
bool blockedByModalWindow;
QPointer<QWindow> transientParent;
- QScreen *screen;
+ QScreen *topLevelScreen;
#ifndef QT_NO_CURSOR
QCursor cursor;
diff --git a/src/gui/kernel/qwindowdefs_win.h b/src/gui/kernel/qwindowdefs_win.h
index fea995a0f5..0dd027e585 100644
--- a/src/gui/kernel/qwindowdefs_win.h
+++ b/src/gui/kernel/qwindowdefs_win.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -107,7 +107,7 @@ Q_DECLARE_HANDLE(HRGN);
#ifndef HMONITOR
Q_DECLARE_HANDLE(HMONITOR);
#endif
-#ifndef HRESULT
+#ifndef _HRESULT_DEFINED
typedef long HRESULT;
#endif
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index 49ff8bcb0d..b716e84a42 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -133,11 +133,11 @@ void QWindowSystemInterface::handleWindowScreenChanged(QWindow *tlw, QScreen *sc
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
-void QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState newState)
+void QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate)
{
Q_ASSERT(QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState));
QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *e =
- new QWindowSystemInterfacePrivate::ApplicationStateChangedEvent(newState);
+ new QWindowSystemInterfacePrivate::ApplicationStateChangedEvent(newState, forcePropagate);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
@@ -629,24 +629,42 @@ void QWindowSystemInterface::handleFileOpenEvent(const QUrl &url)
QGuiApplicationPrivate::processWindowSystemEvent(&e);
}
-void QWindowSystemInterface::handleTabletEvent(QWindow *w, ulong timestamp, bool down, const QPointF &local, const QPointF &global,
- int device, int pointerType, qreal pressure, int xTilt, int yTilt,
+void QWindowSystemInterface::handleTabletEvent(QWindow *w, ulong timestamp, const QPointF &local, const QPointF &global,
+ int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt,
qreal tangentialPressure, qreal rotation, int z, qint64 uid,
Qt::KeyboardModifiers modifiers)
{
QWindowSystemInterfacePrivate::TabletEvent *e =
- new QWindowSystemInterfacePrivate::TabletEvent(w, timestamp, down, local, global, device, pointerType, pressure,
+ new QWindowSystemInterfacePrivate::TabletEvent(w, timestamp, local, global, device, pointerType, buttons, pressure,
xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
+void QWindowSystemInterface::handleTabletEvent(QWindow *w, const QPointF &local, const QPointF &global,
+ int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt,
+ qreal tangentialPressure, qreal rotation, int z, qint64 uid,
+ Qt::KeyboardModifiers modifiers)
+{
+ ulong time = QWindowSystemInterfacePrivate::eventTime.elapsed();
+ handleTabletEvent(w, time, local, global, device, pointerType, buttons, pressure,
+ xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers);
+}
+
+void QWindowSystemInterface::handleTabletEvent(QWindow *w, 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)
+{
+ handleTabletEvent(w, timestamp, local, global, device, pointerType, (down ? Qt::LeftButton : Qt::NoButton), pressure,
+ xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers);
+}
+
void QWindowSystemInterface::handleTabletEvent(QWindow *w, 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)
{
- ulong time = QWindowSystemInterfacePrivate::eventTime.elapsed();
- handleTabletEvent(w, time, down, local, global, device, pointerType, pressure,
+ handleTabletEvent(w, local, global, device, pointerType, (down ? Qt::LeftButton : Qt::NoButton), pressure,
xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers);
}
diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h
index 71feb1bcb7..1462c62e2b 100644
--- a/src/gui/kernel/qwindowsysteminterface.h
+++ b/src/gui/kernel/qwindowsysteminterface.h
@@ -148,7 +148,7 @@ public:
static void handleWindowStateChanged(QWindow *w, Qt::WindowState newState);
static void handleWindowScreenChanged(QWindow *w, QScreen *newScreen);
- static void handleApplicationStateChanged(Qt::ApplicationState newState);
+ static void handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate = false);
static void handleExposeEvent(QWindow *tlw, const QRegion &region);
@@ -172,14 +172,22 @@ public:
static void handleFileOpenEvent(const QString& fileName);
static void handleFileOpenEvent(const QUrl &url);
+ static void handleTabletEvent(QWindow *w, ulong timestamp, const QPointF &local, const QPointF &global,
+ 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 *w, const QPointF &local, const QPointF &global,
+ 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 *w, 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::KeyboardModifiers modifiers = Qt::NoModifier); // ### remove in Qt 6
static void handleTabletEvent(QWindow *w, 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::KeyboardModifiers modifiers = Qt::NoModifier); // ### remove in Qt 6
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 8e503bbf3d..89ca4064b2 100644
--- a/src/gui/kernel/qwindowsysteminterface_p.h
+++ b/src/gui/kernel/qwindowsysteminterface_p.h
@@ -176,11 +176,12 @@ public:
class ApplicationStateChangedEvent : public WindowSystemEvent {
public:
- ApplicationStateChangedEvent(Qt::ApplicationState newState)
- : WindowSystemEvent(ApplicationStateChanged), newState(newState)
+ ApplicationStateChangedEvent(Qt::ApplicationState newState, bool forcePropagate = false)
+ : WindowSystemEvent(ApplicationStateChanged), newState(newState), forcePropagate(forcePropagate)
{ }
Qt::ApplicationState newState;
+ bool forcePropagate;
};
class FlushEventsEvent : public WindowSystemEvent {
@@ -337,19 +338,19 @@ public:
class TabletEvent : public InputEvent {
public:
- static void handleTabletEvent(QWindow *w, bool down, const QPointF &local, const QPointF &global,
- int device, int pointerType, qreal pressure, int xTilt, int yTilt,
+ static void handleTabletEvent(QWindow *w, const QPointF &local, const QPointF &global,
+ 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);
- TabletEvent(QWindow *w, ulong time, bool down, const QPointF &local, const QPointF &global,
- int device, int pointerType, qreal pressure, int xTilt, int yTilt, qreal tpressure,
+ TabletEvent(QWindow *w, ulong time, const QPointF &local, const QPointF &global,
+ int device, int pointerType, Qt::MouseButtons b, qreal pressure, int xTilt, int yTilt, qreal tpressure,
qreal rotation, int z, qint64 uid, Qt::KeyboardModifiers mods)
: InputEvent(w, time, Tablet, mods),
- down(down), local(local), global(global), device(device), pointerType(pointerType),
+ buttons(b), local(local), global(global), device(device), pointerType(pointerType),
pressure(pressure), xTilt(xTilt), yTilt(yTilt), tangentialPressure(tpressure),
rotation(rotation), z(z), uid(uid) { }
- bool down;
+ Qt::MouseButtons buttons;
QPointF local;
QPointF global;
int device;
diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp
index 0b3c5b4cb9..5d7a176fe5 100644
--- a/src/gui/math3d/qmatrix4x4.cpp
+++ b/src/gui/math3d/qmatrix4x4.cpp
@@ -1542,6 +1542,52 @@ void QMatrix4x4::lookAt(const QVector3D& eye, const QVector3D& center, const QVe
#endif
/*!
+ \fn void QMatrix4x4::viewport(const QRectF &rect)
+ \overload
+
+ Sets up viewport transform for viewport bounded by \a rect and with near and far set
+ to 0 and 1 respectively.
+*/
+
+/*!
+ Multiplies this matrix by another that performs the scale and bias
+ transformation used by OpenGL to transform from normalized device
+ coordinates (NDC) to viewport (window) coordinates. That is it maps
+ points from the cube ranging over [-1, 1] in each dimension to the
+ viewport with it's near-lower-left corner at (\a left, \a bottom, \a nearPlane)
+ and with size (\a width, \a height, \a farPlane - \a nearPlane).
+
+ This matches the transform used by the fixed function OpenGL viewport
+ transform controlled by the functions glViewport() and glDepthRange().
+ */
+void QMatrix4x4::viewport(float left, float bottom, float width, float height, float nearPlane, float farPlane)
+{
+ const float w2 = width / 2.0f;
+ const float h2 = height / 2.0f;
+
+ QMatrix4x4 m(1);
+ m.m[0][0] = w2;
+ m.m[1][0] = 0.0f;
+ m.m[2][0] = 0.0f;
+ m.m[3][0] = left + w2;
+ m.m[0][1] = 0.0f;
+ m.m[1][1] = h2;
+ m.m[2][1] = 0.0f;
+ m.m[3][1] = bottom + h2;
+ m.m[0][2] = 0.0f;
+ m.m[1][2] = 0.0f;
+ m.m[2][2] = (farPlane - nearPlane) / 2.0f;
+ m.m[3][2] = (nearPlane + farPlane) / 2.0f;
+ m.m[0][3] = 0.0f;
+ m.m[1][3] = 0.0f;
+ m.m[2][3] = 0.0f;
+ m.m[3][3] = 1.0f;
+ m.flagBits = General;
+
+ *this *= m;
+}
+
+/*!
\deprecated
Flips between right-handed and left-handed coordinate systems
diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h
index d4ba7d64d8..c42ccc2dc5 100644
--- a/src/gui/math3d/qmatrix4x4.h
+++ b/src/gui/math3d/qmatrix4x4.h
@@ -148,6 +148,8 @@ public:
#ifndef QT_NO_VECTOR3D
void lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up);
#endif
+ void viewport(const QRectF &rect);
+ void viewport(float left, float bottom, float width, float height, float nearPlane = 0.0f, float farPlane = 1.0f);
void flipCoordinates();
void copyDataTo(float *values) const;
@@ -1077,6 +1079,11 @@ inline float *QMatrix4x4::data()
return *m;
}
+inline void QMatrix4x4::viewport(const QRectF &rect)
+{
+ viewport(rect.x(), rect.y(), rect.width(), rect.height());
+}
+
#ifndef QT_NO_DEBUG_STREAM
Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
#endif
diff --git a/src/gui/opengl/opengl.pri b/src/gui/opengl/opengl.pri
index cadba26797..f82401c973 100644
--- a/src/gui/opengl/opengl.pri
+++ b/src/gui/opengl/opengl.pri
@@ -2,7 +2,6 @@
contains(QT_CONFIG, opengl):CONFIG += opengl
contains(QT_CONFIG, opengles2):CONFIG += opengles2
-contains(QT_CONFIG, egl):CONFIG += egl
contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles2) {
diff --git a/src/gui/opengl/qopengl.cpp b/src/gui/opengl/qopengl.cpp
index b452c605e3..9dc8f45495 100644
--- a/src/gui/opengl/qopengl.cpp
+++ b/src/gui/opengl/qopengl.cpp
@@ -55,16 +55,17 @@ QOpenGLExtensionMatcher::QOpenGLExtensionMatcher()
{
QOpenGLContext *ctx = QOpenGLContext::currentContext();
QOpenGLFunctions *funcs = ctx->functions();
- const char *extensionStr = reinterpret_cast<const char *>(funcs->glGetString(GL_EXTENSIONS));
+ const char *extensionStr = 0;
+
+ if (ctx->isOpenGLES() || ctx->format().majorVersion() < 3)
+ extensionStr = reinterpret_cast<const char *>(funcs->glGetString(GL_EXTENSIONS));
if (extensionStr) {
QByteArray ba(extensionStr);
QList<QByteArray> extensions = ba.split(' ');
m_extensions = extensions.toSet();
-#if !defined(QT_OPENGL_3)
- }
-#else
} else {
+#ifdef QT_OPENGL_3
// clear error state
while (funcs->glGetError()) {}
@@ -82,8 +83,8 @@ QOpenGLExtensionMatcher::QOpenGLExtensionMatcher()
m_extensions.insert(str);
}
}
+#endif // QT_OPENGL_3
}
-#endif
}
QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopengl.h b/src/gui/opengl/qopengl.h
index ef5ab9aa65..f0f19a5a85 100644
--- a/src/gui/opengl/qopengl.h
+++ b/src/gui/opengl/qopengl.h
@@ -67,8 +67,13 @@
#if defined(QT_OPENGL_ES_2)
# if defined(Q_OS_MAC) // iOS
-# include <OpenGLES/ES2/gl.h>
-# include <OpenGLES/ES2/glext.h>
+# if defined(QT_OPENGL_ES_3)
+# include <OpenGLES/ES3/gl.h>
+# include <OpenGLES/ES3/glext.h>
+# else
+# include <OpenGLES/ES2/gl.h>
+# include <OpenGLES/ES2/glext.h>
+# endif
/*
OES_EGL_image_external is not included in the Apple provided
@@ -79,7 +84,28 @@
typedef void* GLeglImageOES;
# else // "uncontrolled" ES2 platforms
-# include <GLES2/gl2.h>
+
+// In "es2" builds (QT_OPENGL_ES_2) additional defines indicate if ES
+// 3.0 or higher is available. In this case include the corresponding
+// header. These are backwards compatible and it should be safe to
+// include headers on top of each other, meaning that applications can
+// include gl2.h even if gl31.h gets included here.
+
+// This compile time differentation is important inside Qt because,
+// unlike desktop GL, GLES is different when it comes to versioning
+// and extensions: Standard functions that are new in a given version
+// are always available in a version-specific header and are not
+// guaranteed to be dynamically resolvable via eglGetProcAddress (and
+// are typically not available as extensions even if they were part of
+// an extension for a previous version).
+
+# if defined(QT_OPENGL_ES_3_1)
+# include <GLES3/gl31.h>
+# elif defined(QT_OPENGL_ES_3)
+# include <GLES3/gl3.h>
+# else
+# include <GLES2/gl2.h>
+#endif
/*
Some GLES2 implementations (like the one on Harmattan) are missing the
diff --git a/src/gui/opengl/qopenglextensions_p.h b/src/gui/opengl/qopenglextensions_p.h
index 265771ce1b..065cbb0e57 100644
--- a/src/gui/opengl/qopenglextensions_p.h
+++ b/src/gui/opengl/qopenglextensions_p.h
@@ -106,8 +106,6 @@ public:
OpenGLExtensions openGLExtensions();
bool hasOpenGLExtension(QOpenGLExtensions::OpenGLExtension extension) const;
- void initializeGLExtensions();
-
GLvoid *glMapBuffer(GLenum target, GLenum access);
GLboolean glUnmapBuffer(GLenum target);
diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp
index 3102e1ecd2..0c05b61e76 100644
--- a/src/gui/opengl/qopenglframebufferobject.cpp
+++ b/src/gui/opengl/qopenglframebufferobject.cpp
@@ -88,6 +88,10 @@ QT_BEGIN_NAMESPACE
#define GL_DEPTH_COMPONENT24 0x81A6
#endif
+#ifndef GL_DEPTH_COMPONENT24_OES
+#define GL_DEPTH_COMPONENT24_OES 0x81A6
+#endif
+
#ifndef GL_READ_FRAMEBUFFER
#define GL_READ_FRAMEBUFFER 0x8CA8
#endif
@@ -96,6 +100,23 @@ QT_BEGIN_NAMESPACE
#define GL_DRAW_FRAMEBUFFER 0x8CA9
#endif
+#ifndef GL_RGB8
+#define GL_RGB8 0x8051
+#endif
+
+#ifndef GL_RGBA8
+#define GL_RGBA8 0x8058
+#endif
+
+#ifndef GL_BGRA
+#define GL_BGRA 0x80E1
+#endif
+
+#ifndef GL_UNSIGNED_INT_8_8_8_8_REV
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#endif
+
+
/*!
\class QOpenGLFramebufferObjectFormat
\brief The QOpenGLFramebufferObjectFormat class specifies the format of an OpenGL
@@ -423,18 +444,21 @@ void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSi
if (!funcs.hasOpenGLFeature(QOpenGLFunctions::Framebuffers))
return;
-
// Fall back to using a normal non-msaa FBO if we don't have support for MSAA
if (!funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)
|| !funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit)) {
samples = 0;
}
-#ifndef QT_OPENGL_ES_2
- GLint maxSamples;
- funcs.glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
- samples = qBound(0, int(samples), int(maxSamples));
-#endif
+ // On GLES 2.0 multisampled framebuffers are available through vendor-specific extensions
+ const bool msaaES2 = ctx->isOpenGLES() && (ctx->hasExtension("GL_ANGLE_framebuffer_multisample")
+ || ctx->hasExtension("GL_NV_framebuffer_multisample"));
+
+ if (!ctx->isOpenGLES() || msaaES2) {
+ GLint maxSamples;
+ funcs.glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
+ samples = qBound(0, int(samples), int(maxSamples));
+ }
samples = qMax(0, samples);
requestedSamples = samples;
@@ -456,11 +480,9 @@ void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSi
} else {
GLenum storageFormat = internal_format;
#ifdef GL_RGBA8_OES
- // Correct the internal format used by the render buffer when using ANGLE
- if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES && internal_format == GL_RGBA
- && strstr((const char *)funcs.glGetString(GL_RENDERER), "ANGLE") != 0) {
+ // Correct the internal format used by the render buffer when using ES with extensions
+ if (msaaES2 && internal_format == GL_RGBA)
storageFormat = GL_RGBA8_OES;
- }
#endif
mipmap = false;
@@ -488,7 +510,6 @@ void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSi
initAttachments(ctx, attachment);
- funcs.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_func()->current_fbo);
if (valid) {
fbo_guard = new QOpenGLSharedResourceGuard(ctx, fbo, freeFramebufferFunc);
} else {
@@ -975,8 +996,6 @@ bool QOpenGLFramebufferObject::bind()
d->valid = d->checkFramebufferStatus(current);
else
d->initTexture(d->format.textureTarget(), d->format.internalTextureFormat(), d->size, d->format.mipmap());
- if (d->valid && current)
- current->d_func()->current_fbo = d->fbo();
return d->valid;
}
@@ -1004,10 +1023,8 @@ bool QOpenGLFramebufferObject::release()
qWarning("QOpenGLFramebufferObject::release() called from incompatible context");
#endif
- if (current) {
- current->d_func()->current_fbo = current->defaultFramebufferObject();
- d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->d_func()->current_fbo);
- }
+ if (current)
+ d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->defaultFramebufferObject());
return true;
}
@@ -1054,7 +1071,7 @@ GLuint QOpenGLFramebufferObject::takeTexture()
GLuint id = 0;
if (isValid() && d->texture_guard) {
QOpenGLContext *current = QOpenGLContext::currentContext();
- if (current && current->shareGroup() == d->fbo_guard->group() && current->d_func()->current_fbo == d->fbo())
+ if (current && current->shareGroup() == d->fbo_guard->group() && isBound())
release();
id = d->texture_guard->id();
// Do not call free() on texture_guard, just null it out.
@@ -1097,47 +1114,101 @@ QOpenGLFramebufferObjectFormat QOpenGLFramebufferObject::format() const
return d->format;
}
-Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha)
+static inline QImage qt_gl_read_framebuffer_rgba8(const QSize &size, bool include_alpha, QOpenGLContext *context)
{
- int w = size.width();
- int h = size.height();
-
- QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
- while (funcs->glGetError());
+ QOpenGLFunctions *funcs = context->functions();
+ const int w = size.width();
+ const int h = size.height();
+ bool isOpenGL12orBetter = !context->isOpenGLES() && (context->format().majorVersion() >= 2 || context->format().minorVersion() >= 2);
+ if (isOpenGL12orBetter) {
+ QImage img(size, include_alpha ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32);
+ funcs->glReadPixels(0, 0, w, h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, img.bits());
+ return img;
+ }
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- QImage img(size, (alpha_format && include_alpha) ? QImage::Format_ARGB32_Premultiplied
- : QImage::Format_RGB32);
-#ifdef QT_OPENGL_ES
- GLint fmt = GL_BGRA_EXT;
-#else
- GLint fmt = GL_BGRA;
-#endif
- funcs->glReadPixels(0, 0, w, h, fmt, GL_UNSIGNED_BYTE, img.bits());
- if (!funcs->glGetError())
- return img.mirrored();
+ // Without GL_UNSIGNED_INT_8_8_8_8_REV, GL_BGRA only makes sense on little endian.
+ const bool supports_bgra = context->isOpenGLES()
+ ? context->hasExtension(QByteArrayLiteral("GL_EXT_read_format_bgra"))
+ : context->hasExtension(QByteArrayLiteral("GL_EXT_bgra"));
+ if (supports_bgra) {
+ QImage img(size, include_alpha ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32);
+ funcs->glReadPixels(0, 0, w, h, GL_BGRA, GL_UNSIGNED_BYTE, img.bits());
+ return img;
+ }
#endif
-
- QImage rgbaImage(size, (alpha_format && include_alpha) ? QImage::Format_RGBA8888_Premultiplied
- : QImage::Format_RGBX8888);
+ QImage rgbaImage(size, include_alpha ? QImage::Format_RGBA8888_Premultiplied : QImage::Format_RGBX8888);
funcs->glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rgbaImage.bits());
- return rgbaImage.mirrored();
+ return rgbaImage;
+}
+
+static QImage qt_gl_read_framebuffer(const QSize &size, GLenum internal_format, bool include_alpha, bool flip)
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ QOpenGLFunctions *funcs = ctx->functions();
+ while (funcs->glGetError());
+
+ switch (internal_format) {
+ case GL_RGB:
+ case GL_RGB8:
+ return qt_gl_read_framebuffer_rgba8(size, false, ctx).mirrored(false, flip);
+ case GL_RGBA:
+ case GL_RGBA8:
+ default:
+ return qt_gl_read_framebuffer_rgba8(size, include_alpha, ctx).mirrored(false, flip);
+ }
+
+ Q_UNREACHABLE();
+ return QImage();
+}
+
+Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha)
+{
+ return qt_gl_read_framebuffer(size, alpha_format ? GL_RGBA : GL_RGB, include_alpha, true);
}
/*!
- \fn QImage QOpenGLFramebufferObject::toImage() const
+ \fn QImage QOpenGLFramebufferObject::toImage(bool flipped) const
Returns the contents of this framebuffer object as a QImage.
+ If \a flipped is true the image is flipped from OpenGL coordinates to raster coordinates.
+ If used together with QOpenGLPaintDevice, \a flipped should be the opposite of the value
+ of QOpenGLPaintDevice::paintFlipped().
+
Will try to return a premultiplied ARBG32 or RGB32 image. Since 5.2 it will fall back to
a premultiplied RGBA8888 or RGBx8888 image when reading to ARGB32 is not supported.
+
+ For multisampled framebuffer objects the samples are resolved using the
+ \c{GL_EXT_framebuffer_blit} extension. If the extension is not available, the contents
+ of the returned image is undefined.
+
+ For singlesampled framebuffers the contents is retrieved via \c glReadPixels. This is
+ a potentially expensive and inefficient operation. Therefore it is recommended that
+ this function is used as seldom as possible.
+
+ \sa QOpenGLPaintDevice::paintFlipped()
*/
-QImage QOpenGLFramebufferObject::toImage() const
+
+QImage QOpenGLFramebufferObject::toImage(bool flipped) const
{
Q_D(const QOpenGLFramebufferObject);
if (!d->valid)
return QImage();
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (!ctx) {
+ qWarning("QOpenGLFramebufferObject::toImage() called without a current context");
+ return QImage();
+ }
+
+ GLuint prevFbo = 0;
+ ctx->functions()->glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *) &prevFbo);
+
+ if (prevFbo != d->fbo())
+ const_cast<QOpenGLFramebufferObject *>(this)->bind();
+
+ QImage image;
// qt_gl_read_framebuffer doesn't work on a multisample FBO
if (format().samples() != 0) {
QOpenGLFramebufferObject temp(size(), QOpenGLFramebufferObjectFormat());
@@ -1145,20 +1216,31 @@ QImage QOpenGLFramebufferObject::toImage() const
QRect rect(QPoint(0, 0), size());
blitFramebuffer(&temp, rect, const_cast<QOpenGLFramebufferObject *>(this), rect);
- return temp.toImage();
+ image = temp.toImage(flipped);
+ } else {
+ image = qt_gl_read_framebuffer(d->size, format().internalTextureFormat(), true, flipped);
}
- bool wasBound = isBound();
- if (!wasBound)
- const_cast<QOpenGLFramebufferObject *>(this)->bind();
- QImage image = qt_gl_read_framebuffer(d->size, format().internalTextureFormat() != GL_RGB, true);
- if (!wasBound)
- const_cast<QOpenGLFramebufferObject *>(this)->release();
+ if (prevFbo != d->fbo())
+ ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, prevFbo);
return image;
}
/*!
+ \fn QImage QOpenGLFramebufferObject::toImage() const
+ \overload
+
+ Returns the contents of this framebuffer object as a QImage. This method flips
+ the image from OpenGL coordinates to raster coordinates.
+*/
+// ### Qt 6: Remove this method and make it a default argument instead.
+QImage QOpenGLFramebufferObject::toImage() const
+{
+ return toImage(true);
+}
+
+/*!
\fn bool QOpenGLFramebufferObject::bindDefault()
Switches rendering back to the default, windowing system provided
@@ -1170,16 +1252,13 @@ QImage QOpenGLFramebufferObject::toImage() const
bool QOpenGLFramebufferObject::bindDefault()
{
QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
- QOpenGLFunctions functions(ctx);
- if (ctx) {
- ctx->d_func()->current_fbo = ctx->defaultFramebufferObject();
- functions.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_func()->current_fbo);
+ if (ctx)
+ ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
#ifdef QT_DEBUG
- } else {
+ else
qWarning("QOpenGLFramebufferObject::bindDefault() called without current context.");
#endif
- }
return ctx != 0;
}
@@ -1192,7 +1271,7 @@ bool QOpenGLFramebufferObject::bindDefault()
*/
bool QOpenGLFramebufferObject::hasOpenGLFramebufferObjects()
{
- return QOpenGLFunctions(QOpenGLContext::currentContext()).hasOpenGLFeature(QOpenGLFunctions::Framebuffers);
+ return QOpenGLContext::currentContext()->functions()->hasOpenGLFeature(QOpenGLFunctions::Framebuffers);
}
/*!
@@ -1228,6 +1307,8 @@ QOpenGLFramebufferObject::Attachment QOpenGLFramebufferObject::attachment() cons
This can be used to free or reattach the depth and stencil buffer
attachments as needed.
+
+ \note This function alters the current framebuffer binding.
*/
void QOpenGLFramebufferObject::setAttachment(QOpenGLFramebufferObject::Attachment attachment)
{
@@ -1243,20 +1324,21 @@ void QOpenGLFramebufferObject::setAttachment(QOpenGLFramebufferObject::Attachmen
#endif
d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo());
d->initAttachments(current, attachment);
- if (current->d_func()->current_fbo != d->fbo())
- d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->d_func()->current_fbo);
}
/*!
- Returns \c true if the framebuffer object is currently bound to a context,
+ Returns \c true if the framebuffer object is currently bound to the current context,
otherwise false is returned.
*/
-
bool QOpenGLFramebufferObject::isBound() const
{
Q_D(const QOpenGLFramebufferObject);
- QOpenGLContext *current = QOpenGLContext::currentContext();
- return current ? current->d_func()->current_fbo == d->fbo() : false;
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (!ctx)
+ return false;
+ GLint fbo = 0;
+ ctx->functions()->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo);
+ return GLuint(fbo) == d->fbo();
}
/*!
@@ -1310,6 +1392,9 @@ void QOpenGLFramebufferObject::blitFramebuffer(QOpenGLFramebufferObject *target,
If \a source or \a target is 0, the default framebuffer will be used
instead of a framebuffer object as source or target respectively.
+ This function will have no effect unless hasOpenGLFramebufferBlit() returns
+ true.
+
The \a buffers parameter should be a mask consisting of any combination of
\c GL_COLOR_BUFFER_BIT, \c GL_DEPTH_BUFFER_BIT, and
\c GL_STENCIL_BUFFER_BIT. Any buffer type that is not present both
@@ -1326,10 +1411,7 @@ void QOpenGLFramebufferObject::blitFramebuffer(QOpenGLFramebufferObject *target,
have different sizes. The sizes must also be the same if any of the
framebuffer objects are multisample framebuffers.
- Note that the scissor test will restrict the blit area if enabled.
-
- This function will have no effect unless hasOpenGLFramebufferBlit() returns
- true.
+ \note The scissor test will restrict the blit area if enabled.
\sa hasOpenGLFramebufferBlit()
*/
@@ -1346,6 +1428,9 @@ void QOpenGLFramebufferObject::blitFramebuffer(QOpenGLFramebufferObject *target,
if (!extensions.hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit))
return;
+ GLuint prevFbo = 0;
+ ctx->functions()->glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *) &prevFbo);
+
const int sx0 = sourceRect.left();
const int sx1 = sourceRect.left() + sourceRect.width();
const int sy0 = sourceRect.top();
@@ -1363,7 +1448,7 @@ void QOpenGLFramebufferObject::blitFramebuffer(QOpenGLFramebufferObject *target,
tx0, ty0, tx1, ty1,
buffers, filter);
- extensions.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_func()->current_fbo);
+ ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, prevFbo); // sets both READ and DRAW
}
QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopenglframebufferobject.h b/src/gui/opengl/qopenglframebufferobject.h
index 3df929c210..0b1aaae36d 100644
--- a/src/gui/opengl/qopenglframebufferobject.h
+++ b/src/gui/opengl/qopenglframebufferobject.h
@@ -94,6 +94,7 @@ public:
GLuint takeTexture();
QSize size() const;
QImage toImage() const;
+ QImage toImage(bool flipped) const;
Attachment attachment() const;
void setAttachment(Attachment attachment);
diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp
index bc4a714c6c..db88fbb68c 100644
--- a/src/gui/opengl/qopenglfunctions.cpp
+++ b/src/gui/opengl/qopenglfunctions.cpp
@@ -372,6 +372,12 @@ static int qt_gl_resolve_extensions()
if (ctx->isOpenGLES()) {
if (format.majorVersion() >= 2)
extensions |= QOpenGLExtensions::GenerateMipmap;
+
+ if (format.majorVersion() >= 3)
+ extensions |= QOpenGLExtensions::PackedDepthStencil
+ | QOpenGLExtensions::Depth24
+ | QOpenGLExtensions::ElementIndexUint;
+
if (extensionMatcher.match("GL_OES_mapbuffer"))
extensions |= QOpenGLExtensions::MapBuffer;
if (extensionMatcher.match("GL_OES_packed_depth_stencil"))
@@ -387,6 +393,12 @@ static int qt_gl_resolve_extensions()
extensions |= QOpenGLExtensions::FramebufferBlit;
if (extensionMatcher.match("GL_ANGLE_framebuffer_multisample"))
extensions |= QOpenGLExtensions::FramebufferMultisample;
+ if (extensionMatcher.match("GL_NV_framebuffer_blit"))
+ extensions |= QOpenGLExtensions::FramebufferBlit;
+ if (extensionMatcher.match("GL_NV_framebuffer_multisample"))
+ extensions |= QOpenGLExtensions::FramebufferMultisample;
+ if (format.majorVersion() >= 3)
+ extensions |= QOpenGLExtensions::FramebufferBlit | QOpenGLExtensions::FramebufferMultisample;
} else {
extensions |= QOpenGLExtensions::ElementIndexUint | QOpenGLExtensions::MapBuffer;
@@ -2027,7 +2039,9 @@ namespace {
enum ResolvePolicy
{
ResolveOES = 0x1,
- ResolveEXT = 0x2
+ ResolveEXT = 0x2,
+ ResolveANGLE = 0x4,
+ ResolveNV = 0x8
};
template <typename Base, typename FuncType, int Policy, typename ReturnType>
@@ -2149,6 +2163,12 @@ private:
if ((Policy & ResolveEXT) && !(funcs->*funcPointerName)) \
funcs->*funcPointerName = (FuncType)context->getProcAddress(funcName + "EXT"); \
\
+ if ((Policy & ResolveANGLE) && !(funcs->*funcPointerName)) \
+ funcs->*funcPointerName = (FuncType)context->getProcAddress(funcName + "ANGLE"); \
+ \
+ if ((Policy & ResolveNV) && !(funcs->*funcPointerName)) \
+ funcs->*funcPointerName = (FuncType)context->getProcAddress(funcName + "NV"); \
+ \
if (!alternateFuncName.isEmpty() && !(funcs->*funcPointerName)) { \
funcs->*funcPointerName = (FuncType)context->getProcAddress(alternateFuncName); \
\
@@ -2160,6 +2180,12 @@ private:
\
if ((Policy & ResolveEXT) && !(funcs->*funcPointerName)) \
funcs->*funcPointerName = (FuncType)context->getProcAddress(alternateFuncName + "EXT"); \
+ \
+ if ((Policy & ResolveANGLE) && !(funcs->*funcPointerName)) \
+ funcs->*funcPointerName = (FuncType)context->getProcAddress(funcName + "ANGLE"); \
+ \
+ if ((Policy & ResolveNV) && !(funcs->*funcPointerName)) \
+ funcs->*funcPointerName = (FuncType)context->getProcAddress(funcName + "NV"); \
}
#define RESOLVER_COMMON_NON_VOID \
@@ -3156,16 +3182,24 @@ static void QOPENGLF_APIENTRY qopenglfResolveBlitFramebuffer(GLint srcX0, GLint
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter)
{
- RESOLVE_FUNC_VOID_WITH_ALTERNATE(ResolveEXT, BlitFramebuffer, BlitFramebufferANGLE)
+#ifdef QT_OPENGL_ES_3
+ ::glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+#else
+ RESOLVE_FUNC_VOID(ResolveEXT | ResolveANGLE | ResolveNV, BlitFramebuffer)
(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+#endif
}
static void QOPENGLF_APIENTRY qopenglfResolveRenderbufferStorageMultisample(GLenum target, GLsizei samples,
GLenum internalFormat,
GLsizei width, GLsizei height)
{
- RESOLVE_FUNC_VOID_WITH_ALTERNATE(ResolveEXT, RenderbufferStorageMultisample, RenderbufferStorageMultisampleANGLE)
+#ifdef QT_OPENGL_ES_3
+ ::glRenderbufferStorageMultisample(target, samples, internalFormat, width, height);
+#else
+ RESOLVE_FUNC_VOID(ResolveEXT | ResolveANGLE | ResolveNV, RenderbufferStorageMultisample)
(target, samples, internalFormat, width, height);
+#endif
}
static void QOPENGLF_APIENTRY qopenglfResolveGetBufferSubData(GLenum target, qopengl_GLintptr offset, qopengl_GLsizeiptr size, GLvoid *data)
diff --git a/src/gui/opengl/qopenglpaintengine.cpp b/src/gui/opengl/qopenglpaintengine.cpp
index 81a0d82c99..de5b6be492 100644
--- a/src/gui/opengl/qopenglpaintengine.cpp
+++ b/src/gui/opengl/qopenglpaintengine.cpp
@@ -154,8 +154,8 @@ void QOpenGL2PaintEngineExPrivate::setBrush(const QBrush& brush)
Q_ASSERT(newStyle != Qt::NoBrush);
currentBrush = brush;
- if (!currentBrushPixmap.isNull())
- currentBrushPixmap = QPixmap();
+ if (!currentBrushImage.isNull())
+ currentBrushImage = QImage();
brushUniformsDirty = true; // All brushes have at least one uniform
if (newStyle > Qt::SolidPattern)
@@ -214,11 +214,11 @@ void QOpenGL2PaintEngineExPrivate::updateBrushTexture()
updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, q->state()->renderHints & QPainter::SmoothPixmapTransform);
}
else if (style == Qt::TexturePattern) {
- currentBrushPixmap = currentBrush.texture();
+ currentBrushImage = currentBrush.textureImage();
int max_texture_size = ctx->d_func()->maxTextureSize();
- if (currentBrushPixmap.width() > max_texture_size || currentBrushPixmap.height() > max_texture_size)
- currentBrushPixmap = currentBrushPixmap.scaled(max_texture_size, max_texture_size, Qt::KeepAspectRatio);
+ if (currentBrushImage.width() > max_texture_size || currentBrushImage.height() > max_texture_size)
+ currentBrushImage = currentBrushImage.scaled(max_texture_size, max_texture_size, Qt::KeepAspectRatio);
GLuint wrapMode = GL_REPEAT;
if (QOpenGLContext::currentContext()->isOpenGLES()) {
@@ -229,7 +229,7 @@ void QOpenGL2PaintEngineExPrivate::updateBrushTexture()
}
funcs.glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
- QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, currentBrushPixmap);
+ QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, currentBrushImage);
updateTextureFilter(GL_TEXTURE_2D, wrapMode, q->state()->renderHints & QPainter::SmoothPixmapTransform);
textureInvertedY = false;
}
diff --git a/src/gui/opengl/qopenglpaintengine_p.h b/src/gui/opengl/qopenglpaintengine_p.h
index 4f0e2e52a4..89eb7e87b2 100644
--- a/src/gui/opengl/qopenglpaintengine_p.h
+++ b/src/gui/opengl/qopenglpaintengine_p.h
@@ -288,7 +288,7 @@ public:
QBrush currentBrush; // May not be the state's brush!
const QBrush noBrush;
- QPixmap currentBrushPixmap;
+ QImage currentBrushImage;
QOpenGL2PEXVertexArray vertexCoordinateArray;
QOpenGL2PEXVertexArray textureCoordinateArray;
diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp
index e0e1c72a6c..811505cecb 100644
--- a/src/gui/opengl/qopengltexture.cpp
+++ b/src/gui/opengl/qopengltexture.cpp
@@ -67,7 +67,7 @@ QOpenGLTexturePrivate::QOpenGLTexturePrivate(QOpenGLTexture::Target textureTarge
mipLevels(-1),
layers(1),
faces(1),
- samples(1),
+ samples(0),
fixedSamplePositions(true),
baseLevel(0),
maxLevel(1000),
@@ -200,7 +200,7 @@ void QOpenGLTexturePrivate::destroy()
mipLevels = -1;
layers = 1;
faces = 1;
- samples = 1;
+ samples = 0;
fixedSamplePositions = true,
baseLevel = 0;
maxLevel = 1000;
@@ -314,8 +314,239 @@ void QOpenGLTexturePrivate::allocateStorage()
allocateMutableStorage();
}
+static QOpenGLTexture::PixelFormat pixelFormatCompatibleWithInternalFormat(QOpenGLTexture::TextureFormat internalFormat)
+{
+ switch (internalFormat) {
+ case QOpenGLTexture::NoFormat:
+ return QOpenGLTexture::NoSourceFormat;
+
+ case QOpenGLTexture::R8_UNorm:
+ case QOpenGLTexture::RG8_UNorm:
+ case QOpenGLTexture::RGB8_UNorm:
+ case QOpenGLTexture::RGBA8_UNorm:
+ case QOpenGLTexture::R16_UNorm:
+ case QOpenGLTexture::RG16_UNorm:
+ case QOpenGLTexture::RGB16_UNorm:
+ case QOpenGLTexture::RGBA16_UNorm:
+ case QOpenGLTexture::R8_SNorm:
+ case QOpenGLTexture::RG8_SNorm:
+ case QOpenGLTexture::RGB8_SNorm:
+ case QOpenGLTexture::RGBA8_SNorm:
+ case QOpenGLTexture::R16_SNorm:
+ case QOpenGLTexture::RG16_SNorm:
+ case QOpenGLTexture::RGB16_SNorm:
+ case QOpenGLTexture::RGBA16_SNorm:
+ case QOpenGLTexture::R8U:
+ case QOpenGLTexture::RG8U:
+ case QOpenGLTexture::RGB8U:
+ case QOpenGLTexture::RGBA8U:
+ case QOpenGLTexture::R16U:
+ case QOpenGLTexture::RG16U:
+ case QOpenGLTexture::RGB16U:
+ case QOpenGLTexture::RGBA16U:
+ case QOpenGLTexture::R32U:
+ case QOpenGLTexture::RG32U:
+ case QOpenGLTexture::RGB32U:
+ case QOpenGLTexture::RGBA32U:
+ case QOpenGLTexture::R8I:
+ case QOpenGLTexture::RG8I:
+ case QOpenGLTexture::RGB8I:
+ case QOpenGLTexture::RGBA8I:
+ case QOpenGLTexture::R16I:
+ case QOpenGLTexture::RG16I:
+ case QOpenGLTexture::RGB16I:
+ case QOpenGLTexture::RGBA16I:
+ case QOpenGLTexture::R32I:
+ case QOpenGLTexture::RG32I:
+ case QOpenGLTexture::RGB32I:
+ case QOpenGLTexture::RGBA32I:
+ case QOpenGLTexture::R16F:
+ case QOpenGLTexture::RG16F:
+ case QOpenGLTexture::RGB16F:
+ case QOpenGLTexture::RGBA16F:
+ case QOpenGLTexture::R32F:
+ case QOpenGLTexture::RG32F:
+ case QOpenGLTexture::RGB32F:
+ case QOpenGLTexture::RGBA32F:
+ case QOpenGLTexture::RGB9E5:
+ case QOpenGLTexture::RG11B10F:
+ case QOpenGLTexture::RG3B2:
+ case QOpenGLTexture::R5G6B5:
+ case QOpenGLTexture::RGB5A1:
+ case QOpenGLTexture::RGBA4:
+ case QOpenGLTexture::RGB10A2:
+ return QOpenGLTexture::RGBA;
+
+ case QOpenGLTexture::D16:
+ case QOpenGLTexture::D24:
+ case QOpenGLTexture::D32:
+ case QOpenGLTexture::D32F:
+ return QOpenGLTexture::Depth;
+
+ case QOpenGLTexture::D24S8:
+ case QOpenGLTexture::D32FS8X24:
+ return QOpenGLTexture::DepthStencil;
+
+ case QOpenGLTexture::S8:
+ return QOpenGLTexture::Stencil;
+
+ case QOpenGLTexture::RGB_DXT1:
+ case QOpenGLTexture::RGBA_DXT1:
+ case QOpenGLTexture::RGBA_DXT3:
+ case QOpenGLTexture::RGBA_DXT5:
+ case QOpenGLTexture::R_ATI1N_UNorm:
+ case QOpenGLTexture::R_ATI1N_SNorm:
+ case QOpenGLTexture::RG_ATI2N_UNorm:
+ case QOpenGLTexture::RG_ATI2N_SNorm:
+ case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT:
+ case QOpenGLTexture::RGB_BP_SIGNED_FLOAT:
+ case QOpenGLTexture::RGB_BP_UNorm:
+ case QOpenGLTexture::SRGB8:
+ case QOpenGLTexture::SRGB8_Alpha8:
+ case QOpenGLTexture::SRGB_DXT1:
+ case QOpenGLTexture::SRGB_Alpha_DXT1:
+ case QOpenGLTexture::SRGB_Alpha_DXT3:
+ case QOpenGLTexture::SRGB_Alpha_DXT5:
+ case QOpenGLTexture::SRGB_BP_UNorm:
+ return QOpenGLTexture::RGBA;
+
+ case QOpenGLTexture::DepthFormat:
+ return QOpenGLTexture::Depth;
+
+ case QOpenGLTexture::AlphaFormat:
+ return QOpenGLTexture::Alpha;
+
+ case QOpenGLTexture::RGBFormat:
+ case QOpenGLTexture::RGBAFormat:
+ return QOpenGLTexture::RGBA;
+
+ case QOpenGLTexture::LuminanceFormat:
+ return QOpenGLTexture::Luminance;
+
+ case QOpenGLTexture::LuminanceAlphaFormat:
+ return QOpenGLTexture::LuminanceAlpha;
+ }
+
+ Q_UNREACHABLE();
+ return QOpenGLTexture::NoSourceFormat;
+}
+
+static QOpenGLTexture::PixelType pixelTypeCompatibleWithInternalFormat(QOpenGLTexture::TextureFormat internalFormat)
+{
+ switch (internalFormat) {
+ case QOpenGLTexture::NoFormat:
+ return QOpenGLTexture::NoPixelType;
+
+ case QOpenGLTexture::R8_UNorm:
+ case QOpenGLTexture::RG8_UNorm:
+ case QOpenGLTexture::RGB8_UNorm:
+ case QOpenGLTexture::RGBA8_UNorm:
+ case QOpenGLTexture::R16_UNorm:
+ case QOpenGLTexture::RG16_UNorm:
+ case QOpenGLTexture::RGB16_UNorm:
+ case QOpenGLTexture::RGBA16_UNorm:
+ case QOpenGLTexture::R8_SNorm:
+ case QOpenGLTexture::RG8_SNorm:
+ case QOpenGLTexture::RGB8_SNorm:
+ case QOpenGLTexture::RGBA8_SNorm:
+ case QOpenGLTexture::R16_SNorm:
+ case QOpenGLTexture::RG16_SNorm:
+ case QOpenGLTexture::RGB16_SNorm:
+ case QOpenGLTexture::RGBA16_SNorm:
+ case QOpenGLTexture::R8U:
+ case QOpenGLTexture::RG8U:
+ case QOpenGLTexture::RGB8U:
+ case QOpenGLTexture::RGBA8U:
+ case QOpenGLTexture::R16U:
+ case QOpenGLTexture::RG16U:
+ case QOpenGLTexture::RGB16U:
+ case QOpenGLTexture::RGBA16U:
+ case QOpenGLTexture::R32U:
+ case QOpenGLTexture::RG32U:
+ case QOpenGLTexture::RGB32U:
+ case QOpenGLTexture::RGBA32U:
+ case QOpenGLTexture::R8I:
+ case QOpenGLTexture::RG8I:
+ case QOpenGLTexture::RGB8I:
+ case QOpenGLTexture::RGBA8I:
+ case QOpenGLTexture::R16I:
+ case QOpenGLTexture::RG16I:
+ case QOpenGLTexture::RGB16I:
+ case QOpenGLTexture::RGBA16I:
+ case QOpenGLTexture::R32I:
+ case QOpenGLTexture::RG32I:
+ case QOpenGLTexture::RGB32I:
+ case QOpenGLTexture::RGBA32I:
+ case QOpenGLTexture::R16F:
+ case QOpenGLTexture::RG16F:
+ case QOpenGLTexture::RGB16F:
+ case QOpenGLTexture::RGBA16F:
+ case QOpenGLTexture::R32F:
+ case QOpenGLTexture::RG32F:
+ case QOpenGLTexture::RGB32F:
+ case QOpenGLTexture::RGBA32F:
+ case QOpenGLTexture::RGB9E5:
+ case QOpenGLTexture::RG11B10F:
+ case QOpenGLTexture::RG3B2:
+ case QOpenGLTexture::R5G6B5:
+ case QOpenGLTexture::RGB5A1:
+ case QOpenGLTexture::RGBA4:
+ case QOpenGLTexture::RGB10A2:
+ return QOpenGLTexture::UInt8;
+
+ case QOpenGLTexture::D16:
+ case QOpenGLTexture::D24:
+ case QOpenGLTexture::D32:
+ case QOpenGLTexture::D32F:
+ return QOpenGLTexture::UInt8;
+
+ case QOpenGLTexture::D24S8:
+ return QOpenGLTexture::UInt32_D24S8;
+
+ case QOpenGLTexture::D32FS8X24:
+ return QOpenGLTexture::Float32_D32_UInt32_S8_X24;
+
+ case QOpenGLTexture::S8:
+ return QOpenGLTexture::UInt8;
+
+ case QOpenGLTexture::RGB_DXT1:
+ case QOpenGLTexture::RGBA_DXT1:
+ case QOpenGLTexture::RGBA_DXT3:
+ case QOpenGLTexture::RGBA_DXT5:
+ case QOpenGLTexture::R_ATI1N_UNorm:
+ case QOpenGLTexture::R_ATI1N_SNorm:
+ case QOpenGLTexture::RG_ATI2N_UNorm:
+ case QOpenGLTexture::RG_ATI2N_SNorm:
+ case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT:
+ case QOpenGLTexture::RGB_BP_SIGNED_FLOAT:
+ case QOpenGLTexture::RGB_BP_UNorm:
+ case QOpenGLTexture::SRGB8:
+ case QOpenGLTexture::SRGB8_Alpha8:
+ case QOpenGLTexture::SRGB_DXT1:
+ case QOpenGLTexture::SRGB_Alpha_DXT1:
+ case QOpenGLTexture::SRGB_Alpha_DXT3:
+ case QOpenGLTexture::SRGB_Alpha_DXT5:
+ case QOpenGLTexture::SRGB_BP_UNorm:
+ return QOpenGLTexture::UInt8;
+
+ case QOpenGLTexture::DepthFormat:
+ case QOpenGLTexture::AlphaFormat:
+ case QOpenGLTexture::RGBFormat:
+ case QOpenGLTexture::RGBAFormat:
+ case QOpenGLTexture::LuminanceFormat:
+ case QOpenGLTexture::LuminanceAlphaFormat:
+ return QOpenGLTexture::UInt8;
+ }
+
+ Q_UNREACHABLE();
+ return QOpenGLTexture::NoPixelType;
+}
+
void QOpenGLTexturePrivate::allocateMutableStorage()
{
+ const QOpenGLTexture::PixelFormat pixelFormat = pixelFormatCompatibleWithInternalFormat(format);
+ const QOpenGLTexture::PixelType pixelType = pixelTypeCompatibleWithInternalFormat(format);
+
switch (target) {
case QOpenGLTexture::TargetBuffer:
// Buffer textures get their storage from an external OpenGL buffer
@@ -328,7 +559,7 @@ void QOpenGLTexturePrivate::allocateMutableStorage()
texFuncs->glTextureImage1D(textureId, target, bindingTarget, level, format,
mipLevelSize(level, dimensions[0]),
0,
- QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, 0);
+ pixelFormat, pixelType, 0);
} else {
qWarning("1D textures are not supported");
return;
@@ -343,7 +574,7 @@ void QOpenGLTexturePrivate::allocateMutableStorage()
mipLevelSize(level, dimensions[0]),
layers,
0,
- QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, 0);
+ pixelFormat, pixelType, 0);
} else {
qWarning("1D array textures are not supported");
return;
@@ -357,7 +588,7 @@ void QOpenGLTexturePrivate::allocateMutableStorage()
mipLevelSize(level, dimensions[0]),
mipLevelSize(level, dimensions[1]),
0,
- QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, 0);
+ pixelFormat, pixelType, 0);
break;
case QOpenGLTexture::TargetCubeMap: {
@@ -377,7 +608,7 @@ void QOpenGLTexturePrivate::allocateMutableStorage()
mipLevelSize(level, dimensions[0]),
mipLevelSize(level, dimensions[1]),
0,
- QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, 0);
+ pixelFormat, pixelType, 0);
}
}
break;
@@ -391,7 +622,7 @@ void QOpenGLTexturePrivate::allocateMutableStorage()
mipLevelSize(level, dimensions[1]),
layers,
0,
- QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, 0);
+ pixelFormat, pixelType, 0);
} else {
qWarning("Array textures are not supported");
return;
@@ -407,7 +638,7 @@ void QOpenGLTexturePrivate::allocateMutableStorage()
mipLevelSize(level, dimensions[1]),
6 * layers,
0,
- QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, 0);
+ pixelFormat, pixelType, 0);
} else {
qWarning("Cubemap Array textures are not supported");
return;
@@ -422,7 +653,7 @@ void QOpenGLTexturePrivate::allocateMutableStorage()
mipLevelSize(level, dimensions[1]),
mipLevelSize(level, dimensions[2]),
0,
- QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, 0);
+ pixelFormat, pixelType, 0);
} else {
qWarning("3D textures are not supported");
return;
@@ -1289,6 +1520,7 @@ QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target
\value D32 Equivalent to GL_DEPTH_COMPONENT32
\value D32F Equivalent to GL_DEPTH_COMPONENT32F
\value D32FS8X24 Equivalent to GL_DEPTH32F_STENCIL8
+ \value S8 Equivalent to GL_STENCIL_INDEX8. Introduced in Qt 5.4
\value RGB_DXT1 Equivalent to GL_COMPRESSED_RGB_S3TC_DXT1_EXT
\value RGBA_DXT1 Equivalent to GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
@@ -1348,6 +1580,7 @@ QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target
\value BGR_Integer Equivalent to GL_BGR_INTEGER
\value RGBA_Integer Equivalent to GL_RGBA_INTEGER
\value BGRA_Integer Equivalent to GL_BGRA_INTEGER
+ \value Stencil Equivalent to GL_STENCIL_INDEX. Introduced in Qt 5.4
\value Depth Equivalent to GL_DEPTH_COMPONENT
\value DepthStencil Equivalent to GL_DEPTH_STENCIL
\value Alpha Equivalent to GL_ALPHA (OpenGL ES 2 only)
@@ -1380,8 +1613,12 @@ QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target
\value UInt16_R5G6B5_Rev Equivalent to GL_UNSIGNED_SHORT_5_6_5_REV
\value UInt16_RGBA4 Equivalent to GL_UNSIGNED_SHORT_4_4_4_4
\value UInt16_RGBA4_Rev Equivalent to GL_UNSIGNED_SHORT_4_4_4_4_REV
+ \value UInt32_RGBA8 Equivalent to GL_UNSIGNED_INT_8_8_8_8
+ \value UInt32_RGBA8_Rev Equivalent to GL_UNSIGNED_INT_8_8_8_8_REV
\value UInt32_RGB10A2 Equivalent to GL_UNSIGNED_INT_10_10_10_2
\value UInt32_RGB10A2_Rev Equivalent to GL_UNSIGNED_INT_2_10_10_10_REV
+ \value UInt32_D24S8 Equivalent to GL_UNSIGNED_INT_24_8. Introduced in Qt 5.4
+ \value Float32_D32_UInt32_S8_X24 Equivalent to GL_FLOAT_32_UNSIGNED_INT_24_8_REV. Introduced in Qt 5.4
*/
/*!
@@ -1483,6 +1720,17 @@ QOpenGLTexture::~QOpenGLTexture()
}
/*!
+ Returns the binding target of this texture.
+
+ \since 5.4
+*/
+QOpenGLTexture::Target QOpenGLTexture::target() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->target;
+}
+
+/*!
Creates the underlying OpenGL texture object. This requires a current valid
OpenGL context. If the texture object already exists, this function does
nothing.
@@ -1820,6 +2068,7 @@ void QOpenGLTexture::setFormat(TextureFormat format)
case D32:
case D32F:
case D32FS8X24:
+ case S8:
case DepthFormat:
case AlphaFormat:
case RGBFormat:
@@ -2063,6 +2312,125 @@ int QOpenGLTexture::faces() const
}
/*!
+ Sets the number of \a samples to allocate storage for when rendering to
+ a multisample capable texture target. This function should
+ be called before storage is allocated for the texture.
+
+ For targets that do not support multisampling this function has
+ no effect.
+
+ \sa samples(), isStorageAllocated()
+*/
+void QOpenGLTexture::setSamples(int samples)
+{
+ Q_D(QOpenGLTexture);
+ d->create();
+ if (isStorageAllocated()) {
+ qWarning("Cannot set sample count on a texture that already has storage allocated.\n"
+ "To do so, destroy() the texture and then create() and setSamples()");
+ return;
+ }
+
+ switch (d->target) {
+ case QOpenGLTexture::Target2DMultisample:
+ case QOpenGLTexture::Target2DMultisampleArray:
+ d->samples = samples;
+ break;
+
+ case QOpenGLTexture::Target1D:
+ case QOpenGLTexture::Target2D:
+ case QOpenGLTexture::Target3D:
+ case QOpenGLTexture::Target1DArray:
+ case QOpenGLTexture::Target2DArray:
+ case QOpenGLTexture::TargetCubeMap:
+ case QOpenGLTexture::TargetCubeMapArray:
+ case QOpenGLTexture::TargetBuffer:
+ case QOpenGLTexture::TargetRectangle:
+
+ qWarning("Texture target does not support multisampling");
+ break;
+ }
+}
+
+/*!
+ Returns the number of multisample sample points for this texture.
+ If storage has not yet been allocated for this texture then
+ this function returns the requested number of samples.
+
+ For texture targets that do not support multisampling this
+ will return 0.
+
+ \sa setSamples(), isStorageAllocated()
+*/
+int QOpenGLTexture::samples() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->samples;
+}
+
+/*!
+ Sets whether the sample positions and number of samples used with
+ a multisample capable texture target to \a fixed. If set to \c true
+ the sample positions and number of samples used are the same for
+ all texels in the image and will not depend upon the image size or
+ internal format. This function should be called before storage is allocated
+ for the texture.
+
+ For targets that do not support multisampling this function has
+ no effect.
+
+ The default value is \c true.
+
+ \sa isFixedSamplePositions(), isStorageAllocated()
+*/
+void QOpenGLTexture::setFixedSamplePositions(bool fixed)
+{
+ Q_D(QOpenGLTexture);
+ d->create();
+ if (isStorageAllocated()) {
+ qWarning("Cannot set sample positions on a texture that already has storage allocated.\n"
+ "To do so, destroy() the texture and then create() and setFixedSamplePositions()");
+ return;
+ }
+
+ switch (d->target) {
+ case QOpenGLTexture::Target2DMultisample:
+ case QOpenGLTexture::Target2DMultisampleArray:
+ d->fixedSamplePositions = fixed;
+ break;
+
+ case QOpenGLTexture::Target1D:
+ case QOpenGLTexture::Target2D:
+ case QOpenGLTexture::Target3D:
+ case QOpenGLTexture::Target1DArray:
+ case QOpenGLTexture::Target2DArray:
+ case QOpenGLTexture::TargetCubeMap:
+ case QOpenGLTexture::TargetCubeMapArray:
+ case QOpenGLTexture::TargetBuffer:
+ case QOpenGLTexture::TargetRectangle:
+
+ qWarning("Texture target does not support multisampling");
+ break;
+ }
+}
+
+/*!
+ Returns whether this texture uses a fixed pattern of multisample
+ samples. If storage has not yet been allocated for this texture then
+ this function returns the requested fixed sample position setting.
+
+ For texture targets that do not support multisampling this
+ will return \c true.
+
+ \sa setFixedSamplePositions(), isStorageAllocated()
+*/
+bool QOpenGLTexture::isFixedSamplePositions() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->fixedSamplePositions;
+}
+
+/*!
Allocates server-side storage for this texture object taking
into account, the format, dimensions, mipmap levels, array
layers and cubemap faces.
@@ -2298,7 +2666,16 @@ void QOpenGLTexture::setData(PixelFormat sourceFormat, PixelType sourceType,
*/
void QOpenGLTexture::setData(const QImage& image, MipMapGeneration genMipMaps)
{
- setFormat(QOpenGLTexture::RGBA8_UNorm);
+ QOpenGLContext *context = QOpenGLContext::currentContext();
+ if (!context) {
+ qWarning("QOpenGLTexture::setData() requires a valid current context");
+ return;
+ }
+ if (context->isOpenGLES() && context->format().majorVersion() < 3)
+ setFormat(QOpenGLTexture::RGBAFormat);
+ else
+ setFormat(QOpenGLTexture::RGBA8_UNorm);
+
setSize(image.width(), image.height());
setMipLevels(genMipMaps == GenerateMipMaps ? maximumMipLevels() : 1);
allocateStorage();
diff --git a/src/gui/opengl/qopengltexture.h b/src/gui/opengl/qopengltexture.h
index 0c272456f6..1f4e0c048f 100644
--- a/src/gui/opengl/qopengltexture.h
+++ b/src/gui/opengl/qopengltexture.h
@@ -100,6 +100,8 @@ public:
explicit QOpenGLTexture(const QImage& image, MipMapGeneration genMipMaps = GenerateMipMaps);
~QOpenGLTexture();
+ Target target() const;
+
// Creation and destruction
bool create();
void destroy();
@@ -201,6 +203,7 @@ public:
D32 = 0x81A7, // GL_DEPTH_COMPONENT32
D32F = 0x8CAC, // GL_DEPTH_COMPONENT32F
D32FS8X24 = 0x8CAD, // GL_DEPTH32F_STENCIL8
+ S8 = 0x8D48, // GL_STENCIL_INDEX8
// Compressed formats
RGB_DXT1 = 0x83F0, // GL_COMPRESSED_RGB_S3TC_DXT1_EXT
@@ -272,6 +275,10 @@ public:
void setLayers(int layers);
int layers() const;
int faces() const;
+ void setSamples(int samples);
+ int samples() const;
+ void setFixedSamplePositions(bool fixed);
+ bool isFixedSamplePositions() const;
void allocateStorage();
bool isStorageAllocated() const;
@@ -304,6 +311,7 @@ public:
BGR_Integer = 0x8D9A, // GL_BGR_INTEGER
RGBA_Integer = 0x8D99, // GL_RGBA_INTEGER
BGRA_Integer = 0x8D9B, // GL_BGRA_INTEGER
+ Stencil = 0x1901, // GL_STENCIL_INDEX
Depth = 0x1902, // GL_DEPTH_COMPONENT
DepthStencil = 0x84F9, // GL_DEPTH_STENCIL
Alpha = 0x1906, // GL_ALPHA
@@ -332,8 +340,12 @@ public:
UInt16_R5G6B5_Rev = 0x8364, // GL_UNSIGNED_SHORT_5_6_5_REV
UInt16_RGBA4 = 0x8033, // GL_UNSIGNED_SHORT_4_4_4_4
UInt16_RGBA4_Rev = 0x8365, // GL_UNSIGNED_SHORT_4_4_4_4_REV
+ UInt32_RGBA8 = 0x8035, // GL_UNSIGNED_INT_8_8_8_8
+ UInt32_RGBA8_Rev = 0x8367, // GL_UNSIGNED_INT_8_8_8_8_REV
UInt32_RGB10A2 = 0x8036, // GL_UNSIGNED_INT_10_10_10_2
- UInt32_RGB10A2_Rev = 0x8368 // GL_UNSIGNED_INT_2_10_10_10_REV
+ UInt32_RGB10A2_Rev = 0x8368, // GL_UNSIGNED_INT_2_10_10_10_REV
+ UInt32_D24S8 = 0x84FA, // GL_UNSIGNED_INT_24_8
+ Float32_D32_UInt32_S8_X24 = 0x8DAD // GL_FLOAT_32_UNSIGNED_INT_24_8_REV
};
// Pixel transfer
diff --git a/src/gui/opengl/qopengltextureblitter.cpp b/src/gui/opengl/qopengltextureblitter.cpp
index e6dbb70618..ef548188c8 100644
--- a/src/gui/opengl/qopengltextureblitter.cpp
+++ b/src/gui/opengl/qopengltextureblitter.cpp
@@ -67,8 +67,10 @@ static const char fragment_shader150[] =
"out vec4 fragcolor;"
"uniform sampler2D textureSampler;"
"uniform bool swizzle;"
+ "uniform float opacity;"
"void main() {"
" vec4 tmpFragColor = texture(textureSampler, uv);"
+ " tmpFragColor.a *= opacity;"
" fragcolor = swizzle ? tmpFragColor.bgra : tmpFragColor;"
"}";
@@ -87,8 +89,10 @@ static const char fragment_shader[] =
"varying highp vec2 uv;"
"uniform sampler2D textureSampler;"
"uniform bool swizzle;"
+ "uniform highp float opacity;"
"void main() {"
" highp vec4 tmpFragColor = texture2D(textureSampler,uv);"
+ " tmpFragColor.a *= opacity;"
" gl_FragColor = swizzle ? tmpFragColor.bgra : tmpFragColor;"
"}";
@@ -140,6 +144,8 @@ public:
, textureTransformUniformPos(0)
, swizzle(false)
, swizzleOld(false)
+ , opacity(1.0f)
+ , opacityOld(0.0f)
, textureMatrixUniformState(User)
, vao(new QOpenGLVertexArrayObject())
{ }
@@ -165,6 +171,11 @@ public:
program->setUniformValue(swizzleUniformPos, swizzle);
swizzleOld = swizzle;
}
+
+ if (opacity != opacityOld) {
+ program->setUniformValue(opacityUniformPos, opacity);
+ opacityOld = opacity;
+ }
}
QOpenGLBuffer vertexBuffer;
@@ -175,8 +186,11 @@ public:
GLuint textureCoordAttribPos;
GLuint textureTransformUniformPos;
GLuint swizzleUniformPos;
+ GLuint opacityUniformPos;
bool swizzle;
bool swizzleOld;
+ float opacity;
+ float opacityOld;
TextureMatrixUniform textureMatrixUniformState;
QScopedPointer<QOpenGLVertexArrayObject> vao;
};
@@ -274,6 +288,7 @@ bool QOpenGLTextureBlitter::create()
d->textureCoordAttribPos = d->program->attributeLocation("textureCoord");
d->textureTransformUniformPos = d->program->uniformLocation("textureTransform");
d->swizzleUniformPos = d->program->uniformLocation("swizzle");
+ d->opacityUniformPos = d->program->uniformLocation("opacity");
d->program->setUniformValue(d->swizzleUniformPos,false);
@@ -329,6 +344,12 @@ void QOpenGLTextureBlitter::setSwizzleRB(bool swizzle)
d->swizzle = swizzle;
}
+void QOpenGLTextureBlitter::setOpacity(float opacity)
+{
+ Q_D(QOpenGLTextureBlitter);
+ d->opacity = opacity;
+}
+
void QOpenGLTextureBlitter::blit(GLuint texture,
const QMatrix4x4 &targetTransform,
Origin sourceOrigin)
diff --git a/src/gui/opengl/qopengltextureblitter_p.h b/src/gui/opengl/qopengltextureblitter_p.h
index c1dcaf5700..b4310e5f94 100644
--- a/src/gui/opengl/qopengltextureblitter_p.h
+++ b/src/gui/opengl/qopengltextureblitter_p.h
@@ -69,6 +69,7 @@ public:
void release();
void setSwizzleRB(bool swizzle);
+ void setOpacity(float opacity);
void blit(GLuint texture, const QMatrix4x4 &targetTransform, Origin sourceOrigin);
void blit(GLuint texture, const QMatrix4x4 &targetTransform, const QMatrix3x3 &sourceTransform);
diff --git a/src/gui/opengl/qopengltexturecache.cpp b/src/gui/opengl/qopengltexturecache.cpp
index f4aa29ac0f..4a4a36d7e5 100644
--- a/src/gui/opengl/qopengltexturecache.cpp
+++ b/src/gui/opengl/qopengltexturecache.cpp
@@ -40,13 +40,27 @@
****************************************************************************/
#include "qopengltexturecache_p.h"
+#include <qmath.h>
#include <qopenglfunctions.h>
#include <private/qopenglcontext_p.h>
+#include <private/qopenglextensions_p.h>
#include <private/qimagepixmapcleanuphooks_p.h>
#include <qpa/qplatformpixmap.h>
QT_BEGIN_NAMESPACE
+#ifndef GL_BGR
+#define GL_BGR 0x80E0
+#endif
+
+#ifndef GL_BGRA
+#define GL_BGRA 0x80E1
+#endif
+
+#ifndef GL_UNSIGNED_INT_8_8_8_8_REV
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#endif
+
class QOpenGLTextureCacheWrapper
{
public:
@@ -106,7 +120,7 @@ QOpenGLTextureCache::~QOpenGLTextureCache()
{
}
-GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QPixmap &pixmap)
+GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QPixmap &pixmap, BindOptions options)
{
if (pixmap.isNull())
return 0;
@@ -116,34 +130,20 @@ GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QPixmap &
// A QPainter is active on the image - take the safe route and replace the texture.
if (!pixmap.paintingActive()) {
QOpenGLCachedTexture *entry = m_cache.object(key);
- if (entry) {
+ if (entry && entry->options() == options) {
context->functions()->glBindTexture(GL_TEXTURE_2D, entry->id());
return entry->id();
}
}
- GLuint id = bindTexture(context, key, pixmap.toImage());
+ GLuint id = bindTexture(context, key, pixmap.toImage(), options);
if (id > 0)
QImagePixmapCleanupHooks::enableCleanupHooks(pixmap);
return id;
}
-// returns the highest number closest to v, which is a power of 2
-// NB! assumes 32 bit ints
-static int qt_next_power_of_two(int v)
-{
- v--;
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
- ++v;
- return v;
-}
-
-GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QImage &image)
+GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QImage &image, BindOptions options)
{
if (image.isNull())
return 0;
@@ -153,7 +153,7 @@ GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QImage &i
// A QPainter is active on the image - take the safe route and replace the texture.
if (!image.paintingActive()) {
QOpenGLCachedTexture *entry = m_cache.object(key);
- if (entry) {
+ if (entry && entry->options() == options) {
context->functions()->glBindTexture(GL_TEXTURE_2D, entry->id());
return entry->id();
}
@@ -164,33 +164,126 @@ GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QImage &i
// Scale the pixmap if needed. GL textures needs to have the
// dimensions 2^n+2(border) x 2^m+2(border), unless we're using GL
// 2.0 or use the GL_TEXTURE_RECTANGLE texture target
- int tx_w = qt_next_power_of_two(image.width());
- int tx_h = qt_next_power_of_two(image.height());
+ int tx_w = qNextPowerOfTwo(image.width() - 1);
+ int tx_h = qNextPowerOfTwo(image.height() - 1);
if (tx_w != image.width() || tx_h != image.height()) {
img = img.scaled(tx_w, tx_h);
}
}
- GLuint id = bindTexture(context, key, img);
+ GLuint id = bindTexture(context, key, img, options);
if (id > 0)
QImagePixmapCleanupHooks::enableCleanupHooks(image);
return id;
}
-GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, qint64 key, const QImage &image)
+GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, qint64 key, const QImage &image, BindOptions options)
{
GLuint id;
QOpenGLFunctions *funcs = context->functions();
funcs->glGenTextures(1, &id);
funcs->glBindTexture(GL_TEXTURE_2D, id);
- QImage tx = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied);
+ QImage tx;
+ GLenum externalFormat;
+ GLenum internalFormat;
+ GLuint pixelType;
+ QImage::Format targetFormat = QImage::Format_Invalid;
+ const bool isOpenGL12orBetter = !context->isOpenGLES() && (context->format().majorVersion() >= 2 || context->format().minorVersion() >= 2);
+
+ switch (image.format()) {
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ if (isOpenGL12orBetter) {
+ externalFormat = GL_BGRA;
+ internalFormat = GL_RGBA;
+ pixelType = GL_UNSIGNED_INT_8_8_8_8_REV;
+ } else {
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ // Without GL_UNSIGNED_INT_8_8_8_8_REV, BGRA only matches ARGB on little endian.
+ break;
+#endif
+ if (static_cast<QOpenGLExtensions*>(context->functions())->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat)) {
+ // GL_EXT_bgra or GL_EXT_texture_format_BGRA8888 extensions.
+ if (context->isOpenGLES()) {
+ // The GL_EXT_texture_format_BGRA8888 extension requires the internal format to match the external.
+ externalFormat = internalFormat = GL_BGRA;
+ } else {
+ // OpenGL BGRA/BGR format is not allowed as an internal format
+ externalFormat = GL_BGRA;
+ internalFormat = GL_RGBA;
+ }
+ pixelType = GL_UNSIGNED_BYTE;
+ } else if (context->isOpenGLES() && context->hasExtension(QByteArrayLiteral("GL_APPLE_texture_format_BGRA8888"))) {
+ // Is only allowed as an external format like OpenGL.
+ externalFormat = GL_BGRA;
+ internalFormat = GL_RGBA;
+ pixelType = GL_UNSIGNED_BYTE;
+ } else {
+ // No support for direct ARGB32 upload.
+ break;
+ }
+ }
+ targetFormat = image.format();
+ break;
+ case QImage::Format_RGB444:
+ case QImage::Format_RGB555:
+ case QImage::Format_RGB16:
+ if (isOpenGL12orBetter || context->isOpenGLES()) {
+ externalFormat = internalFormat = GL_RGB;
+ pixelType = GL_UNSIGNED_SHORT_5_6_5;
+ targetFormat = QImage::Format_RGB16;
+ }
+ break;
+ case QImage::Format_RGB666:
+ case QImage::Format_RGB888:
+ externalFormat = internalFormat = GL_RGB;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = QImage::Format_RGB888;
+ break;
+ case QImage::Format_RGBX8888:
+ case QImage::Format_RGBA8888:
+ case QImage::Format_RGBA8888_Premultiplied:
+ externalFormat = internalFormat = GL_RGBA;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = image.format();
+ break;
+ default:
+ break;
+ }
+
+ if (targetFormat == QImage::Format_Invalid) {
+ externalFormat = internalFormat = GL_RGBA;
+ pixelType = GL_UNSIGNED_BYTE;
+ if (!image.hasAlphaChannel())
+ targetFormat = QImage::Format_RGBX8888;
+ else
+ targetFormat = QImage::Format_RGBA8888;
+ }
+
+ if (options & PremultipliedAlphaBindOption) {
+ if (targetFormat == QImage::Format_ARGB32)
+ targetFormat = QImage::Format_ARGB32_Premultiplied;
+ else if (targetFormat == QImage::Format_RGBA8888)
+ targetFormat = QImage::Format_RGBA8888_Premultiplied;
+ } else {
+ if (targetFormat == QImage::Format_ARGB32_Premultiplied)
+ targetFormat = QImage::Format_ARGB32;
+ else if (targetFormat == QImage::Format_RGBA8888_Premultiplied)
+ targetFormat = QImage::Format_RGBA8888;
+ }
+
+ if (image.format() != targetFormat)
+ tx = image.convertToFormat(targetFormat);
+ else
+ tx = image;
- funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tx.width(), tx.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, const_cast<const QImage &>(tx).bits());
+ funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, tx.width(), tx.height(), 0, externalFormat, pixelType, const_cast<const QImage &>(tx).bits());
- int cost = tx.width() * tx.height() * 4 / 1024;
- m_cache.insert(key, new QOpenGLCachedTexture(id, context), cost);
+ int cost = tx.width() * tx.height() * tx.depth() / (1024 * 8);
+ m_cache.insert(key, new QOpenGLCachedTexture(id, options, context), cost);
return id;
}
@@ -216,7 +309,7 @@ static void freeTexture(QOpenGLFunctions *funcs, GLuint id)
funcs->glDeleteTextures(1, &id);
}
-QOpenGLCachedTexture::QOpenGLCachedTexture(GLuint id, QOpenGLContext *context)
+QOpenGLCachedTexture::QOpenGLCachedTexture(GLuint id, int options, QOpenGLContext *context) : m_options(options)
{
m_resource = new QOpenGLSharedResourceGuard(context, id, freeTexture);
}
diff --git a/src/gui/opengl/qopengltexturecache_p.h b/src/gui/opengl/qopengltexturecache_p.h
index 2e82d5f373..d81115fefc 100644
--- a/src/gui/opengl/qopengltexturecache_p.h
+++ b/src/gui/opengl/qopengltexturecache_p.h
@@ -64,13 +64,15 @@ QT_BEGIN_NAMESPACE
class QOpenGLCachedTexture
{
public:
- QOpenGLCachedTexture(GLuint id, QOpenGLContext *context);
+ QOpenGLCachedTexture(GLuint id, int options, QOpenGLContext *context);
~QOpenGLCachedTexture() { m_resource->free(); }
GLuint id() const { return m_resource->id(); }
+ int options() const { return m_options; }
private:
QOpenGLSharedResourceGuard *m_resource;
+ int m_options;
};
class Q_GUI_EXPORT QOpenGLTextureCache : public QOpenGLSharedResource
@@ -81,8 +83,14 @@ public:
QOpenGLTextureCache(QOpenGLContext *);
~QOpenGLTextureCache();
- GLuint bindTexture(QOpenGLContext *context, const QPixmap &pixmap);
- GLuint bindTexture(QOpenGLContext *context, const QImage &image);
+ enum BindOption {
+ NoBindOption = 0x0000,
+ PremultipliedAlphaBindOption = 0x0001,
+ };
+ Q_DECLARE_FLAGS(BindOptions, BindOption)
+
+ GLuint bindTexture(QOpenGLContext *context, const QPixmap &pixmap, QOpenGLTextureCache::BindOptions options = PremultipliedAlphaBindOption);
+ GLuint bindTexture(QOpenGLContext *context, const QImage &image, QOpenGLTextureCache::BindOptions options = PremultipliedAlphaBindOption);
void invalidate(qint64 key);
@@ -90,12 +98,14 @@ public:
void freeResource(QOpenGLContext *ctx);
private:
- GLuint bindTexture(QOpenGLContext *context, qint64 key, const QImage &image);
+ GLuint bindTexture(QOpenGLContext *context, qint64 key, const QImage &image, QOpenGLTextureCache::BindOptions options);
QMutex m_mutex;
QCache<quint64, QOpenGLCachedTexture> m_cache;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLTextureCache::BindOptions)
+
QT_END_NAMESPACE
#endif
diff --git a/src/gui/opengl/qopenglversionfunctions.cpp b/src/gui/opengl/qopenglversionfunctions.cpp
index 5949eb6391..3335a88cbb 100644
--- a/src/gui/opengl/qopenglversionfunctions.cpp
+++ b/src/gui/opengl/qopenglversionfunctions.cpp
@@ -227,7 +227,9 @@ QOpenGLFunctions_1_0_CoreBackend::QOpenGLFunctions_1_0_CoreBackend(QOpenGLContex
{
// OpenGL 1.0 core functions
#if defined(Q_OS_WIN)
- HMODULE handle = GetModuleHandleA("opengl32.dll");
+ HMODULE handle = static_cast<HMODULE>(QOpenGLContext::openGLModuleHandle());
+ if (!handle)
+ handle = GetModuleHandleA("opengl32.dll");
Viewport = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLint , GLint , GLsizei , GLsizei )>(GetProcAddress(handle, "glViewport"));
DepthRange = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLdouble , GLdouble )>(GetProcAddress(handle, "glDepthRange"));
IsEnabled = reinterpret_cast<GLboolean (QOPENGLF_APIENTRYP)(GLenum )>(GetProcAddress(handle, "glIsEnabled"));
@@ -339,7 +341,9 @@ QOpenGLFunctions_1_1_CoreBackend::QOpenGLFunctions_1_1_CoreBackend(QOpenGLContex
{
// OpenGL 1.1 core functions
#if defined(Q_OS_WIN)
- HMODULE handle = GetModuleHandleA("opengl32.dll");
+ HMODULE handle = static_cast<HMODULE>(QOpenGLContext::openGLModuleHandle());
+ if (!handle)
+ handle = GetModuleHandleA("opengl32.dll");
Indexubv = reinterpret_cast<void (QOPENGLF_APIENTRYP)(const GLubyte *)>(GetProcAddress(handle, "glIndexubv"));
Indexub = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLubyte )>(GetProcAddress(handle, "glIndexub"));
IsTexture = reinterpret_cast<GLboolean (QOPENGLF_APIENTRYP)(GLuint )>(GetProcAddress(handle, "glIsTexture"));
@@ -991,7 +995,9 @@ QOpenGLFunctions_1_0_DeprecatedBackend::QOpenGLFunctions_1_0_DeprecatedBackend(Q
{
// OpenGL 1.0 deprecated functions
#if defined(Q_OS_WIN)
- HMODULE handle = GetModuleHandleA("opengl32.dll");
+ HMODULE handle = static_cast<HMODULE>(QOpenGLContext::openGLModuleHandle());
+ if (!handle)
+ handle = GetModuleHandleA("opengl32.dll");
Translatef = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLfloat , GLfloat , GLfloat )>(GetProcAddress(handle, "glTranslatef"));
Translated = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLdouble , GLdouble , GLdouble )>(GetProcAddress(handle, "glTranslated"));
Scalef = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLfloat , GLfloat , GLfloat )>(GetProcAddress(handle, "glScalef"));
@@ -1523,7 +1529,9 @@ QOpenGLFunctions_1_1_DeprecatedBackend::QOpenGLFunctions_1_1_DeprecatedBackend(Q
{
// OpenGL 1.1 deprecated functions
#if defined(Q_OS_WIN)
- HMODULE handle = GetModuleHandleA("opengl32.dll");
+ HMODULE handle = static_cast<HMODULE>(QOpenGLContext::openGLModuleHandle());
+ if (!handle)
+ handle = GetModuleHandleA("opengl32.dll");
PushClientAttrib = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLbitfield )>(GetProcAddress(handle, "glPushClientAttrib"));
PopClientAttrib = reinterpret_cast<void (QOPENGLF_APIENTRYP)()>(GetProcAddress(handle, "glPopClientAttrib"));
PrioritizeTextures = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLsizei , const GLuint *, const GLfloat *)>(GetProcAddress(handle, "glPrioritizeTextures"));
diff --git a/src/gui/opengl/qopenglvertexarrayobject.cpp b/src/gui/opengl/qopenglvertexarrayobject.cpp
index 5ebfc9a9c8..d9b9385751 100644
--- a/src/gui/opengl/qopenglvertexarrayobject.cpp
+++ b/src/gui/opengl/qopenglvertexarrayobject.cpp
@@ -60,20 +60,34 @@ public:
QVertexArrayObjectHelper(QOpenGLContext *context)
{
Q_ASSERT(context);
+ bool tryARB = true;
+
if (context->isOpenGLES()) {
- GenVertexArrays = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLsizei , GLuint *)>(context->getProcAddress(QByteArrayLiteral("glGenVertexArraysOES")));
- DeleteVertexArrays = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLsizei , const GLuint *)>(context->getProcAddress(QByteArrayLiteral("glDeleteVertexArraysOES")));
- BindVertexArray = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint )>(context->getProcAddress(QByteArrayLiteral("glBindVertexArrayOES")));
- } else {
- if (context->hasExtension(QByteArrayLiteral("GL_APPLE_vertex_array_object"))) {
- GenVertexArrays = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLsizei , GLuint *)>(context->getProcAddress(QByteArrayLiteral("glGenVertexArraysAPPLE")));
- DeleteVertexArrays = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLsizei , const GLuint *)>(context->getProcAddress(QByteArrayLiteral("glDeleteVertexArraysAPPLE")));
- BindVertexArray = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint )>(context->getProcAddress(QByteArrayLiteral("glBindVertexArrayAPPLE")));
- } else {
- GenVertexArrays = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLsizei , GLuint *)>(context->getProcAddress(QByteArrayLiteral("glGenVertexArrays")));
- DeleteVertexArrays = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLsizei , const GLuint *)>(context->getProcAddress(QByteArrayLiteral("glDeleteVertexArrays")));
- BindVertexArray = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint )>(context->getProcAddress(QByteArrayLiteral("glBindVertexArray")));
+#ifdef QT_OPENGL_ES_3
+ GenVertexArrays = ::glGenVertexArrays;
+ DeleteVertexArrays = ::glDeleteVertexArrays;
+ BindVertexArray = ::glBindVertexArray;
+ tryARB = false;
+#else
+ if (context->hasExtension(QByteArrayLiteral("GL_OES_vertex_array_object"))) {
+ GenVertexArrays = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLsizei , GLuint *)>(context->getProcAddress(QByteArrayLiteral("glGenVertexArraysOES")));
+ DeleteVertexArrays = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLsizei , const GLuint *)>(context->getProcAddress(QByteArrayLiteral("glDeleteVertexArraysOES")));
+ BindVertexArray = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint )>(context->getProcAddress(QByteArrayLiteral("glBindVertexArrayOES")));
+ tryARB = false;
}
+#endif
+ } else if (!context->hasExtension(QByteArrayLiteral("GL_ARB_vertex_array_object"))
+ && context->hasExtension(QByteArrayLiteral("GL_APPLE_vertex_array_object"))) {
+ GenVertexArrays = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLsizei , GLuint *)>(context->getProcAddress(QByteArrayLiteral("glGenVertexArraysAPPLE")));
+ DeleteVertexArrays = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLsizei , const GLuint *)>(context->getProcAddress(QByteArrayLiteral("glDeleteVertexArraysAPPLE")));
+ BindVertexArray = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint )>(context->getProcAddress(QByteArrayLiteral("glBindVertexArrayAPPLE")));
+ tryARB = false;
+ }
+
+ if (tryARB) {
+ GenVertexArrays = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLsizei , GLuint *)>(context->getProcAddress(QByteArrayLiteral("glGenVertexArrays")));
+ DeleteVertexArrays = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLsizei , const GLuint *)>(context->getProcAddress(QByteArrayLiteral("glDeleteVertexArrays")));
+ BindVertexArray = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint )>(context->getProcAddress(QByteArrayLiteral("glBindVertexArray")));
}
}
@@ -93,7 +107,7 @@ public:
}
private:
- // Function signatures are equivalent between desktop core, ARB, APPLE and ES 2 extensions
+ // Function signatures are equivalent between desktop core, ARB, APPLE, ES3 and ES 2 extensions
void (QOPENGLF_APIENTRYP GenVertexArrays)(GLsizei n, GLuint *arrays);
void (QOPENGLF_APIENTRYP DeleteVertexArrays)(GLsizei n, const GLuint *arrays);
void (QOPENGLF_APIENTRYP BindVertexArray)(GLuint array);
@@ -160,7 +174,7 @@ bool QOpenGLVertexArrayObjectPrivate::create()
QObject::connect(context, SIGNAL(aboutToBeDestroyed()), q, SLOT(_q_contextAboutToBeDestroyed()));
if (ctx->isOpenGLES()) {
- if (ctx->hasExtension(QByteArrayLiteral("GL_OES_vertex_array_object"))) {
+ if (ctx->format().majorVersion() >= 3 || ctx->hasExtension(QByteArrayLiteral("GL_OES_vertex_array_object"))) {
vaoFuncs.helper = new QVertexArrayObjectHelper(ctx);
vaoFuncsType = OES;
vaoFuncs.helper->glGenVertexArrays(1, &vao);
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index ed45b8ea17..31c0c214d5 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -91,15 +91,14 @@ SOURCES += \
painting/qpaintbuffer.cpp \
painting/qpathsimplifier.cpp
-contains(QT_CPU_FEATURES.$$QT_ARCH, sse2) {
- SOURCES += painting/qdrawhelper_sse2.cpp
- SSSE3_SOURCES += painting/qdrawhelper_ssse3.cpp
-}
+SSE2_SOURCES += painting/qdrawhelper_sse2.cpp
+SSSE3_SOURCES += painting/qdrawhelper_ssse3.cpp
IWMMXT_SOURCES += painting/qdrawhelper_iwmmxt.cpp
-!ios:contains(QT_CPU_FEATURES.$$QT_ARCH, neon) {
- SOURCES += painting/qdrawhelper_neon.cpp
- HEADERS += painting/qdrawhelper_neon_p.h
+!ios {
+ CONFIG += no_clang_integrated_as
+ NEON_SOURCES += painting/qdrawhelper_neon.cpp
+ NEON_HEADERS += painting/qdrawhelper_neon_p.h
NEON_ASM += ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S
}
diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp
index f22c37aecc..438eb6f34f 100644
--- a/src/gui/painting/qblendfunctions.cpp
+++ b/src/gui/painting/qblendfunctions.cpp
@@ -403,7 +403,168 @@ void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl,
}
}
+template<QtPixelOrder PixelOrder>
+static void qt_blend_argb32pm_on_a2rgb30pm(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
+{
+#ifdef QT_DEBUG_DRAW
+ fprintf(stdout, "qt_blend_argb32pm_on_a2rgb30pm: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n",
+ destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
+ fflush(stdout);
+#endif
+
+ const uint *src = (const uint *) srcPixels;
+ uint *dst = (uint *) destPixels;
+ if (const_alpha == 256) {
+ for (int y=0; y<h; ++y) {
+ for (int x=0; x<w; ++x) {
+ uint s = src[x];
+ dst[x] = qConvertArgb32ToA2rgb30<PixelOrder>(s) + BYTE_MUL_RGB30(dst[x], 255 - qAlpha(s));
+ }
+ dst = (quint32 *)(((uchar *) dst) + dbpl);
+ src = (const quint32 *)(((const uchar *) src) + sbpl);
+ }
+ } else if (const_alpha != 0) {
+ const_alpha = (const_alpha * 255) >> 8;
+ for (int y=0; y<h; ++y) {
+ for (int x=0; x<w; ++x) {
+ uint s = BYTE_MUL(src[x], const_alpha);
+ dst[x] = qConvertArgb32ToA2rgb30<PixelOrder>(s) + BYTE_MUL_RGB30(dst[x], 255 - qAlpha(s));
+ }
+ dst = (quint32 *)(((uchar *) dst) + dbpl);
+ src = (const quint32 *)(((const uchar *) src) + sbpl);
+ }
+ }
+}
+
+template<QtPixelOrder PixelOrder>
+void qt_blend_rgb32_on_rgb30(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
+{
+#ifdef QT_DEBUG_DRAW
+ fprintf(stdout, "qt_blend_rgb32_on_rgb30: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n",
+ destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
+ fflush(stdout);
+#endif
+
+ if (const_alpha != 256) {
+ qt_blend_argb32pm_on_a2rgb30pm<PixelOrder>(destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
+ return;
+ }
+
+ const uint *src = (const uint *) srcPixels;
+ uint *dst = (uint *) destPixels;
+ for (int y = 0; y < h; ++y) {
+ for (int x = 0; x < w; ++x) {
+ dst[x] = qConvertRgb32ToRgb30<PixelOrder>(src[x]);
+ }
+ dst = (quint32 *)(((uchar *) dst) + dbpl);
+ src = (const quint32 *)(((const uchar *) src) + sbpl);
+ }
+}
+
+static void qt_blend_a2rgb30pm_on_a2rgb30pm(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
+{
+#ifdef QT_DEBUG_DRAW
+ fprintf(stdout, "qt_blend_a2rgb30pm_on_a2rgb30pm: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n",
+ destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
+ fflush(stdout);
+#endif
+
+ const uint *src = (const uint *) srcPixels;
+ uint *dst = (uint *) destPixels;
+ if (const_alpha == 256) {
+ for (int y=0; y<h; ++y) {
+ for (int x=0; x<w; ++x) {
+ uint s = src[x];
+ dst[x] = s + BYTE_MUL_RGB30(dst[x], 255 - qAlphaRgb30(s));
+ }
+ dst = (quint32 *)(((uchar *) dst) + dbpl);
+ src = (const quint32 *)(((const uchar *) src) + sbpl);
+ }
+ } else if (const_alpha != 0) {
+ const uint const_alpha255 = (const_alpha * 255) >> 8;
+ for (int y=0; y<h; ++y) {
+ for (int x=0; x<w; ++x) {
+ uint a = (qAlphaRgb30(src[x]) * const_alpha) >> 8;
+ uint s = BYTE_MUL_RGB30(src[x], const_alpha255);
+ dst[x] = s + BYTE_MUL_RGB30(dst[x], 255 - a);
+ }
+ dst = (quint32 *)(((uchar *) dst) + dbpl);
+ src = (const quint32 *)(((const uchar *) src) + sbpl);
+ }
+ }
+}
+
+
+void qt_blend_rgb30_on_rgb30(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
+{
+#ifdef QT_DEBUG_DRAW
+ fprintf(stdout, "qt_blend_rgb30_on_rgb30: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n",
+ destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
+ fflush(stdout);
+#endif
+
+ if (const_alpha != 256) {
+ qt_blend_a2rgb30pm_on_a2rgb30pm(destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
+ return;
+ }
+
+ const uint *src = (const uint *) srcPixels;
+ uint *dst = (uint *) destPixels;
+ int len = w * 4;
+ for (int y=0; y<h; ++y) {
+ memcpy(dst, src, len);
+ dst = (quint32 *)(((uchar *) dst) + dbpl);
+ src = (const quint32 *)(((const uchar *) src) + sbpl);
+ }
+}
+static void qt_blend_a2bgr30pm_on_a2rgb30pm(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
+{
+#ifdef QT_DEBUG_DRAW
+ fprintf(stdout, "qt_blend_a2bgr30pm_on_a2rgb32pm: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n",
+ destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
+ fflush(stdout);
+#endif
+
+ const uint *src = (const uint *) srcPixels;
+ uint *dst = (uint *) destPixels;
+ if (const_alpha == 256) {
+ for (int y=0; y<h; ++y) {
+ for (int x=0; x<w; ++x) {
+ uint s = qRgbSwapRgb30(src[x]);
+ dst[x] = s + BYTE_MUL_RGB30(dst[x], 255 - qAlphaRgb30(s));
+ }
+ dst = (quint32 *)(((uchar *) dst) + dbpl);
+ src = (const quint32 *)(((const uchar *) src) + sbpl);
+ }
+ } else if (const_alpha != 0) {
+ const uint const_alpha255 = (const_alpha * 255) >> 8;
+ for (int y=0; y<h; ++y) {
+ for (int x=0; x<w; ++x) {
+ uint a = (qAlphaRgb30(src[x]) * const_alpha) >> 8;
+ uint s = BYTE_MUL_RGB30(src[x], const_alpha255);
+ dst[x] = qRgbSwapRgb30(s) + BYTE_MUL_RGB30(dst[x], 255 - a);
+ }
+ dst = (quint32 *)(((uchar *) dst) + dbpl);
+ src = (const quint32 *)(((const uchar *) src) + sbpl);
+ }
+ }
+}
struct Blend_RGB32_on_RGB32_NoAlpha {
inline void write(quint32 *dst, quint32 src) { *dst = src; }
@@ -607,7 +768,11 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGRs30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_Mono
0, // Format_Invalid,
@@ -628,7 +793,11 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_MonoLSB
0, // Format_Invalid,
@@ -649,7 +818,11 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_Indexed8
0, // Format_Invalid,
@@ -670,7 +843,11 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGB32
0, // Format_Invalid,
@@ -691,7 +868,11 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_ARGB32
0, // Format_Invalid,
@@ -712,7 +893,11 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_ARGB32_Premultiplied
0, // Format_Invalid,
@@ -733,7 +918,11 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGB16
0, // Format_Invalid,
@@ -754,7 +943,11 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_ARGB8565_Premultiplied
0, // Format_Invalid,
@@ -775,7 +968,11 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGB666
0, // Format_Invalid,
@@ -796,7 +993,11 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_ARGB6666_Premultiplied
0, // Format_Invalid,
@@ -817,7 +1018,11 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGB555
0, // Format_Invalid,
@@ -838,7 +1043,11 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_ARGB8555_Premultiplied
0, // Format_Invalid,
@@ -859,7 +1068,11 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGB888
0, // Format_Invalid,
@@ -880,7 +1093,11 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGB444
0, // Format_Invalid,
@@ -901,7 +1118,11 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_ARGB4444_Premultiplied
0, // Format_Invalid,
@@ -922,7 +1143,11 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGBX8888
0, // Format_Invalid,
@@ -948,8 +1173,12 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
#else
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
#endif
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGBA8888
0, // Format_Invalid,
@@ -970,7 +1199,11 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGBA8888_Premultiplied
0, // Format_Invalid,
@@ -996,9 +1229,113 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
#else
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
#endif
- }
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
+ },
+ { // Format_BGR30
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0, // Format_ARGB4444_Premultiplied,
+ 0, // Format_RGBX8888,
+ 0, // Format_RGBA8888,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
+ },
+ { // Format_A2BGR30_Premultiplied
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0, // Format_ARGB4444_Premultiplied,
+ 0, // Format_RGBX8888,
+ 0, // Format_RGBA8888,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
+ },
+ { // Format_RGB30
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0, // Format_ARGB4444_Premultiplied,
+ 0, // Format_RGBX8888,
+ 0, // Format_RGBA8888,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
+ },
+ { // Format_A2RGB30_Premultiplied
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0, // Format_ARGB4444_Premultiplied,
+ 0, // Format_RGBX8888,
+ 0, // Format_RGBA8888,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
+ },
};
@@ -1022,7 +1359,11 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_Mono
0, // Format_Invalid,
@@ -1043,7 +1384,11 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_MonoLSB
0, // Format_Invalid,
@@ -1064,7 +1409,11 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_Indexed8
0, // Format_Invalid,
@@ -1085,7 +1434,11 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGB32
0, // Format_Invalid,
@@ -1106,7 +1459,11 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_ARGB32
0, // Format_Invalid,
@@ -1127,7 +1484,11 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_ARGB32_Premultiplied
0, // Format_Invalid,
@@ -1148,7 +1509,11 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGB16
0, // Format_Invalid,
@@ -1169,7 +1534,11 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_ARGB8565_Premultiplied
0, // Format_Invalid,
@@ -1190,7 +1559,11 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGB666
0, // Format_Invalid,
@@ -1211,7 +1584,11 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_ARGB6666_Premultiplied
0, // Format_Invalid,
@@ -1232,7 +1609,11 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGB555
0, // Format_Invalid,
@@ -1253,7 +1634,11 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_ARGB8555_Premultiplied
0, // Format_Invalid,
@@ -1274,7 +1659,11 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGB888
0, // Format_Invalid,
@@ -1295,7 +1684,11 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGB444
0, // Format_Invalid,
@@ -1316,7 +1709,11 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_ARGB4444_Premultiplied
0, // Format_Invalid,
@@ -1337,7 +1734,11 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGBX8888
0, // Format_Invalid,
@@ -1363,8 +1764,12 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] =
#else
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
#endif
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGBA8888
0, // Format_Invalid,
@@ -1385,7 +1790,11 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGBA8888_Premultiplied
0, // Format_Invalid,
@@ -1411,9 +1820,113 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] =
#else
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
#endif
- }
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0, // Format_A2RGB30_Premultiplied,
+ },
+ { // Format_BGR30
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ qt_blend_rgb32_on_rgb30<PixelOrderBGR>, // Format_RGB32,
+ 0, // Format_ARGB32,
+ qt_blend_argb32pm_on_a2rgb30pm<PixelOrderBGR>, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0, // Format_ARGB4444_Premultiplied,
+ 0, // Format_RGBX8888,
+ 0, // Format_RGBA8888,
+ 0, // Format_RGBA8888_Premultiplied,
+ qt_blend_rgb30_on_rgb30, // Format_RGB30,
+ qt_blend_a2rgb30pm_on_a2rgb30pm, // Format_A2RGB30_Premultiplied,
+ qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_RGB30,
+ qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_A2RGB30_Premultiplied,
+ },
+ { // Format_A2BGR30_Premultiplied
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ qt_blend_rgb32_on_rgb30<PixelOrderBGR>, // Format_RGB32,
+ 0, // Format_ARGB32,
+ qt_blend_argb32pm_on_a2rgb30pm<PixelOrderBGR>, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0, // Format_ARGB4444_Premultiplied,
+ 0, // Format_RGBX8888,
+ 0, // Format_RGBA8888,
+ 0, // Format_RGBA8888_Premultiplied,
+ qt_blend_rgb30_on_rgb30, // Format_BGR30,
+ qt_blend_a2rgb30pm_on_a2rgb30pm, // Format_A2BGR30_Premultiplied,
+ qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_RGB30,
+ qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_A2RGB30_Premultiplied,
+ },
+ { // Format_RGB30
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ qt_blend_rgb32_on_rgb30<PixelOrderRGB>, // Format_RGB32,
+ 0, // Format_ARGB32,
+ qt_blend_argb32pm_on_a2rgb30pm<PixelOrderRGB>, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0, // Format_ARGB4444_Premultiplied,
+ 0, // Format_RGBX8888,
+ 0, // Format_RGBA8888,
+ 0, // Format_RGBA8888_Premultiplied,
+ qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_BGR30,
+ qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_A2BGR30_Premultiplied,
+ qt_blend_rgb30_on_rgb30, // Format_RGB30,
+ qt_blend_a2rgb30pm_on_a2rgb30pm, // Format_A2RGB30_Premultiplied,
+ },
+ { // Format_A2RGB30_Premultiplied
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ qt_blend_rgb32_on_rgb30<PixelOrderRGB>, // Format_RGB32,
+ 0, // Format_ARGB32,
+ qt_blend_argb32pm_on_a2rgb30pm<PixelOrderRGB>, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0, // Format_ARGB4444_Premultiplied,
+ 0, // Format_RGBX8888,
+ 0, // Format_RGBA8888,
+ 0, // Format_RGBA8888_Premultiplied,
+ qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_BGR30,
+ qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_A2BGR30_Premultiplied,
+ qt_blend_rgb30_on_rgb30, // Format_RGB30,
+ qt_blend_a2rgb30pm_on_a2rgb30pm // Format_A2RGB30_Premultiplied,
+ },
};
SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFormats] = {
@@ -1436,7 +1949,11 @@ SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFo
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_Mono
0, // Format_Invalid,
@@ -1457,7 +1974,11 @@ SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFo
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_MonoLSB
0, // Format_Invalid,
@@ -1478,7 +1999,11 @@ SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFo
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_Indexed8
0, // Format_Invalid,
@@ -1499,7 +2024,11 @@ SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFo
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGB32
0, // Format_Invalid,
@@ -1520,7 +2049,11 @@ SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFo
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_ARGB32
0, // Format_Invalid,
@@ -1541,7 +2074,11 @@ SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFo
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_ARGB32_Premultiplied
0, // Format_Invalid,
@@ -1562,7 +2099,11 @@ SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFo
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGB16
0, // Format_Invalid,
@@ -1583,7 +2124,11 @@ SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFo
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_ARGB8565_Premultiplied
0, // Format_Invalid,
@@ -1604,7 +2149,11 @@ SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFo
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGB666
0, // Format_Invalid,
@@ -1625,7 +2174,11 @@ SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFo
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_ARGB6666_Premultiplied
0, // Format_Invalid,
@@ -1646,7 +2199,11 @@ SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFo
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGB555
0, // Format_Invalid,
@@ -1667,7 +2224,11 @@ SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFo
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_ARGB8555_Premultiplied
0, // Format_Invalid,
@@ -1688,7 +2249,11 @@ SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFo
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGB888
0, // Format_Invalid,
@@ -1709,7 +2274,11 @@ SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFo
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGB444
0, // Format_Invalid,
@@ -1730,7 +2299,11 @@ SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFo
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_ARGB4444_Premultiplied
0, // Format_Invalid,
@@ -1751,7 +2324,11 @@ SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFo
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGBX8888
0, // Format_Invalid,
@@ -1777,8 +2354,12 @@ SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFo
#else
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
#endif
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGBA8888
0, // Format_Invalid,
@@ -1799,7 +2380,11 @@ SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFo
0, // Format_ARGB4444_Premultiplied,
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
},
{ // Format_RGBA8888_Premultiplied
0, // Format_Invalid,
@@ -1825,9 +2410,113 @@ SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFo
#else
0, // Format_RGBX8888,
0, // Format_RGBA8888,
- 0 // Format_RGBA8888_Premultiplied,
+ 0, // Format_RGBA8888_Premultiplied,
#endif
- }
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
+ },
+ { // Format_BGR30
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0, // Format_ARGB4444_Premultiplied,
+ 0, // Format_RGBX8888,
+ 0, // Format_RGBA8888,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
+ },
+ { // Format_A2BGR30_Premultiplied
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0, // Format_ARGB4444_Premultiplied,
+ 0, // Format_RGBX8888,
+ 0, // Format_RGBA8888,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
+ },
+ { // Format_RGB30
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0, // Format_ARGB4444_Premultiplied,
+ 0, // Format_RGBX8888,
+ 0, // Format_RGBA8888,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
+ },
+ { // Format_A2RGB30_Premultiplied
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0, // Format_ARGB4444_Premultiplied,
+ 0, // Format_RGBX8888,
+ 0, // Format_RGBA8888,
+ 0, // Format_RGBA8888_Premultiplied,
+ 0, // Format_BGR30,
+ 0, // Format_A2BGR30_Premultiplied,
+ 0, // Format_RGB30,
+ 0 // Format_A2RGB30_Premultiplied,
+ },
};
QT_END_NAMESPACE
diff --git a/src/gui/painting/qcolor.h b/src/gui/painting/qcolor.h
index 1ede5a3682..e5de2678a4 100644
--- a/src/gui/painting/qcolor.h
+++ b/src/gui/painting/qcolor.h
@@ -173,7 +173,7 @@ public:
QColor toCmyk() const;
QColor toHsl() const;
- QColor convertTo(Spec colorSpec) const;
+ QColor convertTo(Spec colorSpec) const Q_REQUIRED_RESULT;
static QColor fromRgb(QRgb rgb);
static QColor fromRgba(QRgb rgba);
@@ -190,10 +190,10 @@ public:
static QColor fromHsl(int h, int s, int l, int a = 255);
static QColor fromHslF(qreal h, qreal s, qreal l, qreal a = 1.0);
- QColor light(int f = 150) const;
- QColor lighter(int f = 150) const;
- QColor dark(int f = 200) const;
- QColor darker(int f = 200) const;
+ QColor light(int f = 150) const Q_REQUIRED_RESULT;
+ QColor lighter(int f = 150) const Q_REQUIRED_RESULT;
+ QColor dark(int f = 200) const Q_REQUIRED_RESULT;
+ QColor darker(int f = 200) const Q_REQUIRED_RESULT;
QColor &operator=(const QColor &);
QColor &operator=(Qt::GlobalColor color);
diff --git a/src/gui/painting/qcolor_p.cpp b/src/gui/painting/qcolor_p.cpp
index 72b6279b2f..adc81582e2 100644
--- a/src/gui/painting/qcolor_p.cpp
+++ b/src/gui/painting/qcolor_p.cpp
@@ -301,9 +301,8 @@ inline bool operator<(const RGBData &data, const char *name)
static bool get_named_rgb(const char *name_no_space, QRgb *rgb)
{
- QByteArray name = QByteArray(name_no_space).toLower();
- const RGBData *r = std::lower_bound(rgbTbl, rgbTbl + rgbTblSize, name.constData());
- if ((r != rgbTbl + rgbTblSize) && !(name.constData() < *r)) {
+ const RGBData *r = std::lower_bound(rgbTbl, rgbTbl + rgbTblSize, name_no_space);
+ if ((r != rgbTbl + rgbTblSize) && !(name_no_space < *r)) {
*rgb = r->value;
return true;
}
@@ -319,7 +318,7 @@ bool qt_get_named_rgb(const char *name, QRgb* rgb)
int pos = 0;
for(int i = 0; i < len; i++) {
if(name[i] != '\t' && name[i] != ' ')
- name_no_space[pos++] = name[i];
+ name_no_space[pos++] = QChar::toLower(name[i]);
}
name_no_space[pos] = 0;
@@ -334,7 +333,7 @@ bool qt_get_named_rgb(const QChar *name, int len, QRgb *rgb)
int pos = 0;
for(int i = 0; i < len; i++) {
if(name[i] != QLatin1Char('\t') && name[i] != QLatin1Char(' '))
- name_no_space[pos++] = name[i].toLatin1();
+ name_no_space[pos++] = name[i].toLower().toLatin1();
}
name_no_space[pos] = 0;
return get_named_rgb(name_no_space, rgb);
@@ -352,6 +351,7 @@ QStringList qt_get_colornames()
{
int i = 0;
QStringList lst;
+ lst.reserve(rgbTblSize);
for (i = 0; i < rgbTblSize; i++)
lst << QLatin1String(rgbTbl[i].name);
return lst;
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 9293fc32dc..ffb952bce4 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -575,6 +575,42 @@ static const uint *QT_FASTCALL convertRGBXFromARGB32PM(uint *buffer, const uint
return buffer;
}
+template<QtPixelOrder PixelOrder>
+static const uint *QT_FASTCALL convertA2RGB30PMToARGB32PM(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = qConvertA2rgb30ToArgb32<PixelOrder>(src[i]);
+ return buffer;
+}
+
+template<QtPixelOrder PixelOrder>
+static const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = qConvertArgb32ToA2rgb30<PixelOrder>(src[i]);
+ return buffer;
+}
+
+template<QtPixelOrder PixelOrder>
+static const uint *QT_FASTCALL convertRGB30FromRGB32(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = qConvertRgb32ToRgb30<PixelOrder>(src[i]);
+ return buffer;
+}
+
+template<QtPixelOrder PixelOrder>
+static const uint *QT_FASTCALL convertRGB30FromARGB32PM(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = qConvertRgb32ToRgb30<PixelOrder>(qUnpremultiply(src[i]));
+ return buffer;
+}
+
template <QPixelLayout::BPP bpp> static
uint QT_FASTCALL fetchPixel(const uchar *src, int index);
@@ -722,8 +758,12 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
#else
{ 8, 0, 8, 8, 8, 16, 0, 24, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32 }, // Format_RGBX8888
{ 8, 0, 8, 8, 8, 16, 8, 24, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM, 0 }, // Format_RGBA8888 (ABGR32)
- { 8, 0, 8, 8, 8, 16, 8, 24, true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, 0 } // Format_RGBA8888_Premultiplied
+ { 8, 0, 8, 8, 8, 16, 8, 24, true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, 0 }, // Format_RGBA8888_Premultiplied
#endif
+ { 10, 20, 10, 10, 10, 0, 0, 30, false, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderBGR>, convertRGB30FromARGB32PM<PixelOrderBGR>, convertRGB30FromRGB32<PixelOrderBGR> }, // Format_BGR30
+ { 10, 20, 10, 10, 10, 0, 2, 30, true, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderBGR>, convertA2RGB30PMFromARGB32PM<PixelOrderBGR>, 0 }, // Format_A2BGR30_Premultiplied
+ { 10, 0, 10, 10, 10, 20, 0, 30, false, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderRGB>, convertRGB30FromARGB32PM<PixelOrderRGB>, convertRGB30FromRGB32<PixelOrderRGB> }, // Format_RGB30
+ { 10, 0, 10, 10, 10, 20, 2, 30, true, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderRGB>, convertA2RGB30PMFromARGB32PM<PixelOrderRGB>, 0 }, // Format_A2RGB30_Premultiplied
};
FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount] = {
@@ -831,6 +871,10 @@ static DestFetchProc destFetchProc[QImage::NImageFormats] =
destFetch, // Format_RGBX8888
destFetch, // Format_RGBA8888
destFetch, // Format_RGBA8888_Premultiplied
+ destFetch, // Format_BGR30
+ destFetch, // Format_A2BGR30_Premultiplied
+ destFetch, // Format_RGB30
+ destFetch, // Format_A2RGB30_Premultiplied
};
/*
@@ -970,7 +1014,11 @@ static DestStoreProc destStoreProc[QImage::NImageFormats] =
destStore, // Format_ARGB4444_Premultiplied
destStore, // Format_RGBX8888
destStore, // Format_RGBA8888
- destStore // Format_RGBA8888_Premultiplied
+ destStore, // Format_RGBA8888_Premultiplied
+ destStore, // Format_BGR30
+ destStore, // Format_A2BGR30_Premultiplied
+ destStore, // Format_RGB30
+ destStore, // Format_A2RGB30_Premultiplied
};
/*
@@ -2221,7 +2269,11 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
fetchUntransformed, // ARGB4444_Premultiplied
fetchUntransformed, // RGBX8888
fetchUntransformed, // RGBA8888
- fetchUntransformed // RGBA8888_Premultiplied
+ fetchUntransformed, // RGBA8888_Premultiplied
+ fetchUntransformed, // Format_BGR30
+ fetchUntransformed, // Format_A2BGR30_Premultiplied
+ fetchUntransformed, // Format_RGB30
+ fetchUntransformed, // Format_A2RGB30_Premultiplied
},
// Tiled
{
@@ -2243,7 +2295,11 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
fetchUntransformed, // ARGB4444_Premultiplied
fetchUntransformed, // RGBX8888
fetchUntransformed, // RGBA8888
- fetchUntransformed // RGBA8888_Premultiplied
+ fetchUntransformed, // RGBA8888_Premultiplied
+ fetchUntransformed, // BGR30
+ fetchUntransformed, // A2BGR30_Premultiplied
+ fetchUntransformed, // RGB30
+ fetchUntransformed // A2RGB30_Premultiplied
},
// Transformed
{
@@ -2266,6 +2322,10 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
fetchTransformed<BlendTransformed>, // RGBX8888
fetchTransformed<BlendTransformed>, // RGBA8888
fetchTransformed<BlendTransformed>, // RGBA8888_Premultiplied
+ fetchTransformed<BlendTransformed>, // BGR30
+ fetchTransformed<BlendTransformed>, // A2BGR30_Premultiplied
+ fetchTransformed<BlendTransformed>, // RGB30
+ fetchTransformed<BlendTransformed>, // A2RGB30_Premultiplied
},
{
0, // TransformedTiled
@@ -2287,6 +2347,10 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
fetchTransformed<BlendTransformedTiled>, // RGBX8888
fetchTransformed<BlendTransformedTiled>, // RGBA8888
fetchTransformed<BlendTransformedTiled>, // RGBA8888_Premultiplied
+ fetchTransformed<BlendTransformedTiled>, // BGR30
+ fetchTransformed<BlendTransformedTiled>, // A2BGR30_Premultiplied
+ fetchTransformed<BlendTransformedTiled>, // RGB30
+ fetchTransformed<BlendTransformedTiled>, // A2RGB30_Premultiplied
},
{
0, // Bilinear
@@ -2307,7 +2371,11 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
fetchTransformedBilinear<BlendTransformedBilinear>, // ARGB4444_Premultiplied
fetchTransformedBilinear<BlendTransformedBilinear>, // RGBX8888
fetchTransformedBilinear<BlendTransformedBilinear>, // RGBA8888
- fetchTransformedBilinear<BlendTransformedBilinear> // RGBA8888_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinear>, // RGBA8888_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinear>, // BGR30
+ fetchTransformedBilinear<BlendTransformedBilinear>, // A2BGR30_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinear>, // RGB30
+ fetchTransformedBilinear<BlendTransformedBilinear>, // A2RGB30_Premultiplied
},
{
0, // BilinearTiled
@@ -2328,7 +2396,11 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
fetchTransformedBilinear<BlendTransformedBilinearTiled>, // ARGB4444_Premultiplied
fetchTransformedBilinear<BlendTransformedBilinearTiled>, // RGBX8888
fetchTransformedBilinear<BlendTransformedBilinearTiled>, // RGBA8888
- fetchTransformedBilinear<BlendTransformedBilinearTiled> // RGBA8888_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinearTiled>, // RGBA8888_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinearTiled>, // BGR30
+ fetchTransformedBilinear<BlendTransformedBilinearTiled>, // A2BGR30_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinearTiled>, // RGB30
+ fetchTransformedBilinear<BlendTransformedBilinearTiled> // A2RGB30_Premultiplied
},
};
@@ -5749,6 +5821,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats
blend_untransformed_generic,
blend_untransformed_generic,
blend_untransformed_generic,
+ blend_untransformed_generic,
+ blend_untransformed_generic,
+ blend_untransformed_generic,
+ blend_untransformed_generic,
},
// Tiled
{
@@ -5771,6 +5847,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats
blend_tiled_generic,
blend_tiled_generic,
blend_tiled_generic,
+ blend_tiled_generic,
+ blend_tiled_generic,
+ blend_tiled_generic,
+ blend_tiled_generic,
},
// Transformed
{
@@ -5793,6 +5873,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats
blend_src_generic,
blend_src_generic,
blend_src_generic,
+ blend_src_generic,
+ blend_src_generic,
+ blend_src_generic,
+ blend_src_generic,
},
// TransformedTiled
{
@@ -5814,6 +5898,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats
blend_src_generic,
blend_src_generic,
blend_src_generic,
+ blend_src_generic,
+ blend_src_generic,
+ blend_src_generic,
+ blend_src_generic,
blend_src_generic
},
// Bilinear
@@ -5837,6 +5925,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats
blend_src_generic,
blend_src_generic,
blend_src_generic,
+ blend_src_generic,
+ blend_src_generic,
+ blend_src_generic,
+ blend_src_generic,
},
// BilinearTiled
{
@@ -5859,6 +5951,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats
blend_src_generic, // RGBX8888
blend_src_generic, // RGBA8888
blend_src_generic, // RGBA8888_Premultiplied
+ blend_src_generic, // BGR30
+ blend_src_generic, // A2BGR30_Premultiplied
+ blend_src_generic, // RGB30
+ blend_src_generic, // A2RGB30_Premultiplied
}
};
@@ -6379,7 +6475,6 @@ static void qt_rectfill_nonpremul_rgba(QRasterBuffer *rasterBuffer,
ARGB2RGBA(qUnpremultiply(color)), x, y, width, height, rasterBuffer->bytesPerLine());
}
-
// Map table for destination image format. Contains function pointers
// for blends of various types unto the destination
@@ -6527,7 +6622,43 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
#endif
0,
qt_rectfill_rgba
- }
+ },
+ // Format_BGR30
+ {
+ blend_color_generic,
+ blend_src_generic,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ // Format_A2BGR30_Premultiplied
+ {
+ blend_color_generic,
+ blend_src_generic,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ // Format_RGB30
+ {
+ blend_color_generic,
+ blend_src_generic,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ // Format_A2RGB30_Premultiplied
+ {
+ blend_color_generic,
+ blend_src_generic,
+ 0,
+ 0,
+ 0,
+ 0
+ },
};
#if defined(Q_CC_MSVC) && !defined(_MIPS_)
@@ -6588,10 +6719,13 @@ void qt_memfill16(quint16 *dest, quint16 color, int count)
}
#endif
#if !defined(__SSE2__) && !defined(__ARM_NEON__)
+# ifdef QT_COMPILER_SUPPORTS_MIPS_DSP
+extern "C" void qt_memfill32_asm_mips_dsp(quint32 *, quint32, int);
+# endif
+
void qt_memfill32(quint32 *dest, quint32 color, int count)
{
# ifdef QT_COMPILER_SUPPORTS_MIPS_DSP
- extern "C" qt_memfill32_asm_mips_dsp(quint32 *, quint32, int);
qt_memfill32_asm_mips_dsp(dest, color, count);
# else
qt_memfill_template<quint32>(dest, color, count);
@@ -6713,7 +6847,13 @@ void qInitDrawhelperAsm()
qt_fetch_radial_gradient = qt_fetch_radial_gradient_neon;
#endif
-#if defined(QT_COMPILER_SUPPORTS_MIPS_DSP)
+#ifdef Q_PROCESSOR_MIPS_32
+ qt_memfill32 = qt_memfill32_asm_mips_dsp;
+#endif // Q_PROCESSOR_MIPS_32
+
+#if defined(QT_COMPILER_SUPPORTS_MIPS_DSP) || defined(QT_COMPILER_SUPPORTS_MIPS_DSPR2)
+ if (features & (DSP | DSPR2)) {
+ // Composition functions are all DSP r1
functionForMode_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_asm_mips_dsp;
functionForMode_C[QPainter::CompositionMode_Source] = comp_func_Source_mips_dsp;
functionForMode_C[QPainter::CompositionMode_DestinationOver] = comp_func_DestinationOver_mips_dsp;
@@ -6757,8 +6897,9 @@ void qInitDrawhelperAsm()
#else
qBlendFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_blend_rgb16_on_rgb16_mips_dsp;
#endif // QT_COMPILER_SUPPORTS_MIPS_DSPR2
+ }
+#endif // QT_COMPILER_SUPPORTS_MIPS_DSP || QT_COMPILER_SUPPORTS_MIPS_DSPR2
-#endif // QT_COMPILER_SUPPORTS_MIPS_DSP
if (functionForModeSolidAsm) {
const int destinationMode = QPainter::CompositionMode_Destination;
functionForModeSolidAsm[destinationMode] = functionForModeSolid_C[destinationMode];
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index 1c05fc305a..d6b557af01 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -672,6 +672,36 @@ static Q_ALWAYS_INLINE uint BYTE_MUL_RGB16_32(uint x, uint a) {
return t;
}
+#if defined(Q_CC_RVCT)
+# pragma push
+# pragma arm
+#endif
+static Q_ALWAYS_INLINE int qt_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; }
+#if defined(Q_CC_RVCT)
+# pragma pop
+#endif
+
+static Q_ALWAYS_INLINE uint BYTE_MUL_RGB30(uint x, uint a) {
+ uint xa = x >> 30;
+ uint xr = (x >> 20) & 0x3ff;
+ uint xg = (x >> 10) & 0x3ff;
+ uint xb = x & 0x3ff;
+ xa = qt_div_255(xa * a);
+ xr = qt_div_255(xr * a);
+ xg = qt_div_255(xg * a);
+ xb = qt_div_255(xb * a);
+ return (xa << 30) | (xr << 20) | (xg << 10) | xb;
+}
+
+static Q_ALWAYS_INLINE uint qAlphaRgb30(uint c)
+{
+ uint a = c >> 30;
+ a |= a << 2;
+ a |= a << 4;
+ return a;
+}
+
+
// FIXME: Remove when all Qt modules have stopped using PREMUL and INV_PREMUL
#define PREMUL(x) qPremultiply(x)
#define INV_PREMUL(p) qUnpremultiply(p)
@@ -795,15 +825,6 @@ do { \
} \
} while (0)
-#if defined(Q_CC_RVCT)
-# pragma push
-# pragma arm
-#endif
-static Q_ALWAYS_INLINE int qt_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; }
-#if defined(Q_CC_RVCT)
-# pragma pop
-#endif
-
inline ushort qConvertRgb32To16(uint c)
{
return (((c) >> 3) & 0x001f)
@@ -819,6 +840,84 @@ inline QRgb qConvertRgb16To32(uint c)
| ((((c) << 8) & 0xf80000) | (((c) << 3) & 0x70000));
}
+enum QtPixelOrder {
+ PixelOrderRGB,
+ PixelOrderBGR
+};
+
+template<enum QtPixelOrder> inline uint qConvertArgb32ToA2rgb30(QRgb);
+
+template<enum QtPixelOrder> inline uint qConvertRgb32ToRgb30(QRgb);
+
+template<enum QtPixelOrder> inline QRgb qConvertA2rgb30ToArgb32(uint c);
+
+template<>
+inline uint qConvertArgb32ToA2rgb30<PixelOrderBGR>(QRgb c)
+{
+ return (c & 0xc0000000)
+ | (((c << 22) & 0x3fc00000) | ((c << 14) & 0x00300000))
+ | (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00))
+ | (((c >> 14) & 0x000003fc) | ((c >> 22) & 0x00000003));
+}
+
+template<>
+inline uint qConvertArgb32ToA2rgb30<PixelOrderRGB>(QRgb c)
+{
+ return (c & 0xc0000000)
+ | (((c << 6) & 0x3fc00000) | ((c >> 2) & 0x00300000))
+ | (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00))
+ | (((c << 2) & 0x000003fc) | ((c >> 6) & 0x00000003));
+}
+
+template<>
+inline uint qConvertRgb32ToRgb30<PixelOrderBGR>(QRgb c)
+{
+ return 0xc0000000
+ | (((c << 22) & 0x3fc00000) | ((c << 14) & 0x00300000))
+ | (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00))
+ | (((c >> 14) & 0x000003fc) | ((c >> 22) & 0x00000003));
+}
+
+template<>
+inline uint qConvertRgb32ToRgb30<PixelOrderRGB>(QRgb c)
+{
+ return 0xc0000000
+ | (((c << 6) & 0x3fc00000) | ((c >> 2) & 0x00300000))
+ | (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00))
+ | (((c << 2) & 0x000003fc) | ((c >> 6) & 0x00000003));
+}
+
+template<>
+inline QRgb qConvertA2rgb30ToArgb32<PixelOrderBGR>(uint c)
+{
+ uint a = c >> 30;
+ a |= a << 2;
+ a |= a << 4;
+ return (a << 24)
+ | ((c << 14) & 0x00ff0000)
+ | ((c >> 4) & 0x0000ff00)
+ | ((c >> 22) & 0x000000ff);
+}
+
+template<>
+inline QRgb qConvertA2rgb30ToArgb32<PixelOrderRGB>(uint c)
+{
+ uint a = c >> 30;
+ a |= a << 2;
+ a |= a << 4;
+ return (a << 24)
+ | ((c >> 6) & 0x00ff0000)
+ | ((c >> 4) & 0x0000ff00)
+ | ((c >> 2) & 0x000000ff);
+}
+
+inline uint qRgbSwapRgb30(uint c)
+{
+ const uint ag = c & 0xc00ffc00;
+ const uint rb = c & 0x3ff003ff;
+ return ag | (rb << 20) | (rb >> 20);
+}
+
inline int qRed565(quint16 rgb) {
const int r = (rgb & 0xf800);
return (r >> 8) | (r >> 13);
diff --git a/src/gui/painting/qmatrix.h b/src/gui/painting/qmatrix.h
index d2c1ae3a3c..93062899d3 100644
--- a/src/gui/painting/qmatrix.h
+++ b/src/gui/painting/qmatrix.h
@@ -100,7 +100,7 @@ public:
bool isInvertible() const { return !qFuzzyIsNull(_m11*_m22 - _m12*_m21); }
qreal determinant() const { return _m11*_m22 - _m12*_m21; }
- QMatrix inverted(bool *invertible = 0) const;
+ QMatrix inverted(bool *invertible = 0) const Q_REQUIRED_RESULT;
bool operator==(const QMatrix &) const;
bool operator!=(const QMatrix &) const;
diff --git a/src/gui/painting/qmemrotate.cpp b/src/gui/painting/qmemrotate.cpp
index 087231df43..e5eb7cf22d 100644
--- a/src/gui/painting/qmemrotate.cpp
+++ b/src/gui/painting/qmemrotate.cpp
@@ -532,7 +532,10 @@ MemRotateFunc qMemRotateFunctions[QImage::NImageFormats][3] =
{ 0, 0, 0 }, // Format_ARGB4444_Premultiplied,
{ qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // Format_RGBX8888,
{ qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // Format_RGBA8888,
- { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 } // Format_RGBA8888_Premultiplied,
+ { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // Format_RGBA8888_Premultiplied,
+ { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // Format_RGB30,
+ { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // Format_A2RGB30,
+ { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 } // Format_A2RGB30_Premultiplied,
};
QT_END_NAMESPACE
diff --git a/src/gui/painting/qpaintengine.h b/src/gui/painting/qpaintengine.h
index 7b928ba5f6..2a17a13517 100644
--- a/src/gui/painting/qpaintengine.h
+++ b/src/gui/painting/qpaintengine.h
@@ -250,7 +250,7 @@ private:
friend class QFontEngineWin;
friend class QMacPrintEngine;
friend class QMacPrintEnginePrivate;
- friend class QFontEngineQPA;
+ friend class QFontEngineQPF2;
friend class QPainter;
friend class QPainterPrivate;
friend class QWidget;
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index a004428fab..2e340219b9 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -423,6 +423,8 @@ void QRasterPaintEngine::init()
case QImage::Format_ARGB32:
case QImage::Format_RGBA8888_Premultiplied:
case QImage::Format_RGBA8888:
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_A2RGB30_Premultiplied:
gccaps |= PorterDuff;
break;
case QImage::Format_RGB32:
@@ -432,6 +434,8 @@ void QRasterPaintEngine::init()
case QImage::Format_RGB888:
case QImage::Format_RGB16:
case QImage::Format_RGBX8888:
+ case QImage::Format_BGR30:
+ case QImage::Format_RGB30:
break;
default:
break;
@@ -2243,6 +2247,8 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
case QImage::Format_ARGB8555_Premultiplied:
case QImage::Format_ARGB4444_Premultiplied:
case QImage::Format_RGBA8888_Premultiplied:
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_A2RGB30_Premultiplied:
// Combine premultiplied color with the opacity set on the painter.
d->solid_color_filler.solid.color =
((((color & 0x00ff00ff) * s->intOpacity) >> 8) & 0x00ff00ff)
diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h
index 4bfdbd91e0..c4703b3712 100644
--- a/src/gui/painting/qpaintengine_raster_p.h
+++ b/src/gui/painting/qpaintengine_raster_p.h
@@ -250,7 +250,7 @@ private:
QRect toNormalizedFillRect(const QRectF &rect);
inline void ensureBrush(const QBrush &brush) {
- if (!qbrush_fast_equals(state()->lastBrush, brush) || (brush.style() != Qt::NoBrush && state()->fillFlags))
+ if (!qbrush_fast_equals(state()->lastBrush, brush) || state()->fillFlags)
updateBrush(brush);
}
inline void ensureBrush() { ensureBrush(state()->brush); }
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 3f387d575b..7c691c9670 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -6422,6 +6422,7 @@ void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QText
continue;
+ multi->ensureEngineAt(which);
QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
ti2.width = 0;
// set the high byte to zero and calc the width
@@ -6449,6 +6450,7 @@ void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QText
which = e;
}
+ multi->ensureEngineAt(which);
QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
ti2.width = 0;
// set the high byte to zero and calc the width
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index aa2b9bea54..7a29bb87b4 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -1644,7 +1644,8 @@ QList<QPolygonF> QPainterPath::toFillPolygons(const QTransform &matrix) const
if (count == 0)
return polys;
- QList<QRectF> bounds;
+ QVector<QRectF> bounds;
+ bounds.reserve(count);
for (int i=0; i<count; ++i)
bounds += subpaths.at(i).boundingRect();
diff --git a/src/gui/painting/qpen.cpp b/src/gui/painting/qpen.cpp
index c0b3769c2d..b661057f64 100644
--- a/src/gui/painting/qpen.cpp
+++ b/src/gui/painting/qpen.cpp
@@ -327,17 +327,29 @@ QPen::QPen(const QBrush &brush, qreal width, Qt::PenStyle s, Qt::PenCapStyle c,
QPen::QPen(const QPen &p)
{
d = p.d;
- d->ref.ref();
+ if (d)
+ d->ref.ref();
}
/*!
+ \fn QPen::QPen(QPen &&pen)
+ \since 5.4
+
+ Constructs a pen that is moved from the given \a pen.
+
+ The moved-from pen can only be assigned to, copied, or
+ destroyed. Any other operation (prior to assignment) leads to
+ undefined behavior.
+*/
+
+/*!
Destroys the pen.
*/
QPen::~QPen()
{
- if (!d->ref.deref())
+ if (d && !d->ref.deref())
delete d;
}
@@ -373,7 +385,7 @@ void QPen::detach()
QPen &QPen::operator=(const QPen &p)
{
- qAtomicAssign(d, p.d);
+ QPen(p).swap(*this);
return *this;
}
diff --git a/src/gui/painting/qpen.h b/src/gui/painting/qpen.h
index c5144f784f..486f699476 100644
--- a/src/gui/painting/qpen.h
+++ b/src/gui/painting/qpen.h
@@ -72,6 +72,8 @@ public:
QPen &operator=(const QPen &pen);
#ifdef Q_COMPILER_RVALUE_REFS
+ inline QPen(QPen &&other)
+ : d(other.d) { other.d = 0; }
inline QPen &operator=(QPen &&other)
{ qSwap(d, other.d); return *this; }
#endif
diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp
index 5b6c4bb83d..3728b0bddd 100644
--- a/src/gui/painting/qplatformbackingstore.cpp
+++ b/src/gui/painting/qplatformbackingstore.cpp
@@ -321,8 +321,8 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu
#endif
funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageSize.width(), imageSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
const_cast<uchar*>(image.constBits()));
@@ -334,29 +334,32 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu
QRect rect = dirtyRegion.boundingRect() & imageRect;
#ifndef QT_OPENGL_ES_2
- funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, image.width());
- funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
- image.constScanLine(rect.y()) + rect.x() * 4);
- funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-#else
- // if the rect is wide enough it's cheaper to just
- // extend it instead of doing an image copy
- if (rect.width() >= imageRect.width() / 2) {
- rect.setX(0);
- rect.setWidth(imageRect.width());
- }
-
- // if the sub-rect is full-width we can pass the image data directly to
- // OpenGL instead of copying, since there's no gap between scanlines
-
- if (rect.width() == imageRect.width()) {
- funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
- image.constScanLine(rect.y()));
- } else {
+ if (!QOpenGLContext::currentContext()->isOpenGLES()) {
+ funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, image.width());
funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
- image.copy(rect).constBits());
- }
+ image.constScanLine(rect.y()) + rect.x() * 4);
+ funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ } else
#endif
+ {
+ // if the rect is wide enough it's cheaper to just
+ // extend it instead of doing an image copy
+ if (rect.width() >= imageRect.width() / 2) {
+ rect.setX(0);
+ rect.setWidth(imageRect.width());
+ }
+
+ // if the sub-rect is full-width we can pass the image data directly to
+ // OpenGL instead of copying, since there's no gap between scanlines
+
+ if (rect.width() == imageRect.width()) {
+ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
+ image.constScanLine(rect.y()));
+ } else {
+ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
+ image.copy(rect).constBits());
+ }
+ }
}
return d_ptr->textureId;
diff --git a/src/gui/painting/qpolygon.h b/src/gui/painting/qpolygon.h
index 1039e842ab..b696fe279a 100644
--- a/src/gui/painting/qpolygon.h
+++ b/src/gui/painting/qpolygon.h
@@ -71,8 +71,8 @@ public:
void translate(int dx, int dy);
void translate(const QPoint &offset);
- QPolygon translated(int dx, int dy) const;
- inline QPolygon translated(const QPoint &offset) const;
+ QPolygon translated(int dx, int dy) const Q_REQUIRED_RESULT;
+ inline QPolygon translated(const QPoint &offset) const Q_REQUIRED_RESULT;
QRect boundingRect() const;
@@ -88,9 +88,9 @@ public:
bool containsPoint(const QPoint &pt, Qt::FillRule fillRule) const;
- QPolygon united(const QPolygon &r) const;
- QPolygon intersected(const QPolygon &r) const;
- QPolygon subtracted(const QPolygon &r) const;
+ QPolygon united(const QPolygon &r) const Q_REQUIRED_RESULT;
+ QPolygon intersected(const QPolygon &r) const Q_REQUIRED_RESULT;
+ QPolygon subtracted(const QPolygon &r) const Q_REQUIRED_RESULT;
};
inline QPolygon::QPolygon(int asize) : QVector<QPoint>(asize) {}
diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h
index 0e436e3fb4..323a1858fa 100644
--- a/src/gui/painting/qregion.h
+++ b/src/gui/painting/qregion.h
@@ -86,23 +86,23 @@ public:
void translate(int dx, int dy);
inline void translate(const QPoint &p) { translate(p.x(), p.y()); }
- QRegion translated(int dx, int dy) const;
- inline QRegion translated(const QPoint &p) const { return translated(p.x(), p.y()); }
+ QRegion translated(int dx, int dy) const Q_REQUIRED_RESULT;
+ inline QRegion translated(const QPoint &p) const Q_REQUIRED_RESULT { return translated(p.x(), p.y()); }
- QRegion united(const QRegion &r) const;
- QRegion united(const QRect &r) const;
- QRegion intersected(const QRegion &r) const;
- QRegion intersected(const QRect &r) const;
- QRegion subtracted(const QRegion &r) const;
- QRegion xored(const QRegion &r) const;
+ QRegion united(const QRegion &r) const Q_REQUIRED_RESULT;
+ QRegion united(const QRect &r) const Q_REQUIRED_RESULT;
+ QRegion intersected(const QRegion &r) const Q_REQUIRED_RESULT;
+ QRegion intersected(const QRect &r) const Q_REQUIRED_RESULT;
+ QRegion subtracted(const QRegion &r) const Q_REQUIRED_RESULT;
+ QRegion xored(const QRegion &r) const Q_REQUIRED_RESULT;
#if QT_DEPRECATED_SINCE(5, 0)
- inline QT_DEPRECATED QRegion unite(const QRegion &r) const { return united(r); }
- inline QT_DEPRECATED QRegion unite(const QRect &r) const { return united(r); }
- inline QT_DEPRECATED QRegion intersect(const QRegion &r) const { return intersected(r); }
- inline QT_DEPRECATED QRegion intersect(const QRect &r) const { return intersected(r); }
- inline QT_DEPRECATED QRegion subtract(const QRegion &r) const { return subtracted(r); }
- inline QT_DEPRECATED QRegion eor(const QRegion &r) const { return xored(r); }
+ inline QT_DEPRECATED QRegion unite(const QRegion &r) const Q_REQUIRED_RESULT { return united(r); }
+ inline QT_DEPRECATED QRegion unite(const QRect &r) const Q_REQUIRED_RESULT { return united(r); }
+ inline QT_DEPRECATED QRegion intersect(const QRegion &r) const Q_REQUIRED_RESULT { return intersected(r); }
+ inline QT_DEPRECATED QRegion intersect(const QRect &r) const Q_REQUIRED_RESULT { return intersected(r); }
+ inline QT_DEPRECATED QRegion subtract(const QRegion &r) const Q_REQUIRED_RESULT { return subtracted(r); }
+ inline QT_DEPRECATED QRegion eor(const QRegion &r) const Q_REQUIRED_RESULT { return xored(r); }
#endif
bool intersects(const QRegion &r) const;
diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp
index 83edeb41a6..fb8c23835d 100644
--- a/src/gui/painting/qtextureglyphcache.cpp
+++ b/src/gui/painting/qtextureglyphcache.cpp
@@ -50,20 +50,6 @@ QT_BEGIN_NAMESPACE
// #define CACHE_DEBUG
-// returns the highest number closest to v, which is a power of 2
-// NB! assumes 32 bit ints
-static inline int qt_next_power_of_two(int v)
-{
- v--;
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
- ++v;
- return v;
-}
-
int QTextureGlyphCache::calculateSubPixelPositionCount(glyph_t glyph) const
{
// Test 12 different subpixel positions since it factors into 3*4 so it gives
@@ -199,7 +185,7 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
if (fontEngine->maxCharWidth() <= QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH)
m_w = QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH;
else
- m_w = qt_next_power_of_two(fontEngine->maxCharWidth());
+ m_w = qNextPowerOfTwo(qCeil(fontEngine->maxCharWidth()) - 1);
}
// now actually use the coords and paint the wanted glyps into cache.
@@ -261,9 +247,9 @@ void QTextureGlyphCache::fillInPendingGlyphs()
if (isNull() || requiredHeight > m_h || requiredWidth > m_w) {
if (isNull())
- createCache(qt_next_power_of_two(requiredWidth), qt_next_power_of_two(requiredHeight));
+ createCache(qNextPowerOfTwo(requiredWidth - 1), qNextPowerOfTwo(requiredHeight - 1));
else
- resizeCache(qt_next_power_of_two(requiredWidth), qt_next_power_of_two(requiredHeight));
+ resizeCache(qNextPowerOfTwo(requiredWidth - 1), qNextPowerOfTwo(requiredHeight - 1));
}
{
diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h
index 060362f63e..e6acbe0490 100644
--- a/src/gui/painting/qtransform.h
+++ b/src/gui/painting/qtransform.h
@@ -104,9 +104,9 @@ public:
qreal m21, qreal m22, qreal m23,
qreal m31, qreal m32, qreal m33);
- QTransform inverted(bool *invertible = 0) const;
- QTransform adjoint() const;
- QTransform transposed() const;
+ QTransform inverted(bool *invertible = 0) const Q_REQUIRED_RESULT;
+ QTransform adjoint() const Q_REQUIRED_RESULT;
+ QTransform transposed() const Q_REQUIRED_RESULT;
QTransform &translate(qreal dx, qreal dy);
QTransform &scale(qreal sx, qreal sy);
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index cf40dd028d..31fd9929f9 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -62,6 +62,8 @@
#include <limits.h>
#include <qpa/qplatformscreen.h>
+#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformfontdatabase.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtCore/QMutexLocker>
@@ -545,79 +547,6 @@ QFontEngineData::~QFontEngineData()
*/
/*!
- \fn QString QFont::rawName() const
- \deprecated
-
- Returns the name of the font within the underlying window system.
-
- On X11, this function will return an empty string.
-
- Using the return value of this function is usually \e not \e
- portable.
-
- \sa setRawName()
-*/
-
-/*!
- \fn void QFont::setRawName(const QString &name)
- \deprecated
-
- Sets a font by its system specific name.
-
- A font set with setRawName() is still a full-featured QFont. It can
- be queried (for example with italic()) or modified (for example with
- setItalic()) and is therefore also suitable for rendering rich text.
-
- If Qt's internal font database cannot resolve the raw name, the
- font becomes a raw font with \a name as its family.
-
- \sa rawName(), setRawMode(), setFamily()
-*/
-
-/*!
- \fn QString QFont::lastResortFamily() const
-
- Returns the "last resort" font family name.
-
- The current implementation tries a wide variety of common fonts,
- returning the first one it finds. Is is possible that no family is
- found in which case an empty string is returned.
-
- \sa lastResortFont()
-*/
-
-/*!
- \fn QString QFont::defaultFamily() const
-
- Returns the family name that corresponds to the current style
- hint.
-
- \sa StyleHint, styleHint(), setStyleHint()
-*/
-
-/*!
- \fn QString QFont::lastResortFont() const
-
- Returns a "last resort" font name for the font matching algorithm.
- This is used if the last resort family is not available. It will
- always return a name, if necessary returning something like
- "fixed" or "system".
-
- The current implementation tries a wide variety of common fonts,
- returning the first one it finds. The implementation may change
- at any time, but this function will always return a string
- containing something.
-
- It is theoretically possible that there really isn't a
- lastResortFont() in which case Qt will abort with an error
- message. We have not been able to identify a case where this
- happens. Please \l{bughowto.html}{report it as a bug} if
- it does, preferably with a list of the fonts you have installed.
-
- \sa lastResortFamily(), rawName()
-*/
-
-/*!
Constructs a font from \a font for use on the paint device \a pd.
*/
QFont::QFont(const QFont &font, QPaintDevice *pd)
@@ -1913,20 +1842,6 @@ void QFont::insertSubstitutions(const QString &familyName,
}
}
-/*! \fn void QFont::initialize()
- \internal
-
- Internal function that initializes the font system. The font cache
- and font dict do not alloc the keys. The key is a QString which is
- shared between QFontPrivate and QXFontName.
-*/
-
-/*! \fn void QFont::cleanup()
- \internal
-
- Internal function that cleans up the font system.
-*/
-
/*!
Removes all the substitutions for \a familyName.
@@ -2041,6 +1956,42 @@ static void set_extended_font_bits(quint8 bits, QFontPrivate *f)
}
#endif
+/*!
+ \fn QString QFont::rawName() const
+ \deprecated
+
+ Returns the name of the font within the underlying window system.
+
+ On X11, this function will return an empty string.
+
+ Using the return value of this function is usually \e not \e
+ portable.
+
+ \sa setRawName()
+*/
+QString QFont::rawName() const
+{
+ return QLatin1String("unknown");
+}
+
+/*!
+ \fn void QFont::setRawName(const QString &name)
+ \deprecated
+
+ Sets a font by its system specific name.
+
+ A font set with setRawName() is still a full-featured QFont. It can
+ be queried (for example with italic()) or modified (for example with
+ setItalic()) and is therefore also suitable for rendering rich text.
+
+ If Qt's internal font database cannot resolve the raw name, the
+ font becomes a raw font with \a name as its family.
+
+ \sa rawName(), setRawMode(), setFamily()
+*/
+void QFont::setRawName(const QString &)
+{
+}
/*!
Returns the font's key, a textual representation of a font. It is
@@ -2134,17 +2085,96 @@ bool QFont::fromString(const QString &descrip)
return true;
}
+/*! \fn void QFont::initialize()
+ \internal
+
+ Internal function that initializes the font system. The font cache
+ and font dict do not alloc the keys. The key is a QString which is
+ shared between QFontPrivate and QXFontName.
+*/
+void QFont::initialize()
+{
+}
+
+/*! \fn void QFont::cleanup()
+ \internal
+
+ Internal function that cleans up the font system.
+*/
+void QFont::cleanup()
+{
+ QFontCache::cleanup();
+}
+
/*! \internal
Internal function that dumps font cache statistics.
*/
void QFont::cacheStatistics()
{
+}
+
+/*!
+ \fn QString QFont::lastResortFamily() const
+
+ Returns the "last resort" font family name.
+
+ The current implementation tries a wide variety of common fonts,
+ returning the first one it finds. Is is possible that no family is
+ found in which case an empty string is returned.
+
+ \sa lastResortFont()
+*/
+QString QFont::lastResortFamily() const
+{
+ return QString::fromLatin1("helvetica");
+}
+/*!
+ \fn QString QFont::defaultFamily() const
+
+ Returns the family name that corresponds to the current style
+ hint.
+ \sa StyleHint, styleHint(), setStyleHint()
+*/
+QString QFont::defaultFamily() const
+{
+ QPlatformFontDatabase *fontDB = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
+ const QStringList fallbacks = fontDB->fallbacksForFamily(QString(), QFont::StyleNormal
+ , QFont::StyleHint(d->request.styleHint), QChar::Script_Common);
+ if (!fallbacks.isEmpty())
+ return fallbacks.first();
+ return QString();
}
+/*!
+ \fn QString QFont::lastResortFont() const
+ Returns a "last resort" font name for the font matching algorithm.
+ This is used if the last resort family is not available. It will
+ always return a name, if necessary returning something like
+ "fixed" or "system".
+
+ The current implementation tries a wide variety of common fonts,
+ returning the first one it finds. The implementation may change
+ at any time, but this function will always return a string
+ containing something.
+
+ It is theoretically possible that there really isn't a
+ lastResortFont() in which case Qt will abort with an error
+ message. We have not been able to identify a case where this
+ happens. Please \l{bughowto.html}{report it as a bug} if
+ it does, preferably with a list of the fonts you have installed.
+
+ \sa lastResortFamily(), rawName()
+*/
+QString QFont::lastResortFont() const
+{
+ qFatal("QFont::lastResortFont: Cannot find any reasonable font");
+ // Shut compiler up
+ return QString();
+}
/*****************************************************************************
QFont stream functions
@@ -2165,6 +2195,8 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
s << font.d->request.family.toLatin1();
} else {
s << font.d->request.family;
+ if (s.version() >= QDataStream::Qt_5_4)
+ s << font.d->request.styleName;
}
if (s.version() >= QDataStream::Qt_4_0) {
@@ -2185,8 +2217,14 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
}
s << (quint8) font.d->request.styleHint;
- if (s.version() >= QDataStream::Qt_3_1)
- s << (quint8) font.d->request.styleStrategy;
+ if (s.version() >= QDataStream::Qt_3_1) {
+ // Continue writing 8 bits for versions < 5.4 so that we don't write too much,
+ // even though we need 16 to store styleStrategy, so there is some data loss.
+ if (s.version() >= QDataStream::Qt_5_4)
+ s << (quint16) font.d->request.styleStrategy;
+ else
+ s << (quint8) font.d->request.styleStrategy;
+ }
s << (quint8) 0
<< (quint8) font.d->request.weight
<< get_font_bits(s.version(), font.d.data());
@@ -2198,6 +2236,8 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
s << font.d->letterSpacing.value();
s << font.d->wordSpacing.value();
}
+ if (s.version() >= QDataStream::Qt_5_4)
+ s << (quint8)font.d->request.hintingPreference;
return s;
}
@@ -2215,7 +2255,8 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
font.d = new QFontPrivate;
font.resolve_mask = QFont::AllPropertiesResolved;
- quint8 styleHint, styleStrategy = QFont::PreferDefault, charSet, weight, bits;
+ quint8 styleHint, charSet, weight, bits;
+ quint16 styleStrategy = QFont::PreferDefault;
if (s.version() == 1) {
QByteArray fam;
@@ -2223,6 +2264,8 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
font.d->request.family = QString::fromLatin1(fam);
} else {
s >> font.d->request.family;
+ if (s.version() >= QDataStream::Qt_5_4)
+ s >> font.d->request.styleName;
}
if (s.version() >= QDataStream::Qt_4_0) {
@@ -2242,8 +2285,15 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
font.d->request.pixelSize = pixelSize;
}
s >> styleHint;
- if (s.version() >= QDataStream::Qt_3_1)
- s >> styleStrategy;
+ if (s.version() >= QDataStream::Qt_3_1) {
+ if (s.version() >= QDataStream::Qt_5_4) {
+ s >> styleStrategy;
+ } else {
+ quint8 tempStyleStrategy;
+ s >> tempStyleStrategy;
+ styleStrategy = tempStyleStrategy;
+ }
+ }
s >> charSet;
s >> weight;
@@ -2273,6 +2323,11 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
s >> value;
font.d->wordSpacing.setValue(value);
}
+ if (s.version() >= QDataStream::Qt_5_4) {
+ quint8 value;
+ s >> value;
+ font.d->request.hintingPreference = QFont::HintingPreference(value);
+ }
return s;
}
diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h
index 4d8712e76e..be0402b95a 100644
--- a/src/gui/text/qfont_p.h
+++ b/src/gui/text/qfont_p.h
@@ -92,7 +92,7 @@ struct QFontDef
uint weight : 7; // 0-99
uint fixedPitch : 1;
uint style : 2;
- uint stretch : 12; // 0-400
+ uint stretch : 12; // 0-4000
uint hintingPreference : 2;
uint ignorePitch : 1;
diff --git a/src/gui/text/qfont_qpa.cpp b/src/gui/text/qfont_qpa.cpp
deleted file mode 100644
index be432dc52f..0000000000
--- a/src/gui/text/qfont_qpa.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtGui/private/qguiapplication_p.h>
-#include <qpa/qplatformintegration.h>
-#include <qpa/qplatformfontdatabase.h>
-
-QT_BEGIN_NAMESPACE
-
-void QFont::initialize()
-{
-}
-
-void QFont::cleanup()
-{
- QFontCache::cleanup();
-}
-
-
-/*****************************************************************************
- QFont member functions
- *****************************************************************************/
-
-QString QFont::rawName() const
-{
- return QLatin1String("unknown");
-}
-
-void QFont::setRawName(const QString &)
-{
-}
-
-QString QFont::defaultFamily() const
-{
- QPlatformFontDatabase *fontDB = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
- const QStringList fallbacks = fontDB->fallbacksForFamily(QString(), QFont::StyleNormal
- , QFont::StyleHint(d->request.styleHint), QChar::Script_Common);
- if (!fallbacks.isEmpty())
- return fallbacks.first();
- return QString();
-}
-
-QString QFont::lastResortFamily() const
-{
- return QString::fromLatin1("helvetica");
-}
-
-QString QFont::lastResortFont() const
-{
- qFatal("QFont::lastResortFont: Cannot find any reasonable font");
- // Shut compiler up
- return QString();
-}
-
-
-QT_END_NAMESPACE
-
diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h
index 833e574707..245d1cf81b 100644
--- a/src/gui/text/qfontdatabase.h
+++ b/src/gui/text/qfontdatabase.h
@@ -167,7 +167,7 @@ private:
friend class QFontPrivate;
friend class QFontDialog;
friend class QFontDialogPrivate;
- friend class QFontEngineMultiQPA;
+ friend class QFontEngineMultiBasicImpl;
QFontDatabasePrivate *d;
};
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 8adbb31a55..5f801c3bf4 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -42,6 +42,10 @@
#include <qdebug.h>
#include <private/qfontengine_p.h>
#include <private/qfontengineglyphcache_p.h>
+#include <private/qguiapplication_p.h>
+
+#include <qpa/qplatformfontdatabase.h>
+#include <qpa/qplatformintegration.h>
#include "qbitmap.h"
#include "qpainter.h"
@@ -2000,4 +2004,115 @@ QImage QFontEngineMulti::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPosit
return engine(which)->alphaRGBMapForGlyph(stripped(glyph), subPixelPosition, t);
}
+/*
+ Creates a new multi engine.
+
+ This function takes ownership of the QFontEngine, increasing it's refcount.
+*/
+QFontEngineMultiBasicImpl::QFontEngineMultiBasicImpl(QFontEngine *fe, int _script, const QStringList &fallbacks)
+ : QFontEngineMulti(fallbacks.size() + 1),
+ fallbackFamilies(fallbacks), script(_script)
+ , fallbacksQueried(true)
+{
+ init(fe);
+}
+
+QFontEngineMultiBasicImpl::QFontEngineMultiBasicImpl(QFontEngine *fe, int _script)
+ : QFontEngineMulti(2)
+ , script(_script)
+ , fallbacksQueried(false)
+{
+ fallbackFamilies << QString();
+ init(fe);
+}
+
+void QFontEngineMultiBasicImpl::init(QFontEngine *fe)
+{
+ Q_ASSERT(fe && fe->type() != QFontEngine::Multi);
+ engines[0] = fe;
+ fe->ref.ref();
+ fontDef = engines[0]->fontDef;
+ cache_cost = fe->cache_cost;
+}
+
+void QFontEngineMultiBasicImpl::loadEngine(int at)
+{
+ ensureFallbackFamiliesQueried();
+ Q_ASSERT(at < engines.size());
+ Q_ASSERT(engines.at(at) == 0);
+ QFontDef request = fontDef;
+ request.styleStrategy |= QFont::NoFontMerging;
+ request.family = fallbackFamilies.at(at-1);
+ engines[at] = QFontDatabase::findFont(script,
+ /*fontprivate = */0,
+ request, /*multi = */false, true);
+ Q_ASSERT(engines[at]);
+ engines[at]->ref.ref();
+ engines[at]->fontDef = request;
+}
+void QFontEngineMultiBasicImpl::ensureFallbackFamiliesQueried()
+{
+ if (fallbacksQueried)
+ return;
+ QStringList fallbacks = QGuiApplicationPrivate::instance()->platformIntegration()->fontDatabase()->fallbacksForFamily(engine(0)->fontDef.family, QFont::Style(engine(0)->fontDef.style)
+ , QFont::AnyStyle, QChar::Script(script));
+ setFallbackFamiliesList(fallbacks);
+}
+
+void QFontEngineMultiBasicImpl::setFallbackFamiliesList(const QStringList &fallbacks)
+{
+ // Original FontEngine to restore after the fill.
+ QFontEngine *fe = engines[0];
+ fallbackFamilies = fallbacks;
+ if (!fallbackFamilies.isEmpty()) {
+ engines.fill(0, fallbackFamilies.size() + 1);
+ engines[0] = fe;
+ } else {
+ // Turns out we lied about having any fallback at all.
+ fallbackFamilies << fe->fontDef.family;
+ engines[1] = fe;
+ fe->ref.ref();
+ }
+ fallbacksQueried = true;
+}
+
+/*
+ This is used indirectly by Qt WebKit when using QTextLayout::setRawFont
+
+ The purpose of this is to provide the necessary font fallbacks when drawing complex
+ text. Since Qt WebKit ends up repeatedly creating QTextLayout instances and passing them
+ the same raw font over and over again, we want to cache the corresponding multi font engine
+ as it may contain fallback font engines already.
+*/
+QFontEngine* QFontEngineMultiBasicImpl::createMultiFontEngine(QFontEngine *fe, int script)
+{
+ QFontEngine *engine = 0;
+ QFontCache::Key key(fe->fontDef, script, /*multi = */true);
+ QFontCache *fc = QFontCache::instance();
+ // We can't rely on the fontDef (and hence the cache Key)
+ // alone to distinguish webfonts, since these should not be
+ // accidentally shared, even if the resulting fontcache key
+ // is strictly identical. See:
+ // http://www.w3.org/TR/css3-fonts/#font-face-rule
+ const bool faceIsLocal = !fe->faceId().filename.isEmpty();
+ QFontCache::EngineCache::Iterator it = fc->engineCache.find(key),
+ end = fc->engineCache.end();
+ while (it != end && it.key() == key) {
+ Q_ASSERT(it.value().data->type() == QFontEngine::Multi);
+ QFontEngineMulti *cachedEngine = static_cast<QFontEngineMulti *>(it.value().data);
+ if (fe == cachedEngine->engine(0) || (faceIsLocal && fe->faceId().filename == cachedEngine->engine(0)->faceId().filename)) {
+ engine = cachedEngine;
+ fc->updateHitCountAndTimeStamp(it.value());
+ break;
+ }
+ it++;
+ }
+ if (!engine) {
+ engine = QGuiApplicationPrivate::instance()->platformIntegration()->fontDatabase()->fontEngineMulti(fe, QChar::Script(script));
+ QFontCache::instance()->insertEngine(key, engine, /* insertMulti */ !faceIsLocal);
+ }
+ Q_ASSERT(engine);
+ return engine;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index fc849d788f..5040424c6f 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -433,6 +433,29 @@ protected:
QVector<QFontEngine *> engines;
};
+class Q_GUI_EXPORT QFontEngineMultiBasicImpl : public QFontEngineMulti
+{
+public:
+ QFontEngineMultiBasicImpl(QFontEngine *fe, int script, const QStringList &fallbacks);
+ QFontEngineMultiBasicImpl(QFontEngine *fe, int script);
+
+ void loadEngine(int at);
+ static QFontEngine* createMultiFontEngine(QFontEngine *fe, int script);
+
+ int fallbackFamilyCount() const { return fallbackFamilies.size(); }
+ QString fallbackFamilyAt(int at) const { return fallbackFamilies.at(at); }
+
+ virtual void ensureFallbackFamiliesQueried();
+ virtual void setFallbackFamiliesList(const QStringList &fallbacks);
+
+private:
+ void init(QFontEngine *fe);
+
+ mutable QStringList fallbackFamilies;
+ int script;
+ mutable bool fallbacksQueried;
+};
+
class QTestFontEngine : public QFontEngineBox
{
public:
diff --git a/src/gui/text/qfontengine_qpa.cpp b/src/gui/text/qfontengine_qpf2.cpp
index a115d2a901..bcb128baac 100644
--- a/src/gui/text/qfontengine_qpa.cpp
+++ b/src/gui/text/qfontengine_qpf2.cpp
@@ -39,7 +39,7 @@
**
****************************************************************************/
-#include "qfontengine_qpa_p.h"
+#include "qfontengine_qpf2_p.h"
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
@@ -57,28 +57,28 @@ QT_BEGIN_NAMESPACE
//#define DEBUG_HEADER
//#define DEBUG_FONTENGINE
-static QFontEngineQPA::TagType tagTypes[QFontEngineQPA::NumTags] = {
- QFontEngineQPA::StringType, // FontName
- QFontEngineQPA::StringType, // FileName
- QFontEngineQPA::UInt32Type, // FileIndex
- QFontEngineQPA::UInt32Type, // FontRevision
- QFontEngineQPA::StringType, // FreeText
- QFontEngineQPA::FixedType, // Ascent
- QFontEngineQPA::FixedType, // Descent
- QFontEngineQPA::FixedType, // Leading
- QFontEngineQPA::FixedType, // XHeight
- QFontEngineQPA::FixedType, // AverageCharWidth
- QFontEngineQPA::FixedType, // MaxCharWidth
- QFontEngineQPA::FixedType, // LineThickness
- QFontEngineQPA::FixedType, // MinLeftBearing
- QFontEngineQPA::FixedType, // MinRightBearing
- QFontEngineQPA::FixedType, // UnderlinePosition
- QFontEngineQPA::UInt8Type, // GlyphFormat
- QFontEngineQPA::UInt8Type, // PixelSize
- QFontEngineQPA::UInt8Type, // Weight
- QFontEngineQPA::UInt8Type, // Style
- QFontEngineQPA::StringType, // EndOfHeader
- QFontEngineQPA::BitFieldType// WritingSystems
+static QFontEngineQPF2::TagType tagTypes[QFontEngineQPF2::NumTags] = {
+ QFontEngineQPF2::StringType, // FontName
+ QFontEngineQPF2::StringType, // FileName
+ QFontEngineQPF2::UInt32Type, // FileIndex
+ QFontEngineQPF2::UInt32Type, // FontRevision
+ QFontEngineQPF2::StringType, // FreeText
+ QFontEngineQPF2::FixedType, // Ascent
+ QFontEngineQPF2::FixedType, // Descent
+ QFontEngineQPF2::FixedType, // Leading
+ QFontEngineQPF2::FixedType, // XHeight
+ QFontEngineQPF2::FixedType, // AverageCharWidth
+ QFontEngineQPF2::FixedType, // MaxCharWidth
+ QFontEngineQPF2::FixedType, // LineThickness
+ QFontEngineQPF2::FixedType, // MinLeftBearing
+ QFontEngineQPF2::FixedType, // MinRightBearing
+ QFontEngineQPF2::FixedType, // UnderlinePosition
+ QFontEngineQPF2::UInt8Type, // GlyphFormat
+ QFontEngineQPF2::UInt8Type, // PixelSize
+ QFontEngineQPF2::UInt8Type, // Weight
+ QFontEngineQPF2::UInt8Type, // Style
+ QFontEngineQPF2::StringType, // EndOfHeader
+ QFontEngineQPF2::BitFieldType// WritingSystems
};
@@ -122,21 +122,21 @@ static inline const uchar *verifyTag(const uchar *tagPtr, const uchar *endPtr)
quint16 tag, length;
READ_VERIFY(quint16, tag);
READ_VERIFY(quint16, length);
- if (tag == QFontEngineQPA::Tag_EndOfHeader)
+ if (tag == QFontEngineQPF2::Tag_EndOfHeader)
return endPtr;
- if (tag < QFontEngineQPA::NumTags) {
+ if (tag < QFontEngineQPF2::NumTags) {
switch (tagTypes[tag]) {
- case QFontEngineQPA::BitFieldType:
- case QFontEngineQPA::StringType:
+ case QFontEngineQPF2::BitFieldType:
+ case QFontEngineQPF2::StringType:
// can't do anything...
break;
- case QFontEngineQPA::UInt32Type:
+ case QFontEngineQPF2::UInt32Type:
VERIFY_TAG(length == sizeof(quint32));
break;
- case QFontEngineQPA::FixedType:
+ case QFontEngineQPF2::FixedType:
VERIFY_TAG(length == sizeof(quint32));
break;
- case QFontEngineQPA::UInt8Type:
+ case QFontEngineQPF2::UInt8Type:
VERIFY_TAG(length == sizeof(quint8));
break;
}
@@ -150,7 +150,7 @@ static inline const uchar *verifyTag(const uchar *tagPtr, const uchar *endPtr)
return tagPtr + length;
}
-const QFontEngineQPA::Glyph *QFontEngineQPA::findGlyph(glyph_t g) const
+const QFontEngineQPF2::Glyph *QFontEngineQPF2::findGlyph(glyph_t g) const
{
if (!g || g >= glyphMapEntries)
return 0;
@@ -168,7 +168,7 @@ const QFontEngineQPA::Glyph *QFontEngineQPA::findGlyph(glyph_t g) const
return reinterpret_cast<const Glyph *>(fontData + glyphDataOffset + glyphPos);
}
-bool QFontEngineQPA::verifyHeader(const uchar *data, int size)
+bool QFontEngineQPF2::verifyHeader(const uchar *data, int size)
{
VERIFY(quintptr(data) % Q_ALIGNOF(Header) == 0);
VERIFY(size >= int(sizeof(Header)));
@@ -194,7 +194,7 @@ bool QFontEngineQPA::verifyHeader(const uchar *data, int size)
return true;
}
-QVariant QFontEngineQPA::extractHeaderField(const uchar *data, HeaderTag requestedTag)
+QVariant QFontEngineQPF2::extractHeaderField(const uchar *data, HeaderTag requestedTag)
{
const Header *header = reinterpret_cast<const Header *>(data);
const uchar *tagPtr = data + sizeof(Header);
@@ -226,7 +226,7 @@ QVariant QFontEngineQPA::extractHeaderField(const uchar *data, HeaderTag request
}
-QFontEngineQPA::QFontEngineQPA(const QFontDef &def, const QByteArray &data)
+QFontEngineQPF2::QFontEngineQPF2(const QFontDef &def, const QByteArray &data)
: QFontEngine(QPF2),
fontData(reinterpret_cast<const uchar *>(data.constData())), dataSize(data.size())
{
@@ -243,7 +243,7 @@ QFontEngineQPA::QFontEngineQPA(const QFontDef &def, const QByteArray &data)
readOnly = true;
#if defined(DEBUG_FONTENGINE)
- qDebug() << "QFontEngineQPA::QFontEngineQPA( fd =" << fd << ", renderingFontEngine =" << renderingFontEngine << ')';
+ qDebug() << "QFontEngineQPF2::QFontEngineQPF2( fd =" << fd << ", renderingFontEngine =" << renderingFontEngine << ')';
#endif
if (!verifyHeader(fontData, dataSize)) {
@@ -312,11 +312,11 @@ QFontEngineQPA::QFontEngineQPA(const QFontDef &def, const QByteArray &data)
#endif
}
-QFontEngineQPA::~QFontEngineQPA()
+QFontEngineQPF2::~QFontEngineQPF2()
{
}
-bool QFontEngineQPA::getSfntTableData(uint tag, uchar *buffer, uint *length) const
+bool QFontEngineQPF2::getSfntTableData(uint tag, uchar *buffer, uint *length) const
{
if (tag != MAKE_TAG('c', 'm', 'a', 'p') || !cmap)
return false;
@@ -328,7 +328,7 @@ bool QFontEngineQPA::getSfntTableData(uint tag, uchar *buffer, uint *length) con
return true;
}
-glyph_t QFontEngineQPA::glyphIndex(uint ucs4) const
+glyph_t QFontEngineQPF2::glyphIndex(uint ucs4) const
{
glyph_t glyph = getTrueTypeGlyphIndex(cmap, ucs4);
if (glyph == 0 && symbol && ucs4 < 0x100)
@@ -339,7 +339,7 @@ glyph_t QFontEngineQPA::glyphIndex(uint ucs4) const
return glyph;
}
-bool QFontEngineQPA::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QFontEngine::ShaperFlags flags) const
+bool QFontEngineQPF2::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QFontEngine::ShaperFlags flags) const
{
Q_ASSERT(glyphs->numGlyphs >= *nglyphs);
if (*nglyphs < len) {
@@ -386,7 +386,7 @@ bool QFontEngineQPA::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph
return true;
}
-void QFontEngineQPA::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags) const
+void QFontEngineQPF2::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags) const
{
for (int i = 0; i < glyphs->numGlyphs; ++i) {
const Glyph *g = findGlyph(glyphs->glyphs[i]);
@@ -396,7 +396,7 @@ void QFontEngineQPA::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFla
}
}
-QImage QFontEngineQPA::alphaMapForGlyph(glyph_t g)
+QImage QFontEngineQPF2::alphaMapForGlyph(glyph_t g)
{
const Glyph *glyph = findGlyph(g);
if (!glyph)
@@ -409,12 +409,12 @@ QImage QFontEngineQPA::alphaMapForGlyph(glyph_t g)
return image;
}
-void QFontEngineQPA::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)
+void QFontEngineQPF2::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)
{
addBitmapFontToPath(x, y, glyphs, path, flags);
}
-glyph_metrics_t QFontEngineQPA::boundingBox(const QGlyphLayout &glyphs)
+glyph_metrics_t QFontEngineQPF2::boundingBox(const QGlyphLayout &glyphs)
{
glyph_metrics_t overall;
// initialize with line height, we get the same behaviour on all platforms
@@ -442,7 +442,7 @@ glyph_metrics_t QFontEngineQPA::boundingBox(const QGlyphLayout &glyphs)
return overall;
}
-glyph_metrics_t QFontEngineQPA::boundingBox(glyph_t glyph)
+glyph_metrics_t QFontEngineQPF2::boundingBox(glyph_t glyph)
{
glyph_metrics_t overall;
const Glyph *g = findGlyph(glyph);
@@ -456,107 +456,107 @@ glyph_metrics_t QFontEngineQPA::boundingBox(glyph_t glyph)
return overall;
}
-QFixed QFontEngineQPA::ascent() const
+QFixed QFontEngineQPF2::ascent() const
{
return QFixed::fromReal(extractHeaderField(fontData, Tag_Ascent).value<qreal>());
}
-QFixed QFontEngineQPA::descent() const
+QFixed QFontEngineQPF2::descent() const
{
return QFixed::fromReal(extractHeaderField(fontData, Tag_Descent).value<qreal>());
}
-QFixed QFontEngineQPA::leading() const
+QFixed QFontEngineQPF2::leading() const
{
return QFixed::fromReal(extractHeaderField(fontData, Tag_Leading).value<qreal>());
}
-qreal QFontEngineQPA::maxCharWidth() const
+qreal QFontEngineQPF2::maxCharWidth() const
{
return extractHeaderField(fontData, Tag_MaxCharWidth).value<qreal>();
}
-qreal QFontEngineQPA::minLeftBearing() const
+qreal QFontEngineQPF2::minLeftBearing() const
{
return extractHeaderField(fontData, Tag_MinLeftBearing).value<qreal>();
}
-qreal QFontEngineQPA::minRightBearing() const
+qreal QFontEngineQPF2::minRightBearing() const
{
return extractHeaderField(fontData, Tag_MinRightBearing).value<qreal>();
}
-QFixed QFontEngineQPA::underlinePosition() const
+QFixed QFontEngineQPF2::underlinePosition() const
{
return QFixed::fromReal(extractHeaderField(fontData, Tag_UnderlinePosition).value<qreal>());
}
-QFixed QFontEngineQPA::lineThickness() const
+QFixed QFontEngineQPF2::lineThickness() const
{
return QFixed::fromReal(extractHeaderField(fontData, Tag_LineThickness).value<qreal>());
}
-bool QFontEngineQPA::isValid() const
+bool QFontEngineQPF2::isValid() const
{
return fontData && dataSize && cmapOffset
&& glyphMapOffset && glyphDataOffset && glyphDataSize > 0;
}
-void QPAGenerator::generate()
+void QPF2Generator::generate()
{
writeHeader();
writeGMap();
- writeBlock(QFontEngineQPA::GlyphBlock, QByteArray());
+ writeBlock(QFontEngineQPF2::GlyphBlock, QByteArray());
dev->seek(4); // position of header.lock
writeUInt32(0);
}
-void QPAGenerator::writeHeader()
+void QPF2Generator::writeHeader()
{
- QFontEngineQPA::Header header;
+ QFontEngineQPF2::Header header;
header.magic[0] = 'Q';
header.magic[1] = 'P';
header.magic[2] = 'F';
header.magic[3] = '2';
header.lock = 1;
- header.majorVersion = QFontEngineQPA::CurrentMajorVersion;
- header.minorVersion = QFontEngineQPA::CurrentMinorVersion;
+ header.majorVersion = QFontEngineQPF2::CurrentMajorVersion;
+ header.minorVersion = QFontEngineQPF2::CurrentMinorVersion;
header.dataSize = 0;
dev->write((const char *)&header, sizeof(header));
- writeTaggedString(QFontEngineQPA::Tag_FontName, fe->fontDef.family.toUtf8());
+ writeTaggedString(QFontEngineQPF2::Tag_FontName, fe->fontDef.family.toUtf8());
QFontEngine::FaceId face = fe->faceId();
- writeTaggedString(QFontEngineQPA::Tag_FileName, face.filename);
- writeTaggedUInt32(QFontEngineQPA::Tag_FileIndex, face.index);
+ writeTaggedString(QFontEngineQPF2::Tag_FileName, face.filename);
+ writeTaggedUInt32(QFontEngineQPF2::Tag_FileIndex, face.index);
{
const QByteArray head = fe->getSfntTable(MAKE_TAG('h', 'e', 'a', 'd'));
if (head.size() >= 4) {
const quint32 revision = qFromBigEndian<quint32>(reinterpret_cast<const uchar *>(head.constData()));
- writeTaggedUInt32(QFontEngineQPA::Tag_FontRevision, revision);
+ writeTaggedUInt32(QFontEngineQPF2::Tag_FontRevision, revision);
}
}
- writeTaggedQFixed(QFontEngineQPA::Tag_Ascent, fe->ascent());
- writeTaggedQFixed(QFontEngineQPA::Tag_Descent, fe->descent());
- writeTaggedQFixed(QFontEngineQPA::Tag_Leading, fe->leading());
- writeTaggedQFixed(QFontEngineQPA::Tag_XHeight, fe->xHeight());
- writeTaggedQFixed(QFontEngineQPA::Tag_AverageCharWidth, fe->averageCharWidth());
- writeTaggedQFixed(QFontEngineQPA::Tag_MaxCharWidth, QFixed::fromReal(fe->maxCharWidth()));
- writeTaggedQFixed(QFontEngineQPA::Tag_LineThickness, fe->lineThickness());
- writeTaggedQFixed(QFontEngineQPA::Tag_MinLeftBearing, QFixed::fromReal(fe->minLeftBearing()));
- writeTaggedQFixed(QFontEngineQPA::Tag_MinRightBearing, QFixed::fromReal(fe->minRightBearing()));
- writeTaggedQFixed(QFontEngineQPA::Tag_UnderlinePosition, fe->underlinePosition());
- writeTaggedUInt8(QFontEngineQPA::Tag_PixelSize, fe->fontDef.pixelSize);
- writeTaggedUInt8(QFontEngineQPA::Tag_Weight, fe->fontDef.weight);
- writeTaggedUInt8(QFontEngineQPA::Tag_Style, fe->fontDef.style);
-
- writeTaggedUInt8(QFontEngineQPA::Tag_GlyphFormat, QFontEngineQPA::AlphamapGlyphs);
-
- writeTaggedString(QFontEngineQPA::Tag_EndOfHeader, QByteArray());
+ writeTaggedQFixed(QFontEngineQPF2::Tag_Ascent, fe->ascent());
+ writeTaggedQFixed(QFontEngineQPF2::Tag_Descent, fe->descent());
+ writeTaggedQFixed(QFontEngineQPF2::Tag_Leading, fe->leading());
+ writeTaggedQFixed(QFontEngineQPF2::Tag_XHeight, fe->xHeight());
+ writeTaggedQFixed(QFontEngineQPF2::Tag_AverageCharWidth, fe->averageCharWidth());
+ writeTaggedQFixed(QFontEngineQPF2::Tag_MaxCharWidth, QFixed::fromReal(fe->maxCharWidth()));
+ writeTaggedQFixed(QFontEngineQPF2::Tag_LineThickness, fe->lineThickness());
+ writeTaggedQFixed(QFontEngineQPF2::Tag_MinLeftBearing, QFixed::fromReal(fe->minLeftBearing()));
+ writeTaggedQFixed(QFontEngineQPF2::Tag_MinRightBearing, QFixed::fromReal(fe->minRightBearing()));
+ writeTaggedQFixed(QFontEngineQPF2::Tag_UnderlinePosition, fe->underlinePosition());
+ writeTaggedUInt8(QFontEngineQPF2::Tag_PixelSize, fe->fontDef.pixelSize);
+ writeTaggedUInt8(QFontEngineQPF2::Tag_Weight, fe->fontDef.weight);
+ writeTaggedUInt8(QFontEngineQPF2::Tag_Style, fe->fontDef.style);
+
+ writeTaggedUInt8(QFontEngineQPF2::Tag_GlyphFormat, QFontEngineQPF2::AlphamapGlyphs);
+
+ writeTaggedString(QFontEngineQPF2::Tag_EndOfHeader, QByteArray());
align4();
const quint64 size = dev->pos();
@@ -566,11 +566,11 @@ void QPAGenerator::writeHeader()
dev->seek(size);
}
-void QPAGenerator::writeGMap()
+void QPF2Generator::writeGMap()
{
const quint16 glyphCount = fe->glyphCount();
- writeUInt16(QFontEngineQPA::GMapBlock);
+ writeUInt16(QFontEngineQPF2::GMapBlock);
writeUInt16(0); // padding
writeUInt32(glyphCount * 4);
@@ -582,7 +582,7 @@ void QPAGenerator::writeGMap()
dev->seek(pos + numBytes);
}
-void QPAGenerator::writeBlock(QFontEngineQPA::BlockTag tag, const QByteArray &data)
+void QPF2Generator::writeBlock(QFontEngineQPF2::BlockTag tag, const QByteArray &data)
{
writeUInt16(tag);
writeUInt16(0); // padding
@@ -593,144 +593,32 @@ void QPAGenerator::writeBlock(QFontEngineQPA::BlockTag tag, const QByteArray &da
writeUInt8(0);
}
-void QPAGenerator::writeTaggedString(QFontEngineQPA::HeaderTag tag, const QByteArray &string)
+void QPF2Generator::writeTaggedString(QFontEngineQPF2::HeaderTag tag, const QByteArray &string)
{
writeUInt16(tag);
writeUInt16(string.length());
dev->write(string);
}
-void QPAGenerator::writeTaggedUInt32(QFontEngineQPA::HeaderTag tag, quint32 value)
+void QPF2Generator::writeTaggedUInt32(QFontEngineQPF2::HeaderTag tag, quint32 value)
{
writeUInt16(tag);
writeUInt16(sizeof(value));
writeUInt32(value);
}
-void QPAGenerator::writeTaggedUInt8(QFontEngineQPA::HeaderTag tag, quint8 value)
+void QPF2Generator::writeTaggedUInt8(QFontEngineQPF2::HeaderTag tag, quint8 value)
{
writeUInt16(tag);
writeUInt16(sizeof(value));
writeUInt8(value);
}
-void QPAGenerator::writeTaggedQFixed(QFontEngineQPA::HeaderTag tag, QFixed value)
+void QPF2Generator::writeTaggedQFixed(QFontEngineQPF2::HeaderTag tag, QFixed value)
{
writeUInt16(tag);
writeUInt16(sizeof(quint32));
writeUInt32(value.value());
}
-
-/*
- Creates a new multi QPA engine.
-
- This function takes ownership of the QFontEngine, increasing it's refcount.
-*/
-QFontEngineMultiQPA::QFontEngineMultiQPA(QFontEngine *fe, int _script, const QStringList &fallbacks)
- : QFontEngineMulti(fallbacks.size() + 1),
- fallbackFamilies(fallbacks), script(_script)
- , fallbacksQueried(true)
-{
- init(fe);
-}
-
-QFontEngineMultiQPA::QFontEngineMultiQPA(QFontEngine *fe, int _script)
- : QFontEngineMulti(2)
- , script(_script)
- , fallbacksQueried(false)
-{
- fallbackFamilies << QString();
- init(fe);
-}
-
-void QFontEngineMultiQPA::init(QFontEngine *fe)
-{
- Q_ASSERT(fe && fe->type() != QFontEngine::Multi);
- engines[0] = fe;
- fe->ref.ref();
- fontDef = engines[0]->fontDef;
- cache_cost = fe->cache_cost;
-}
-
-void QFontEngineMultiQPA::loadEngine(int at)
-{
- ensureFallbackFamiliesQueried();
- Q_ASSERT(at < engines.size());
- Q_ASSERT(engines.at(at) == 0);
- QFontDef request = fontDef;
- request.styleStrategy |= QFont::NoFontMerging;
- request.family = fallbackFamilies.at(at-1);
- engines[at] = QFontDatabase::findFont(script,
- /*fontprivate = */0,
- request, /*multi = */false, true);
- Q_ASSERT(engines[at]);
- engines[at]->ref.ref();
- engines[at]->fontDef = request;
-}
-void QFontEngineMultiQPA::ensureFallbackFamiliesQueried()
-{
- if (fallbacksQueried)
- return;
- QStringList fallbacks = QGuiApplicationPrivate::instance()->platformIntegration()->fontDatabase()->fallbacksForFamily(engine(0)->fontDef.family, QFont::Style(engine(0)->fontDef.style)
- , QFont::AnyStyle, QChar::Script(script));
- setFallbackFamiliesList(fallbacks);
-}
-
-void QFontEngineMultiQPA::setFallbackFamiliesList(const QStringList &fallbacks)
-{
- // Original FontEngine to restore after the fill.
- QFontEngine *fe = engines[0];
- fallbackFamilies = fallbacks;
- if (!fallbackFamilies.isEmpty()) {
- engines.fill(0, fallbackFamilies.size() + 1);
- engines[0] = fe;
- } else {
- // Turns out we lied about having any fallback at all.
- fallbackFamilies << fe->fontDef.family;
- engines[1] = fe;
- fe->ref.ref();
- }
- fallbacksQueried = true;
-}
-
-/*
- This is used indirectly by Qt WebKit when using QTextLayout::setRawFont
-
- The purpose of this is to provide the necessary font fallbacks when drawing complex
- text. Since Qt WebKit ends up repeatedly creating QTextLayout instances and passing them
- the same raw font over and over again, we want to cache the corresponding multi font engine
- as it may contain fallback font engines already.
-*/
-QFontEngine* QFontEngineMultiQPA::createMultiFontEngine(QFontEngine *fe, int script)
-{
- QFontEngine *engine = 0;
- QFontCache::Key key(fe->fontDef, script, /*multi = */true);
- QFontCache *fc = QFontCache::instance();
- // We can't rely on the fontDef (and hence the cache Key)
- // alone to distinguish webfonts, since these should not be
- // accidentally shared, even if the resulting fontcache key
- // is strictly identical. See:
- // http://www.w3.org/TR/css3-fonts/#font-face-rule
- const bool faceIsLocal = !fe->faceId().filename.isEmpty();
- QFontCache::EngineCache::Iterator it = fc->engineCache.find(key),
- end = fc->engineCache.end();
- while (it != end && it.key() == key) {
- Q_ASSERT(it.value().data->type() == QFontEngine::Multi);
- QFontEngineMulti *cachedEngine = static_cast<QFontEngineMulti *>(it.value().data);
- if (faceIsLocal || fe == cachedEngine->engine(0)) {
- engine = cachedEngine;
- fc->updateHitCountAndTimeStamp(it.value());
- break;
- }
- it++;
- }
- if (!engine) {
- engine = QGuiApplicationPrivate::instance()->platformIntegration()->fontDatabase()->fontEngineMulti(fe, QChar::Script(script));
- QFontCache::instance()->insertEngine(key, engine, /* insertMulti */ !faceIsLocal);
- }
- Q_ASSERT(engine);
- return engine;
-}
-
QT_END_NAMESPACE
diff --git a/src/gui/text/qfontengine_qpa_p.h b/src/gui/text/qfontengine_qpf2_p.h
index e84b067c68..a616cc3300 100644
--- a/src/gui/text/qfontengine_qpa_p.h
+++ b/src/gui/text/qfontengine_qpf2_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QFONTENGINE_QPA_P_H
-#define QFONTENGINE_QPA_P_H
+#ifndef QFONTENGINE_QPF2_P_H
+#define QFONTENGINE_QPF2_P_H
//
// W A R N I N G
@@ -67,7 +67,7 @@ class QFontEngine;
class QFreetypeFace;
class QBuffer;
-class Q_GUI_EXPORT QFontEngineQPA : public QFontEngine
+class Q_GUI_EXPORT QFontEngineQPF2 : public QFontEngine
{
public:
// if you add new tags please make sure to update the tables in
@@ -157,8 +157,8 @@ public:
qint8 advance;
};
- QFontEngineQPA(const QFontDef &def, const QByteArray &data);
- ~QFontEngineQPA();
+ QFontEngineQPF2(const QFontDef &def, const QByteArray &data);
+ ~QFontEngineQPF2();
FaceId faceId() const { return face_id; }
bool getSfntTableData(uint tag, uchar *buffer, uint *length) const;
@@ -211,20 +211,20 @@ private:
mutable bool kerning_pairs_loaded;
};
-struct QPAGenerator
+struct QPF2Generator
{
- QPAGenerator(QBuffer *device, QFontEngine *engine)
+ QPF2Generator(QBuffer *device, QFontEngine *engine)
: dev(device), fe(engine) {}
void generate();
void writeHeader();
void writeGMap();
- void writeBlock(QFontEngineQPA::BlockTag tag, const QByteArray &data);
+ void writeBlock(QFontEngineQPF2::BlockTag tag, const QByteArray &data);
- void writeTaggedString(QFontEngineQPA::HeaderTag tag, const QByteArray &string);
- void writeTaggedUInt32(QFontEngineQPA::HeaderTag tag, quint32 value);
- void writeTaggedUInt8(QFontEngineQPA::HeaderTag tag, quint8 value);
- void writeTaggedQFixed(QFontEngineQPA::HeaderTag tag, QFixed value);
+ void writeTaggedString(QFontEngineQPF2::HeaderTag tag, const QByteArray &string);
+ void writeTaggedUInt32(QFontEngineQPF2::HeaderTag tag, quint32 value);
+ void writeTaggedUInt8(QFontEngineQPF2::HeaderTag tag, quint8 value);
+ void writeTaggedQFixed(QFontEngineQPF2::HeaderTag tag, QFixed value);
void writeUInt16(quint16 value) { value = qToBigEndian(value); dev->write((const char *)&value, sizeof(value)); }
void writeUInt32(quint32 value) { value = qToBigEndian(value); dev->write((const char *)&value, sizeof(value)); }
@@ -237,29 +237,6 @@ struct QPAGenerator
QFontEngine *fe;
};
-class Q_GUI_EXPORT QFontEngineMultiQPA : public QFontEngineMulti
-{
-public:
- QFontEngineMultiQPA(QFontEngine *fe, int script, const QStringList &fallbacks);
- QFontEngineMultiQPA(QFontEngine *fe, int script);
-
- void loadEngine(int at);
- static QFontEngine* createMultiFontEngine(QFontEngine *fe, int script);
-
- int fallbackFamilyCount() const { return fallbackFamilies.size(); }
- QString fallbackFamilyAt(int at) const { return fallbackFamilies.at(at); }
-
- virtual void ensureFallbackFamiliesQueried();
- virtual void setFallbackFamiliesList(const QStringList &fallbacks);
-
-private:
- void init(QFontEngine *fe);
-
- mutable QStringList fallbackFamilies;
- int script;
- mutable bool fallbacksQueried;
-};
-
QT_END_NAMESPACE
-#endif // QFONTENGINE_QPA_P_H
+#endif // QFONTENGINE_QPF2_P_H
diff --git a/src/gui/text/qplatformfontdatabase.cpp b/src/gui/text/qplatformfontdatabase.cpp
index 33301005c6..e9ffa68591 100644
--- a/src/gui/text/qplatformfontdatabase.cpp
+++ b/src/gui/text/qplatformfontdatabase.cpp
@@ -41,7 +41,7 @@
#include "qplatformfontdatabase.h"
#include <QtGui/private/qfontengine_p.h>
-#include <QtGui/private/qfontengine_qpa_p.h>
+#include <QtGui/private/qfontengine_qpf2_p.h>
#include <QtCore/QLibraryInfo>
#include <QtCore/QDir>
@@ -69,12 +69,12 @@ void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void *
return;
const uchar *data = reinterpret_cast<const uchar *>(dataArray.constData());
- if (QFontEngineQPA::verifyHeader(data, dataArray.size())) {
- QString fontName = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_FontName).toString();
- int pixelSize = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_PixelSize).toInt();
- QVariant weight = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_Weight);
- QVariant style = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_Style);
- QByteArray writingSystemBits = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_WritingSystems).toByteArray();
+ if (QFontEngineQPF2::verifyHeader(data, dataArray.size())) {
+ QString fontName = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_FontName).toString();
+ int pixelSize = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_PixelSize).toInt();
+ QVariant weight = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_Weight);
+ QVariant style = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_Style);
+ QByteArray writingSystemBits = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_WritingSystems).toByteArray();
if (!fontName.isEmpty() && pixelSize) {
QFont::Weight fontWeight = QFont::Normal;
@@ -322,7 +322,7 @@ void QPlatformFontDatabase::invalidate()
*/
QFontEngineMulti *QPlatformFontDatabase::fontEngineMulti(QFontEngine *fontEngine, QChar::Script script)
{
- return new QFontEngineMultiQPA(fontEngine, script);
+ return new QFontEngineMultiBasicImpl(fontEngine, script);
}
/*!
@@ -332,7 +332,7 @@ QFontEngineMulti *QPlatformFontDatabase::fontEngineMulti(QFontEngine *fontEngine
QFontEngine *QPlatformFontDatabase::fontEngine(const QFontDef &fontDef, void *handle)
{
QByteArray *fileDataPtr = static_cast<QByteArray *>(handle);
- QFontEngineQPA *engine = new QFontEngineQPA(fontDef,*fileDataPtr);
+ QFontEngineQPF2 *engine = new QFontEngineQPF2(fontDef,*fileDataPtr);
//qDebug() << fontDef.pixelSize << fontDef.weight << fontDef.style << fontDef.stretch << fontDef.styleHint << fontDef.styleStrategy << fontDef.family;
return engine;
}
diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp
index f789ec596b..9b24742823 100644
--- a/src/gui/text/qrawfont.cpp
+++ b/src/gui/text/qrawfont.cpp
@@ -47,6 +47,10 @@
#include "qrawfont_p.h"
#include "qplatformfontdatabase.h"
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformfontdatabase.h>
+
#include <QtCore/qendian.h>
QT_BEGIN_NAMESPACE
@@ -252,7 +256,7 @@ void QRawFont::loadFromData(const QByteArray &fontData,
d->cleanUp();
d->hintingPreference = hintingPreference;
d->thread = QThread::currentThread();
- d->platformLoadFromData(fontData, pixelSize, hintingPreference);
+ d->loadFromData(fontData, pixelSize, hintingPreference);
}
/*!
@@ -735,7 +739,6 @@ void QRawFont::setPixelSize(qreal pixelSize)
*/
void QRawFontPrivate::cleanUp()
{
- platformCleanUp();
if (fontEngine != 0) {
if (!fontEngine->ref.deref())
delete fontEngine;
@@ -744,6 +747,17 @@ void QRawFontPrivate::cleanUp()
hintingPreference = QFont::PreferDefaultHinting;
}
+void QRawFontPrivate::loadFromData(const QByteArray &fontData, qreal pixelSize,
+ QFont::HintingPreference hintingPreference)
+{
+ Q_ASSERT(fontEngine == 0);
+
+ QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
+ fontEngine = pfdb->fontEngine(fontData, pixelSize, hintingPreference);
+ if (fontEngine != 0)
+ fontEngine->ref.ref();
+}
+
/*!
Returns the smallest rectangle containing the glyph with the given \a glyphIndex.
diff --git a/src/gui/text/qrawfont_p.h b/src/gui/text/qrawfont_p.h
index c9c15717cc..b13454c391 100644
--- a/src/gui/text/qrawfont_p.h
+++ b/src/gui/text/qrawfont_p.h
@@ -95,8 +95,7 @@ public:
}
void cleanUp();
- void platformCleanUp();
- void platformLoadFromData(const QByteArray &fontData,
+ void loadFromData(const QByteArray &fontData,
qreal pixelSize,
QFont::HintingPreference hintingPreference);
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index a3059008be..17bc4fde98 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -59,10 +59,6 @@
#include <algorithm>
#include <stdlib.h>
-#ifndef QT_NO_RAWFONT
-#include "qfontengine_qpa_p.h"
-#endif
-
QT_BEGIN_NAMESPACE
static const float smallCapsFraction = 0.7f;
@@ -88,7 +84,7 @@ public:
/// The caps parameter is used to choose the algoritm of splitting text and assiging roles to the textitems
void generate(int start, int length, QFont::Capitalization caps)
{
- if ((int)caps == (int)QFont::SmallCaps)
+ if (caps == QFont::SmallCaps)
generateScriptItemsSmallCaps(reinterpret_cast<const ushort *>(m_string.unicode()), start, length);
else if(caps == QFont::Capitalize)
generateScriptItemsCapitalize(start, length);
@@ -122,9 +118,7 @@ private:
return;
const int end = start + length;
for (int i = start + 1; i < end; ++i) {
- if (m_analysis[i].bidiLevel == m_analysis[start].bidiLevel
- && m_analysis[i].flags == m_analysis[start].flags
- && m_analysis[i].script == m_analysis[start].script
+ if (m_analysis[i] == m_analysis[start]
&& m_analysis[i].flags < QScriptAnalysis::SpaceTabOrObject
&& i - start < MaxItemLength)
continue;
@@ -843,6 +837,81 @@ enum JustificationClass {
Justification_Arabic_Kashida = 13 // User-inserted Kashida(U+0640)
};
+#ifdef QT_ENABLE_HARFBUZZ_NG
+
+/*
+ Adds an inter character justification opportunity after the number or letter
+ character and a space justification opportunity after the space character.
+*/
+static inline void qt_getDefaultJustificationOpportunities(const ushort *string, int length, QGlyphLayout g, ushort *log_clusters, int spaceAs)
+{
+ int str_pos = 0;
+ while (str_pos < length) {
+ int glyph_pos = log_clusters[str_pos];
+
+ Q_ASSERT(glyph_pos < g.numGlyphs && g.attributes[glyph_pos].clusterStart);
+
+ uint ucs4 = string[str_pos];
+ if (QChar::isHighSurrogate(ucs4) && str_pos + 1 < length) {
+ ushort low = string[str_pos + 1];
+ if (QChar::isLowSurrogate(low)) {
+ ++str_pos;
+ ucs4 = QChar::surrogateToUcs4(ucs4, low);
+ }
+ }
+
+ // skip whole cluster
+ do {
+ ++str_pos;
+ } while (str_pos < length && log_clusters[str_pos] == glyph_pos);
+ do {
+ ++glyph_pos;
+ } while (glyph_pos < g.numGlyphs && !g.attributes[glyph_pos].clusterStart);
+ --glyph_pos;
+
+ // justification opportunity at the end of cluster
+ if (Q_LIKELY(QChar::isLetterOrNumber(ucs4)))
+ g.attributes[glyph_pos].justification = Justification_Character;
+ else if (Q_LIKELY(QChar::isSpace(ucs4)))
+ g.attributes[glyph_pos].justification = spaceAs;
+ }
+}
+
+static inline void qt_getJustificationOpportunities(const ushort *string, int length, const QScriptItem &si, QGlyphLayout g, ushort *log_clusters)
+{
+ Q_ASSERT(length > 0 && g.numGlyphs > 0);
+
+ for (int glyph_pos = 0; glyph_pos < g.numGlyphs; ++glyph_pos)
+ g.attributes[glyph_pos].justification = Justification_Prohibited;
+
+ int spaceAs;
+
+ switch (si.analysis.script) {
+ case QChar::Script_Nko:
+ case QChar::Script_Mandaic:
+ case QChar::Script_Mongolian:
+ case QChar::Script_PhagsPa:
+ // same as default but inter character justification takes precedence
+ spaceAs = Justification_Arabic_Space;
+ break;
+
+ case QChar::Script_Hiragana:
+ case QChar::Script_Katakana:
+ case QChar::Script_Han:
+ // same as default but inter character justification is the only option
+ spaceAs = Justification_Character;
+ break;
+
+ default:
+ spaceAs = Justification_Space;
+ break;
+ }
+
+ qt_getDefaultJustificationOpportunities(string, length, g, log_clusters, spaceAs);
+}
+
+#endif // QT_ENABLE_HARFBUZZ_NG
+
// shape all the items that intersect with the line, taking tab widths into account to find out what text actually fits in the line.
void QTextEngine::shapeLine(const QScriptLine &line)
@@ -853,7 +922,7 @@ void QTextEngine::shapeLine(const QScriptLine &line)
int item = findItem(line.from);
if (item == -1)
return;
- for (item = findItem(line.from); item <= end; ++item) {
+ for ( ; item <= end; ++item) {
QScriptItem &si = layoutData->items[item];
if (si.analysis.flags == QScriptAnalysis::Tab) {
ensureSpace(1);
@@ -1003,6 +1072,11 @@ void QTextEngine::shapeText(int item) const
QGlyphLayout glyphs = shapedGlyphs(&si);
+#ifdef QT_ENABLE_HARFBUZZ_NG
+ if (useHarfbuzzNG)
+ qt_getJustificationOpportunities(string, itemLength, si, glyphs, logClusters(&si));
+#endif
+
if (letterSpacing != 0) {
for (int i = 1; i < si.num_glyphs; ++i) {
if (glyphs.attributes[i].clusterStart) {
@@ -1082,7 +1156,7 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st
hb_buffer_set_segment_properties(buffer, &props);
hb_buffer_guess_segment_properties(buffer);
- uint buffer_flags = 0; // HB_BUFFER_FLAG_DEFAULT
+ uint buffer_flags = HB_BUFFER_FLAG_DEFAULT;
// Symbol encoding used to encode various crap in the 32..255 character code range,
// and thus might override U+00AD [SHY]; avoid hiding default ignorables
if (actualFontEngine->symbol)
@@ -1424,8 +1498,6 @@ void QTextEngine::invalidate()
freeMemory();
minWidth = 0;
maxWidth = 0;
- if (specialData)
- specialData->resolvedFormats.clear();
resetFontEngineCache();
}
@@ -1586,9 +1658,9 @@ void QTextEngine::itemize() const
}
Q_ASSERT(position <= length);
QFont::Capitalization capitalization =
- formats()->charFormat(format).hasProperty(QTextFormat::FontCapitalization)
- ? formats()->charFormat(format).fontCapitalization()
- : formats()->defaultFont().capitalization();
+ formatCollection()->charFormat(format).hasProperty(QTextFormat::FontCapitalization)
+ ? formatCollection()->charFormat(format).fontCapitalization()
+ : formatCollection()->defaultFont().capitalization();
itemizer.generate(prevPosition, position - prevPosition, capitalization);
if (it == end) {
if (position < length)
@@ -1605,8 +1677,8 @@ void QTextEngine::itemize() const
#ifndef QT_NO_RAWFONT
if (useRawFont && specialData) {
int lastIndex = 0;
- for (int i = 0; i < specialData->addFormats.size(); ++i) {
- const QTextLayout::FormatRange &range = specialData->addFormats.at(i);
+ for (int i = 0; i < specialData->formats.size(); ++i) {
+ const QTextLayout::FormatRange &range = specialData->formats.at(i);
const QTextCharFormat &format = range.format;
if (format.hasProperty(QTextFormat::FontCapitalization)) {
itemizer.generate(lastIndex, range.start - lastIndex, QFont::MixedCase);
@@ -1621,7 +1693,7 @@ void QTextEngine::itemize() const
}
addRequiredBoundaries();
- resolveAdditionalFormats();
+ resolveFormats();
}
bool QTextEngine::isRightToLeft() const
@@ -1646,6 +1718,9 @@ bool QTextEngine::isRightToLeft() const
int QTextEngine::findItem(int strPos) const
{
itemize();
+ if (strPos < 0 || strPos >= layoutData->string.size())
+ return -1;
+
int left = 1;
int right = layoutData->items.size()-1;
while(left <= right) {
@@ -1884,7 +1959,7 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix
if (feCache.prevFontEngine && feCache.prevFontEngine->type() == QFontEngine::Multi && feCache.prevScript == script) {
engine = feCache.prevFontEngine;
} else {
- engine = QFontEngineMultiQPA::createMultiFontEngine(rawFont.d->fontEngine, script);
+ engine = QFontEngineMultiBasicImpl::createMultiFontEngine(rawFont.d->fontEngine, script);
feCache.prevFontEngine = engine;
feCache.prevScript = script;
engine->ref.ref();
@@ -1893,13 +1968,13 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix
feCache.prevScaledFontEngine = 0;
}
}
- if (si.analysis.flags & QFont::SmallCaps) {
+ if (si.analysis.flags == QScriptAnalysis::SmallCaps) {
if (feCache.prevScaledFontEngine) {
scaledEngine = feCache.prevScaledFontEngine;
} else {
QFontEngine *scEngine = rawFont.d->fontEngine->cloneWithSize(smallCapsFraction * rawFont.pixelSize());
scEngine->ref.ref();
- scaledEngine = QFontEngineMultiQPA::createMultiFontEngine(scEngine, script);
+ scaledEngine = QFontEngineMultiBasicImpl::createMultiFontEngine(scEngine, script);
scaledEngine->ref.ref();
feCache.prevScaledFontEngine = scaledEngine;
// If scEngine is not ref'ed by scaledEngine, make sure it is deallocated and not leaked.
@@ -2065,7 +2140,8 @@ void QTextEngine::justify(const QScriptLine &line)
return;
int firstItem = findItem(line.from);
- int nItems = findItem(line.from + line_length - 1) - firstItem + 1;
+ int lastItem = findItem(line.from + line_length - 1);
+ int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0;
QVarLengthArray<QJustificationPoint> justificationPoints;
int nPoints = 0;
@@ -2367,6 +2443,8 @@ void QTextEngine::freeMemory()
layoutData->haveCharAttributes = false;
layoutData->items.clear();
}
+ if (specialData)
+ specialData->resolvedFormats.clear();
for (int i = 0; i < lines.size(); ++i) {
lines[i].justified = 0;
lines[i].gridfitted = 0;
@@ -2376,7 +2454,7 @@ void QTextEngine::freeMemory()
int QTextEngine::formatIndex(const QScriptItem *si) const
{
if (specialData && !specialData->resolvedFormats.isEmpty()) {
- QTextFormatCollection *collection = formats();
+ QTextFormatCollection *collection = formatCollection();
Q_ASSERT(collection);
return collection->indexForFormat(specialData->resolvedFormats.at(si - &layoutData->items[0]));
}
@@ -2398,16 +2476,16 @@ int QTextEngine::formatIndex(const QScriptItem *si) const
QTextCharFormat QTextEngine::format(const QScriptItem *si) const
{
- if (const QTextFormatCollection *formats = this->formats())
- return formats->charFormat(formatIndex(si));
+ if (const QTextFormatCollection *collection = formatCollection())
+ return collection->charFormat(formatIndex(si));
return QTextCharFormat();
}
void QTextEngine::addRequiredBoundaries() const
{
if (specialData) {
- for (int i = 0; i < specialData->addFormats.size(); ++i) {
- const QTextLayout::FormatRange &r = specialData->addFormats.at(i);
+ for (int i = 0; i < specialData->formats.size(); ++i) {
+ const QTextLayout::FormatRange &r = specialData->formats.at(i);
setBoundary(r.start);
setBoundary(r.start + r.length);
//qDebug("adding boundaries %d %d", r.start, r.start+r.length);
@@ -2476,7 +2554,7 @@ void QTextEngine::setPreeditArea(int position, const QString &preeditText)
if (preeditText.isEmpty()) {
if (!specialData)
return;
- if (specialData->addFormats.isEmpty()) {
+ if (specialData->formats.isEmpty()) {
delete specialData;
specialData = 0;
} else {
@@ -2493,41 +2571,41 @@ void QTextEngine::setPreeditArea(int position, const QString &preeditText)
clearLineData();
}
-void QTextEngine::setAdditionalFormats(const QList<QTextLayout::FormatRange> &formatList)
+void QTextEngine::setFormats(const QList<QTextLayout::FormatRange> &formats)
{
- if (formatList.isEmpty()) {
+ if (formats.isEmpty()) {
if (!specialData)
return;
if (specialData->preeditText.isEmpty()) {
delete specialData;
specialData = 0;
} else {
- specialData->addFormats.clear();
+ specialData->formats.clear();
}
} else {
if (!specialData) {
specialData = new SpecialData;
specialData->preeditPosition = -1;
}
- specialData->addFormats = formatList;
- indexAdditionalFormats();
+ specialData->formats = formats;
+ indexFormats();
}
invalidate();
clearLineData();
}
-void QTextEngine::indexAdditionalFormats()
+void QTextEngine::indexFormats()
{
- QTextFormatCollection *collection = formats();
+ QTextFormatCollection *collection = formatCollection();
if (!collection) {
Q_ASSERT(!block.docHandle());
- specialData->formats.reset(new QTextFormatCollection);
- collection = specialData->formats.data();
+ specialData->formatCollection.reset(new QTextFormatCollection);
+ collection = specialData->formatCollection.data();
}
// replace with shared copies
- for (int i = 0; i < specialData->addFormats.count(); ++i) {
- QTextCharFormat &format = specialData->addFormats[i].format;
+ for (int i = 0; i < specialData->formats.size(); ++i) {
+ QTextCharFormat &format = specialData->formats[i].format;
format = collection->charFormat(collection->indexForFormat(format));
}
}
@@ -2755,64 +2833,17 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
return layoutData->string.mid(from, to - from);
}
-namespace {
-struct QScriptItemComparator {
- bool operator()(int p, const QScriptItem &b) { return p < b.position; }
-#if defined(Q_CC_MSVC) && _MSC_VER < 1600
-//The STL implementation of MSVC 2008 requires the definition
- bool operator()(const QScriptItem &a, int p) { return a.position < p; }
- bool operator()(const QScriptItem &a, const QScriptItem &b) { return a.position < b.position; }
-#endif
-};
-}
-
void QTextEngine::setBoundary(int strPos) const
{
- if (strPos <= 0 || strPos >= layoutData->string.length())
+ const int item = findItem(strPos);
+ if (item < 0)
return;
- const QScriptItem* it = std::upper_bound(layoutData->items.constBegin(), layoutData->items.constEnd(),
- strPos, QScriptItemComparator());
- Q_ASSERT(it > layoutData->items.constBegin());
- --it;
- if (it->position == strPos) {
- // already a split at the requested position
- return;
+ QScriptItem newItem = layoutData->items.at(item);
+ if (newItem.position != strPos) {
+ newItem.position = strPos;
+ layoutData->items.insert(item + 1, newItem);
}
- splitItem(it - layoutData->items.constBegin(), strPos - it->position);
-}
-
-void QTextEngine::splitItem(int item, int pos) const
-{
- if (pos <= 0)
- return;
-
- layoutData->items.insert(item + 1, layoutData->items[item]);
- QScriptItem &oldItem = layoutData->items[item];
- QScriptItem &newItem = layoutData->items[item+1];
- newItem.position += pos;
-
- if (oldItem.num_glyphs) {
- // already shaped, break glyphs aswell
- int breakGlyph = logClusters(&oldItem)[pos];
-
- newItem.num_glyphs = oldItem.num_glyphs - breakGlyph;
- oldItem.num_glyphs = breakGlyph;
- newItem.glyph_data_offset = oldItem.glyph_data_offset + breakGlyph;
-
- for (int i = 0; i < newItem.num_glyphs; i++)
- logClusters(&newItem)[i] -= breakGlyph;
-
- QFixed w = 0;
- const QGlyphLayout g = shapedGlyphs(&oldItem);
- for(int j = 0; j < breakGlyph; ++j)
- w += g.advances[j] * !g.attributes[j].dontPrint;
-
- newItem.width = oldItem.width - w;
- oldItem.width = w;
- }
-
-// qDebug("split at position %d itempos=%d", pos, item);
}
QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const
@@ -2932,45 +2963,44 @@ public:
};
}
-void QTextEngine::resolveAdditionalFormats() const
+void QTextEngine::resolveFormats() const
{
- if (!specialData || specialData->addFormats.isEmpty()
- || !specialData->resolvedFormats.isEmpty())
+ if (!specialData || specialData->formats.isEmpty())
return;
+ Q_ASSERT(specialData->resolvedFormats.isEmpty());
- QTextFormatCollection *collection = formats();
+ QTextFormatCollection *collection = formatCollection();
- specialData->resolvedFormats.clear();
QVector<QTextCharFormat> resolvedFormats(layoutData->items.count());
- QVarLengthArray<int, 64> addFormatSortedByStart;
- addFormatSortedByStart.reserve(specialData->addFormats.count());
- for (int i = 0; i < specialData->addFormats.count(); ++i) {
- if (specialData->addFormats.at(i).length >= 0)
- addFormatSortedByStart.append(i);
+ QVarLengthArray<int, 64> formatsSortedByStart;
+ formatsSortedByStart.reserve(specialData->formats.size());
+ for (int i = 0; i < specialData->formats.size(); ++i) {
+ if (specialData->formats.at(i).length >= 0)
+ formatsSortedByStart.append(i);
}
- QVarLengthArray<int, 64> addFormatSortedByEnd = addFormatSortedByStart;
- std::sort(addFormatSortedByStart.begin(), addFormatSortedByStart.end(),
- FormatRangeComparatorByStart(specialData->addFormats));
- std::sort(addFormatSortedByEnd.begin(), addFormatSortedByEnd.end(),
- FormatRangeComparatorByEnd(specialData->addFormats));
+ QVarLengthArray<int, 64> formatsSortedByEnd = formatsSortedByStart;
+ std::sort(formatsSortedByStart.begin(), formatsSortedByStart.end(),
+ FormatRangeComparatorByStart(specialData->formats));
+ std::sort(formatsSortedByEnd.begin(), formatsSortedByEnd.end(),
+ FormatRangeComparatorByEnd(specialData->formats));
QVarLengthArray<int, 16> currentFormats;
- const int *startIt = addFormatSortedByStart.constBegin();
- const int *endIt = addFormatSortedByEnd.constBegin();
+ const int *startIt = formatsSortedByStart.constBegin();
+ const int *endIt = formatsSortedByEnd.constBegin();
for (int i = 0; i < layoutData->items.count(); ++i) {
const QScriptItem *si = &layoutData->items.at(i);
int end = si->position + length(si);
- while (startIt != addFormatSortedByStart.constEnd() &&
- specialData->addFormats.at(*startIt).start <= si->position) {
+ while (startIt != formatsSortedByStart.constEnd() &&
+ specialData->formats.at(*startIt).start <= si->position) {
currentFormats.insert(std::upper_bound(currentFormats.begin(), currentFormats.end(), *startIt),
*startIt);
++startIt;
}
- while (endIt != addFormatSortedByEnd.constEnd() &&
- specialData->addFormats.at(*endIt).start + specialData->addFormats.at(*endIt).length < end) {
+ while (endIt != formatsSortedByEnd.constEnd() &&
+ specialData->formats.at(*endIt).start + specialData->formats.at(*endIt).length < end) {
int *currentFormatIterator = std::lower_bound(currentFormats.begin(), currentFormats.end(), *endIt);
if (*endIt < *currentFormatIterator)
currentFormatIterator = currentFormats.end();
@@ -2986,7 +3016,7 @@ void QTextEngine::resolveAdditionalFormats() const
}
if (!currentFormats.isEmpty()) {
foreach (int cur, currentFormats) {
- const QTextLayout::FormatRange &range = specialData->addFormats.at(cur);
+ const QTextLayout::FormatRange &range = specialData->formats.at(cur);
Q_ASSERT(range.start <= si->position && range.start + range.length >= end);
format.merge(range.format);
}
@@ -3486,15 +3516,15 @@ QTextLineItemIterator::QTextLineItemIterator(QTextEngine *_eng, int _lineNum, co
logicalItem(-1),
item(-1),
visualOrder(nItems),
- levels(nItems),
selection(_selection)
{
- pos_x = x = QFixed::fromReal(pos.x());
+ x = QFixed::fromReal(pos.x());
x += line.x;
x += eng->alignLine(line);
+ QVarLengthArray<uchar> levels(nItems);
for (int i = 0; i < nItems; ++i)
levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;
QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
@@ -3565,7 +3595,7 @@ bool QTextLineItemIterator::getSelectionBounds(QFixed *selectionX, QFixed *selec
return false;
int start_glyph = logClusters[from];
- int end_glyph = (to == eng->length(item)) ? si->num_glyphs : logClusters[to];
+ int end_glyph = (to == itemLength) ? si->num_glyphs : logClusters[to];
QFixed soff;
QFixed swidth;
if (si->analysis.bidiLevel %2) {
@@ -3590,7 +3620,7 @@ bool QTextLineItemIterator::getSelectionBounds(QFixed *selectionX, QFixed *selec
// If the ending character is also part of a ligature, swidth does
// not contain that part yet, we also need to find out the width of
// that left part
- *selectionWidth += eng->offsetInLigature(si, to, eng->length(item), end_glyph);
+ *selectionWidth += eng->offsetInLigature(si, to, itemLength, end_glyph);
}
return true;
}
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index 342a94de66..13879912d3 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -505,10 +505,10 @@ public:
void freeMemory();
int findItem(int strPos) const;
- inline QTextFormatCollection *formats() const {
+ inline QTextFormatCollection *formatCollection() const {
if (block.docHandle())
return block.docHandle()->formatCollection();
- return specialData ? specialData->formats.data() : 0;
+ return specialData ? specialData->formatCollection.data() : 0;
}
QTextCharFormat format(const QScriptItem *si) const;
inline QAbstractTextDocumentLayout *docLayout() const {
@@ -572,19 +572,17 @@ public:
ItemDecorationList overlineList;
inline bool visualCursorMovement() const
- {
- return (visualMovement ||
- (block.docHandle() ? block.docHandle()->defaultCursorMoveStyle == Qt::VisualMoveStyle : false));
- }
+ { return visualMovement || (block.docHandle() && block.docHandle()->defaultCursorMoveStyle == Qt::VisualMoveStyle); }
inline int preeditAreaPosition() const { return specialData ? specialData->preeditPosition : -1; }
inline QString preeditAreaText() const { return specialData ? specialData->preeditText : QString(); }
void setPreeditArea(int position, const QString &text);
- inline bool hasFormats() const { return block.docHandle() || (specialData && !specialData->addFormats.isEmpty()); }
- inline QList<QTextLayout::FormatRange> additionalFormats() const
- { return specialData ? specialData->addFormats : QList<QTextLayout::FormatRange>(); }
- void setAdditionalFormats(const QList<QTextLayout::FormatRange> &formatList);
+ inline bool hasFormats() const
+ { return block.docHandle() || (specialData && !specialData->formats.isEmpty()); }
+ inline QList<QTextLayout::FormatRange> formats() const
+ { return specialData ? specialData->formats : QList<QTextLayout::FormatRange>(); }
+ void setFormats(const QList<QTextLayout::FormatRange> &formats);
private:
static void init(QTextEngine *e);
@@ -592,15 +590,15 @@ private:
struct SpecialData {
int preeditPosition;
QString preeditText;
- QList<QTextLayout::FormatRange> addFormats;
+ QList<QTextLayout::FormatRange> formats;
QVector<QTextCharFormat> resolvedFormats;
// only used when no docHandle is available
- QScopedPointer<QTextFormatCollection> formats;
+ QScopedPointer<QTextFormatCollection> formatCollection;
};
SpecialData *specialData;
- void indexAdditionalFormats();
- void resolveAdditionalFormats() const;
+ void indexFormats();
+ void resolveFormats() const;
public:
bool atWordSeparator(int position) const;
@@ -643,7 +641,6 @@ private:
int shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector<uint> &itemBoundaries, bool kerningEnabled) const;
#endif
int shapeTextWithHarfbuzz(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector<uint> &itemBoundaries, bool kerningEnabled) const;
- void splitItem(int item, int pos) const;
int endOfLine(int lineNum);
int beginningOfLine(int lineNum);
@@ -676,15 +673,14 @@ struct QTextLineItemIterator
QTextEngine *eng;
QFixed x;
- QFixed pos_x;
const QScriptLine &line;
QScriptItem *si;
- int lineNum;
- int lineEnd;
- int firstItem;
- int lastItem;
- int nItems;
+ const int lineNum;
+ const int lineEnd;
+ const int firstItem;
+ const int lastItem;
+ const int nItems;
int logicalItem;
int item;
int itemLength;
@@ -697,7 +693,6 @@ struct QTextLineItemIterator
QFixed itemWidth;
QVarLengthArray<int> visualOrder;
- QVarLengthArray<uchar> levels;
const QTextLayout::FormatRange *selection;
};
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 4879ae51d7..9919ce6bb4 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -505,7 +505,7 @@ QString QTextLayout::preeditAreaText() const
*/
void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList)
{
- d->setAdditionalFormats(formatList);
+ d->setFormats(formatList);
if (d->block.docHandle())
d->block.docHandle()->documentChange(d->block.position(), d->block.length());
@@ -518,7 +518,7 @@ void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList)
*/
QList<QTextLayout::FormatRange> QTextLayout::additionalFormats() const
{
- return d->additionalFormats();
+ return d->formats();
}
/*!
@@ -567,7 +567,7 @@ bool QTextLayout::cacheEnabled() const
*/
void QTextLayout::setCursorMoveStyle(Qt::CursorMoveStyle style)
{
- d->visualMovement = style == Qt::VisualMoveStyle ? true : false;
+ d->visualMovement = style == Qt::VisualMoveStyle;
}
/*!
@@ -1735,6 +1735,7 @@ void QTextLine::layout_helper(int maxGlyphs)
int item = -1;
int newItem = eng->findItem(line.from);
+ Q_ASSERT(newItem >= 0);
LB_DEBUG("from: %d: item=%d, total %d, width available %f", line.from, newItem, eng->layoutData->items.size(), line.width.toReal());
@@ -2212,14 +2213,10 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
if (si.analysis.flags >= QScriptAnalysis::TabOrObject)
continue;
- QPointF pos(iterator.x.toReal(), y);
- if (from >= 0 && length >= 0 &&
- (from >= si.position + eng->length(&si)
- || from + length <= si.position
- || from + length <= iterator.itemStart
- || from >= iterator.itemEnd)) {
+ if (from >= 0 && length >= 0 && (from >= iterator.itemEnd || from + length <= iterator.itemStart))
continue;
- }
+
+ QPointF pos(iterator.x.toReal(), y);
QFont font;
QGlyphRun::GlyphRunFlags flags;
@@ -2240,15 +2237,13 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
}
int relativeFrom = qMax(iterator.itemStart, from) - si.position;
- int relativeTo = qMin(iterator.itemEnd - 1, from + length - 1) - si.position;
+ int relativeTo = qMin(iterator.itemEnd, from + length) - 1 - si.position;
unsigned short *logClusters = eng->logClusters(&si);
int glyphsStart = logClusters[relativeFrom];
- int glyphsEnd = (relativeTo == eng->length(&si))
- ? si.num_glyphs - 1
- : logClusters[relativeTo];
+ int glyphsEnd = (relativeTo == iterator.itemLength) ? si.num_glyphs - 1 : logClusters[relativeTo];
// the glyph index right next to the requested range
- int nextGlyphIndex = relativeTo < eng->length(&si) - 1 ? logClusters[relativeTo + 1] : si.num_glyphs;
+ int nextGlyphIndex = (relativeTo < iterator.itemLength - 1) ? logClusters[relativeTo + 1] : si.num_glyphs;
if (nextGlyphIndex - 1 > glyphsEnd)
glyphsEnd = nextGlyphIndex - 1;
bool startsInsideLigature = relativeFrom > 0 && logClusters[relativeFrom - 1] == glyphsStart;
diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri
index c67769ad48..091129f5be 100644
--- a/src/gui/text/text.pri
+++ b/src/gui/text/text.pri
@@ -77,10 +77,8 @@ SOURCES += \
text/qdistancefield.cpp
SOURCES += \
- text/qfont_qpa.cpp \
- text/qfontengine_qpa.cpp \
- text/qplatformfontdatabase.cpp \
- text/qrawfont_qpa.cpp
+ text/qfontengine_qpf2.cpp \
+ text/qplatformfontdatabase.cpp
HEADERS += \
text/qplatformfontdatabase.h
diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp
index 87146118db..460646324f 100644
--- a/src/gui/util/qdesktopservices.cpp
+++ b/src/gui/util/qdesktopservices.cpp
@@ -314,7 +314,7 @@ extern Q_CORE_EXPORT QString qt_applicationName_noFallback();
QString QDesktopServices::storageLocationImpl(QStandardPaths::StandardLocation type)
{
- if (type == QStandardPaths::DataLocation) {
+ if (type == QStandardPaths::AppLocalDataLocation) {
// Preserve Qt 4 compatibility:
// * QCoreApplication::applicationName() must default to empty
// * Unix data location is under the "data/" subdirectory
diff --git a/src/gui/util/qgridlayoutengine.cpp b/src/gui/util/qgridlayoutengine.cpp
index 10b4a2ee35..7170477e84 100644
--- a/src/gui/util/qgridlayoutengine.cpp
+++ b/src/gui/util/qgridlayoutengine.cpp
@@ -983,9 +983,10 @@ void QGridLayoutEngine::invalidate()
q_cachedEffectiveFirstRows[Ver] = -1;
q_cachedEffectiveLastRows[Hor] = -1;
q_cachedEffectiveLastRows[Ver] = -1;
- q_totalBoxesValid = false;
- q_sizeHintValid[Hor] = false;
- q_sizeHintValid[Ver] = false;
+
+ q_totalBoxCachedConstraints[Hor] = NotCached;
+ q_totalBoxCachedConstraints[Ver] = NotCached;
+
q_cachedSize = QSizeF();
q_cachedConstraintOrientation = UnknownConstraint;
}
@@ -1530,7 +1531,11 @@ void QGridLayoutEngine::ensureColumnAndRowData(QGridLayoutRowData *rowData, QGri
const QAbstractLayoutStyleInfo *styleInfo) const
{
const int o = (orientation == Qt::Vertical ? Ver : Hor);
- if (q_sizeHintValid[o] && !colPositions && !colSizes) {
+ const int cc = columnCount(orientation);
+
+ const qreal constraint = (colPositions && colSizes && hasDynamicConstraint()) ? (colPositions[cc - 1] + colSizes[cc - 1]) : qreal(CachedWithNoConstraint);
+ qreal &cachedConstraint = q_totalBoxCachedConstraints[o];
+ if (cachedConstraint == constraint) {
if (totalBox != &q_totalBoxes[o])
*totalBox = q_totalBoxes[o];
return;
@@ -1541,10 +1546,10 @@ void QGridLayoutEngine::ensureColumnAndRowData(QGridLayoutRowData *rowData, QGri
rowData->distributeMultiCells(rowInfo);
*totalBox = rowData->totalBox(0, rowCount(orientation));
- if (!colPositions && !colSizes) {
+ if (totalBox != &q_totalBoxes[o])
q_totalBoxes[o] = *totalBox;
- q_sizeHintValid[o] = true;
- }
+
+ cachedConstraint = constraint;
}
/**
@@ -1593,10 +1598,9 @@ Qt::Orientation QGridLayoutEngine::constraintOrientation() const
void QGridLayoutEngine::ensureGeometries(const QSizeF &size,
const QAbstractLayoutStyleInfo *styleInfo) const
{
- if (!styleInfo->hasChanged() && q_totalBoxesValid && q_cachedSize == size)
+ if (!styleInfo->hasChanged() && q_cachedSize == size)
return;
- q_totalBoxesValid = true;
q_cachedSize = size;
q_xx.resize(columnCount());
@@ -1606,7 +1610,7 @@ void QGridLayoutEngine::ensureGeometries(const QSizeF &size,
q_descents.resize(rowCount());
if (constraintOrientation() != Qt::Horizontal) {
- //We might have items whose width depends on their height
+ //We might have items whose height depends on their width (HFW)
ensureColumnAndRowData(&q_columnData, &q_totalBoxes[Hor], NULL, NULL, Qt::Horizontal, styleInfo);
//Calculate column widths and positions, and put results in q_xx.data() and q_widths.data() so that we can use this information as
//constraints to find the row heights
@@ -1617,7 +1621,7 @@ void QGridLayoutEngine::ensureGeometries(const QSizeF &size,
q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(),
q_descents.data(), q_totalBoxes[Ver], q_infos[Ver]);
} else {
- //We have items whose height depends on their width
+ //We have items whose width depends on their height (WFH)
ensureColumnAndRowData(&q_rowData, &q_totalBoxes[Ver], NULL, NULL, Qt::Vertical, styleInfo);
//Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() so that we can use this information as
//constraints to find the column widths
diff --git a/src/gui/util/qgridlayoutengine_p.h b/src/gui/util/qgridlayoutengine_p.h
index 9650e7fffe..bbc94bd51f 100644
--- a/src/gui/util/qgridlayoutengine_p.h
+++ b/src/gui/util/qgridlayoutengine_p.h
@@ -450,15 +450,21 @@ private:
mutable int q_cachedEffectiveLastRows[NOrientations];
mutable quint8 q_cachedConstraintOrientation : 3;
+ // this is useful to cache
+ mutable QGridLayoutBox q_totalBoxes[NOrientations];
+ enum {
+ NotCached = -2, // Cache is empty. Happens when the engine is invalidated.
+ CachedWithNoConstraint = -1 // cache has a totalBox without any HFW/WFH constraints.
+ // >= 0 // cache has a totalBox with this specific constraint.
+ };
+ mutable qreal q_totalBoxCachedConstraints[NOrientations]; // holds the constraint used for the cached totalBox
+
// Layout item input
mutable QGridLayoutRowData q_columnData;
mutable QGridLayoutRowData q_rowData;
- mutable QGridLayoutBox q_totalBoxes[NOrientations];
// Output
mutable QSizeF q_cachedSize;
- mutable bool q_totalBoxesValid;
- mutable bool q_sizeHintValid[NOrientations];
mutable QVector<qreal> q_xx;
mutable QVector<qreal> q_yy;
mutable QVector<qreal> q_widths;
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index 360f9722c7..7ff6bffed3 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -1203,7 +1203,7 @@ QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16
: QObject(*(new QHttpNetworkConnectionPrivate(hostName, port, encrypt, connectionType)), parent)
{
Q_D(QHttpNetworkConnection);
- d->networkSession = networkSession;
+ d->networkSession = qMove(networkSession);
d->init();
}
@@ -1215,7 +1215,7 @@ QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QS
connectionType)), parent)
{
Q_D(QHttpNetworkConnection);
- d->networkSession = networkSession;
+ d->networkSession = qMove(networkSession);
d->init();
}
#else
@@ -1339,7 +1339,7 @@ QSharedPointer<QSslContext> QHttpNetworkConnection::sslContext()
void QHttpNetworkConnection::setSslContext(QSharedPointer<QSslContext> context)
{
Q_D(QHttpNetworkConnection);
- d->sslContext = context;
+ d->sslContext = qMove(context);
}
void QHttpNetworkConnection::ignoreSslErrors(int channel)
diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp
index 76107d3110..8743989dec 100644
--- a/src/network/access/qhttpthreaddelegate.cpp
+++ b/src/network/access/qhttpthreaddelegate.cpp
@@ -188,7 +188,7 @@ public:
QHttpNetworkConnection::ConnectionType connectionType,
QSharedPointer<QNetworkSession> networkSession)
: QHttpNetworkConnection(hostName, port, encrypt, connectionType, /*parent=*/0,
- networkSession)
+ qMove(networkSession))
#endif
{
setExpires(true);
diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp
index b4aaca0851..acaba33dee 100644
--- a/src/network/access/qnetworkaccessbackend.cpp
+++ b/src/network/access/qnetworkaccessbackend.cpp
@@ -130,9 +130,9 @@ QStringList QNetworkAccessManagerPrivate::backendSupportedSchemes() const
QNonContiguousByteDevice* QNetworkAccessBackend::createUploadByteDevice()
{
if (reply->outgoingDataBuffer)
- uploadByteDevice = QSharedPointer<QNonContiguousByteDevice>(QNonContiguousByteDeviceFactory::create(reply->outgoingDataBuffer));
+ uploadByteDevice = QNonContiguousByteDeviceFactory::createShared(reply->outgoingDataBuffer);
else if (reply->outgoingData) {
- uploadByteDevice = QSharedPointer<QNonContiguousByteDevice>(QNonContiguousByteDeviceFactory::create(reply->outgoingData));
+ uploadByteDevice = QNonContiguousByteDeviceFactory::createShared(reply->outgoingData);
} else {
return 0;
}
diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h
index 9528330aae..bd5a6faeef 100644
--- a/src/network/access/qnetworkaccessmanager_p.h
+++ b/src/network/access/qnetworkaccessmanager_p.h
@@ -92,7 +92,7 @@ public:
initializeSession(true),
#endif
cookieJarCreated(false),
- authenticationManager(new QNetworkAccessAuthenticationManager)
+ authenticationManager(QSharedPointer<QNetworkAccessAuthenticationManager>::create())
{ }
~QNetworkAccessManagerPrivate();
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index 4efb2f6a2a..c5cf849a55 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -194,7 +194,7 @@ QNetworkReplyHttpImpl::QNetworkReplyHttpImpl(QNetworkAccessManager* const manage
if (d->synchronous && outgoingData) {
// The synchronous HTTP is a corner case, we will put all upload data in one big QByteArray in the outgoingDataBuffer.
// Yes, this is not the most efficient thing to do, but on the other hand synchronous XHR needs to die anyway.
- d->outgoingDataBuffer = QSharedPointer<QRingBuffer>(new QRingBuffer());
+ d->outgoingDataBuffer = QSharedPointer<QRingBuffer>::create();
qint64 previousDataSize = 0;
do {
previousDataSize = d->outgoingDataBuffer->size();
@@ -277,6 +277,10 @@ void QNetworkReplyHttpImpl::abort()
// call finished which will emit signals
// FIXME shouldn't this be emitted Queued?
d->error(OperationCanceledError, tr("Operation canceled"));
+
+ // If state is WaitingForSession, calling finished has no effect
+ if (d->state == QNetworkReplyHttpImplPrivate::WaitingForSession)
+ d->state = QNetworkReplyHttpImplPrivate::Working;
d->finished();
}
@@ -440,8 +444,8 @@ QNetworkReplyHttpImplPrivate::QNetworkReplyHttpImplPrivate()
, downloadBufferReadPosition(0)
, downloadBufferCurrentSize(0)
, downloadZerocopyBuffer(0)
- , pendingDownloadDataEmissions(new QAtomicInt())
- , pendingDownloadProgressEmissions(new QAtomicInt())
+ , pendingDownloadDataEmissions(QSharedPointer<QAtomicInt>::create())
+ , pendingDownloadProgressEmissions(QSharedPointer<QAtomicInt>::create())
#ifndef QT_NO_SSL
, pendingIgnoreAllSslErrors(false)
#endif
@@ -1743,7 +1747,7 @@ void QNetworkReplyHttpImplPrivate::_q_bufferOutgoingData()
if (!outgoingDataBuffer) {
// first call, create our buffer
- outgoingDataBuffer = QSharedPointer<QRingBuffer>(new QRingBuffer());
+ outgoingDataBuffer = QSharedPointer<QRingBuffer>::create();
QObject::connect(outgoingData, SIGNAL(readyRead()), q, SLOT(_q_bufferOutgoingData()));
QObject::connect(outgoingData, SIGNAL(readChannelFinished()), q, SLOT(_q_bufferOutgoingDataFinished()));
@@ -1872,9 +1876,9 @@ QNonContiguousByteDevice* QNetworkReplyHttpImplPrivate::createUploadByteDevice()
Q_Q(QNetworkReplyHttpImpl);
if (outgoingDataBuffer)
- uploadByteDevice = QSharedPointer<QNonContiguousByteDevice>(QNonContiguousByteDeviceFactory::create(outgoingDataBuffer));
+ uploadByteDevice = QNonContiguousByteDeviceFactory::createShared(outgoingDataBuffer);
else if (outgoingData) {
- uploadByteDevice = QSharedPointer<QNonContiguousByteDevice>(QNonContiguousByteDeviceFactory::create(outgoingData));
+ uploadByteDevice = QNonContiguousByteDeviceFactory::createShared(outgoingData);
} else {
return 0;
}
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index f51b85cba0..616019ea41 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -248,7 +248,7 @@ void QNetworkReplyImplPrivate::_q_bufferOutgoingData()
if (!outgoingDataBuffer) {
// first call, create our buffer
- outgoingDataBuffer = QSharedPointer<QRingBuffer>(new QRingBuffer());
+ outgoingDataBuffer = QSharedPointer<QRingBuffer>::create();
QObject::connect(outgoingData, SIGNAL(readyRead()), q, SLOT(_q_bufferOutgoingData()));
QObject::connect(outgoingData, SIGNAL(readChannelFinished()), q, SLOT(_q_bufferOutgoingDataFinished()));
@@ -367,7 +367,7 @@ void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const
// The synchronous HTTP is a corner case, we will put all upload data in one big QByteArray in the outgoingDataBuffer.
// Yes, this is not the most efficient thing to do, but on the other hand synchronous XHR needs to die anyway.
if (synchronousHttpAttribute.toBool() && outgoingData) {
- outgoingDataBuffer = QSharedPointer<QRingBuffer>(new QRingBuffer());
+ outgoingDataBuffer = QSharedPointer<QRingBuffer>::create();
qint64 previousDataSize = 0;
do {
previousDataSize = outgoingDataBuffer->size();
diff --git a/src/network/access/qspdyprotocolhandler.cpp b/src/network/access/qspdyprotocolhandler.cpp
index 32a804e9f4..ab703981ee 100644
--- a/src/network/access/qspdyprotocolhandler.cpp
+++ b/src/network/access/qspdyprotocolhandler.cpp
@@ -506,25 +506,7 @@ QByteArray QSpdyProtocolHandler::composeHeader(const QHttpNetworkRequest &reques
#endif
uncompressedHeader.append(headerField(":version", "HTTP/1.1"));
- QHostAddress add; // ### unify with the host parsing from QHttpNetworkConnection
- QByteArray host;
- QString hostName = m_connection->hostName();
- if (add.setAddress(hostName)) {
- if (add.protocol() == QAbstractSocket::IPv6Protocol)
- host = "[" + hostName.toLatin1() + "]"; //format the ipv6 in the standard way
- else
- host = hostName.toLatin1();
-
- } else {
- host = QUrl::toAce(hostName);
- }
-
- int port = request.url().port();
- if (port != -1) {
- host += ':';
- host += QByteArray::number(port);
- }
- uncompressedHeader.append(headerField(":host", host));
+ uncompressedHeader.append(headerField(":host", request.url().authority(QUrl::FullyEncoded | QUrl::RemoveUserInfo).toLatin1()));
uncompressedHeader.append(headerField(":scheme", request.url().scheme().toLatin1()));
diff --git a/src/network/doc/qtnetwork.qdocconf b/src/network/doc/qtnetwork.qdocconf
index 33d6c24461..522d71fd27 100644
--- a/src/network/doc/qtnetwork.qdocconf
+++ b/src/network/doc/qtnetwork.qdocconf
@@ -2,7 +2,6 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = QtNetwork
description = Qt Network Reference Documentation
-url = http://qt-project.org/doc/qt-$QT_VER
version = $QT_VERSION
examplesinstallpath = network
diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp
index f7b956651f..ea935869fb 100644
--- a/src/network/kernel/qauthenticator.cpp
+++ b/src/network/kernel/qauthenticator.cpp
@@ -282,6 +282,15 @@ QString QAuthenticator::realm() const
}
/*!
+ \internal
+*/
+void QAuthenticator::setRealm(const QString &realm)
+{
+ detach();
+ d->realm = realm;
+}
+
+/*!
\since 4.7
Returns the value related to option \a opt if it was set by the server.
See \l{QAuthenticator#Options} for more information on incoming options.
diff --git a/src/network/kernel/qauthenticator.h b/src/network/kernel/qauthenticator.h
index 4d96104bc0..2f440d660d 100644
--- a/src/network/kernel/qauthenticator.h
+++ b/src/network/kernel/qauthenticator.h
@@ -70,6 +70,7 @@ public:
void setPassword(const QString &password);
QString realm() const;
+ void setRealm(const QString &realm);
QVariant option(const QString &opt) const;
QVariantHash options() const;
diff --git a/src/network/kernel/qdnslookup.cpp b/src/network/kernel/qdnslookup.cpp
index e111a190cb..b7e6bad0a7 100644
--- a/src/network/kernel/qdnslookup.cpp
+++ b/src/network/kernel/qdnslookup.cpp
@@ -283,9 +283,21 @@ QDnsLookup::QDnsLookup(Type type, const QString &name, QObject *parent)
/*!
\fn QDnsLookup::QDnsLookup(Type type, const QString &name, const QHostAddress &nameserver, QObject *parent)
- \internal
+ \since 5.4
+ Constructs a QDnsLookup object for the given \a type, \a name and
+ \a nameserver and sets \a parent as the parent object.
*/
+QDnsLookup::QDnsLookup(Type type, const QString &name, const QHostAddress &nameserver, QObject *parent)
+ : QObject(*new QDnsLookupPrivate, parent)
+{
+ Q_D(QDnsLookup);
+ qRegisterMetaType<QDnsLookupReply>();
+ d->name = name;
+ d->type = type;
+ d->nameserver = nameserver;
+}
+
/*!
Destroys the QDnsLookup object.
diff --git a/src/network/kernel/qdnslookup_winrt.cpp b/src/network/kernel/qdnslookup_winrt.cpp
index e2a5ba2f37..52a8c3a530 100644
--- a/src/network/kernel/qdnslookup_winrt.cpp
+++ b/src/network/kernel/qdnslookup_winrt.cpp
@@ -81,31 +81,28 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
return;
}
- IHostNameFactory *hostnameFactory;
-
- HStringReference classId(RuntimeClass_Windows_Networking_HostName);
- if (FAILED(GetActivationFactory(classId.Get(), &hostnameFactory))) {
+ ComPtr<IHostNameFactory> hostnameFactory;
+ HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(),
+ IID_PPV_ARGS(&hostnameFactory));
+ if (FAILED(hr)) {
reply->error = QDnsLookup::ResolverError;
reply->errorString = QLatin1String("Could not obtain hostname factory");
return;
}
- IHostName *host;
+ ComPtr<IHostName> host;
HStringReference hostNameRef((const wchar_t*)aceHostname.utf16());
hostnameFactory->CreateHostName(hostNameRef.Get(), &host);
- hostnameFactory->Release();
- IDatagramSocketStatics *datagramSocketStatics;
+ ComPtr<IDatagramSocketStatics> datagramSocketStatics;
GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_DatagramSocket).Get(), &datagramSocketStatics);
- IAsyncOperation<IVectorView<EndpointPair*> *> *op;
- datagramSocketStatics->GetEndpointPairsAsync(host,
+ ComPtr<IAsyncOperation<IVectorView<EndpointPair *> *>> op;
+ datagramSocketStatics->GetEndpointPairsAsync(host.Get(),
HString::MakeReference(L"0").Get(),
&op);
- datagramSocketStatics->Release();
- host->Release();
- IVectorView<EndpointPair*> *endpointPairs = 0;
- HRESULT hr = op->GetResults(&endpointPairs);
+ ComPtr<IVectorView<EndpointPair *>> endpointPairs;
+ hr = op->GetResults(&endpointPairs);
int waitCount = 0;
while (hr == E_ILLEGAL_METHOD_CALL) {
WaitForSingleObjectEx(GetCurrentThread(), 50, FALSE);
@@ -113,7 +110,6 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
if (++waitCount > 1200) // Wait for 1 minute max
return;
}
- op->Release();
if (!endpointPairs)
return;
@@ -123,11 +119,10 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
// endpoint pairs might contain duplicates so we temporarily store addresses in a QSet
QSet<QHostAddress> addresses;
for (unsigned int i = 0; i < size; ++i) {
- IEndpointPair *endpointpair;
+ ComPtr<IEndpointPair> endpointpair;
endpointPairs->GetAt(i, &endpointpair);
- IHostName *remoteHost;
+ ComPtr<IHostName> remoteHost;
endpointpair->get_RemoteHostName(&remoteHost);
- endpointpair->Release();
HostNameType type;
remoteHost->get_Type(&type);
if (type == HostNameType_Bluetooth || type == HostNameType_DomainName
@@ -138,7 +133,6 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
HString name;
remoteHost->get_CanonicalName(name.GetAddressOf());
- remoteHost->Release();
UINT32 length;
PCWSTR rawString = name.GetRawBuffer(&length);
addresses.insert(QHostAddress(QString::fromWCharArray(rawString, length)));
diff --git a/src/network/kernel/qhostinfo_winrt.cpp b/src/network/kernel/qhostinfo_winrt.cpp
index e02cd98e08..26f6585c32 100644
--- a/src/network/kernel/qhostinfo_winrt.cpp
+++ b/src/network/kernel/qhostinfo_winrt.cpp
@@ -80,29 +80,25 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
return results;
}
- IHostNameFactory *hostnameFactory;
+ ComPtr<IHostNameFactory> hostnameFactory;
+ HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(),
+ IID_PPV_ARGS(&hostnameFactory));
+ Q_ASSERT_X(SUCCEEDED(hr), Q_FUNC_INFO, qPrintable(qt_error_string(hr)));
- HStringReference classId(RuntimeClass_Windows_Networking_HostName);
- if (FAILED(GetActivationFactory(classId.Get(), &hostnameFactory)))
- Q_ASSERT_X(false, "QHostInfoAgent", "Could not obtain hostname factory.");
-
- IHostName *host;
+ ComPtr<IHostName> host;
HStringReference hostNameRef((const wchar_t*)hostName.utf16());
hostnameFactory->CreateHostName(hostNameRef.Get(), &host);
- hostnameFactory->Release();
- IDatagramSocketStatics *datagramSocketStatics;
+ ComPtr<IDatagramSocketStatics> datagramSocketStatics;
GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_DatagramSocket).Get(), &datagramSocketStatics);
- IAsyncOperation<IVectorView<EndpointPair*> *> *op;
- datagramSocketStatics->GetEndpointPairsAsync(host,
+ ComPtr<IAsyncOperation<IVectorView<EndpointPair *> *>> op;
+ datagramSocketStatics->GetEndpointPairsAsync(host.Get(),
HString::MakeReference(L"0").Get(),
&op);
- datagramSocketStatics->Release();
- host->Release();
- IVectorView<EndpointPair*> *endpointPairs = 0;
- HRESULT hr = op->GetResults(&endpointPairs);
+ ComPtr<IVectorView<EndpointPair *>> endpointPairs;
+ hr = op->GetResults(&endpointPairs);
int waitCount = 0;
while (hr == E_ILLEGAL_METHOD_CALL) {
WaitForSingleObjectEx(GetCurrentThread(), 50, FALSE);
@@ -110,7 +106,6 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
if (++waitCount > 1200) // Wait for 1 minute max
return results;
}
- op->Release();
if (!endpointPairs)
return results;
@@ -119,11 +114,10 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
endpointPairs->get_Size(&size);
QList<QHostAddress> addresses;
for (unsigned int i = 0; i < size; ++i) {
- IEndpointPair *endpointpair;
+ ComPtr<IEndpointPair> endpointpair;
endpointPairs->GetAt(i, &endpointpair);
- IHostName *remoteHost;
+ ComPtr<IHostName> remoteHost;
endpointpair->get_RemoteHostName(&remoteHost);
- endpointpair->Release();
if (!remoteHost)
continue;
HostNameType type;
@@ -133,7 +127,6 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
HString name;
remoteHost->get_CanonicalName(name.GetAddressOf());
- remoteHost->Release();
UINT32 length;
PCWSTR rawString = name.GetRawBuffer(&length);
QHostAddress addr;
@@ -148,12 +141,11 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
QString QHostInfo::localHostName()
{
- INetworkInformationStatics *statics;
+ ComPtr<INetworkInformationStatics> statics;
GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Connectivity_NetworkInformation).Get(), &statics);
- IVectorView<HostName*> *hostNames = 0;
+ ComPtr<IVectorView<HostName *>> hostNames;
statics->GetHostNames(&hostNames);
- statics->Release();
if (!hostNames)
return QString();
@@ -163,7 +155,7 @@ QString QHostInfo::localHostName()
return QString();
for (unsigned int i = 0; i < size; ++i) {
- IHostName *hostName;
+ ComPtr<IHostName> hostName;
hostNames->GetAt(i, &hostName);
HostNameType type;
hostName->get_Type(&type);
@@ -172,18 +164,15 @@ QString QHostInfo::localHostName()
HString name;
hostName->get_CanonicalName(name.GetAddressOf());
- hostName->Release();
UINT32 length;
PCWSTR rawString = name.GetRawBuffer(&length);
return QString::fromWCharArray(rawString, length);
}
- IHostName *firstHost;
+ ComPtr<IHostName> firstHost;
hostNames->GetAt(0, &firstHost);
- hostNames->Release();
HString name;
firstHost->get_CanonicalName(name.GetAddressOf());
- firstHost->Release();
UINT32 length;
PCWSTR rawString = name.GetRawBuffer(&length);
return QString::fromWCharArray(rawString, length);
diff --git a/src/network/kernel/qnetworkinterface_winrt.cpp b/src/network/kernel/qnetworkinterface_winrt.cpp
index 48a96928a8..c8547411eb 100644
--- a/src/network/kernel/qnetworkinterface_winrt.cpp
+++ b/src/network/kernel/qnetworkinterface_winrt.cpp
@@ -73,12 +73,11 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
QList<HostNameInfo> hostList;
- INetworkInformationStatics *hostNameStatics;
+ ComPtr<INetworkInformationStatics> hostNameStatics;
GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Connectivity_NetworkInformation).Get(), &hostNameStatics);
- IVectorView<HostName*> *hostNames = 0;
+ ComPtr<IVectorView<HostName *>> hostNames;
hostNameStatics->GetHostNames(&hostNames);
- hostNameStatics->Release();
if (!hostNames)
return interfaces;
@@ -86,7 +85,7 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
hostNames->get_Size(&hostNameCount);
for (unsigned i = 0; i < hostNameCount; ++i) {
HostNameInfo hostInfo;
- IHostName *hostName;
+ ComPtr<IHostName> hostName;
hostNames->GetAt(i, &hostName);
HostNameType type;
@@ -94,20 +93,17 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
if (type == HostNameType_DomainName)
continue;
- IIPInformation *ipInformation;
+ ComPtr<IIPInformation> ipInformation;
hostName->get_IPInformation(&ipInformation);
- INetworkAdapter *currentAdapter;
+ ComPtr<INetworkAdapter> currentAdapter;
ipInformation->get_NetworkAdapter(&currentAdapter);
currentAdapter->get_NetworkAdapterId(&hostInfo.adapterId);
- currentAdapter->Release();
- IReference<unsigned char> *prefixLengthReference;
+ ComPtr<IReference<unsigned char>> prefixLengthReference;
ipInformation->get_PrefixLength(&prefixLengthReference);
- ipInformation->Release();
prefixLengthReference->get_Value(&hostInfo.prefixLength);
- prefixLengthReference->Release();
// invalid prefixes
if ((type == HostNameType_Ipv4 && hostInfo.prefixLength > 32)
@@ -116,20 +112,17 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
HString name;
hostName->get_CanonicalName(name.GetAddressOf());
- hostName->Release();
UINT32 length;
PCWSTR rawString = name.GetRawBuffer(&length);
hostInfo.address = QString::fromWCharArray(rawString, length);
hostList << hostInfo;
}
- hostNames->Release();
INetworkInformationStatics *networkInfoStatics;
GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Connectivity_NetworkInformation).Get(), &networkInfoStatics);
- IVectorView<ConnectionProfile *> *connectionProfiles = 0;
+ ComPtr<IVectorView<ConnectionProfile *>> connectionProfiles;
networkInfoStatics->GetConnectionProfiles(&connectionProfiles);
- networkInfoStatics->Release();
if (!connectionProfiles)
return interfaces;
@@ -139,7 +132,7 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
interfaces << iface;
- IConnectionProfile *profile;
+ ComPtr<IConnectionProfile> profile;
connectionProfiles->GetAt(i, &profile);
NetworkConnectivityLevel connectivityLevel;
@@ -147,16 +140,14 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
if (connectivityLevel != NetworkConnectivityLevel_None)
iface->flags = QNetworkInterface::IsUp | QNetworkInterface::IsRunning;
- INetworkAdapter *adapter;
+ ComPtr<INetworkAdapter> adapter;
profile->get_NetworkAdapter(&adapter);
- profile->Release();
UINT32 type;
adapter->get_IanaInterfaceType(&type);
if (type == 23)
iface->flags |= QNetworkInterface::IsPointToPoint;
GUID id;
adapter->get_NetworkAdapterId(&id);
- adapter->Release();
OLECHAR adapterName[39]={0};
StringFromGUID2(id, adapterName, 39);
iface->name = QString::fromWCharArray(adapterName);
@@ -179,7 +170,6 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
--i;
}
}
- connectionProfiles->Release();
return interfaces;
}
diff --git a/src/network/network.pro b/src/network/network.pro
index 79e357e0cb..4cced923f7 100644
--- a/src/network/network.pro
+++ b/src/network/network.pro
@@ -25,3 +25,14 @@ include(socket/socket.pri)
include(ssl/ssl.pri)
QMAKE_LIBS += $$QMAKE_LIBS_NETWORK
+
+ANDROID_BUNDLED_JAR_DEPENDENCIES = \
+ jar/QtAndroidBearer-bundled.jar
+ANDROID_JAR_DEPENDENCIES = \
+ jar/QtAndroidBearer.jar
+ANDROID_LIB_DEPENDENCIES = \
+ plugins/bearer/libqandroidbearer.so
+MODULE_PLUGIN_TYPES = \
+ bearer
+ANDROID_PERMISSIONS += \
+ android.permission.ACCESS_NETWORK_STATE
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index 65244ce9cf..472e0cb98c 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -365,7 +365,7 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt
bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 port)
{
#ifdef QNATIVESOCKETENGINE_DEBUG
- qDebug("QNativeSocketEnginePrivate::nativeConnect() : %lli", socketDescriptor);
+ qDebug() << "QNativeSocketEnginePrivate::nativeConnect() " << socketDescriptor;
#endif
struct sockaddr_in sockAddrIPv4;
@@ -405,6 +405,9 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16
}
int connectResult = qt_safe_connect(socketDescriptor, sockAddrPtr, sockAddrSize);
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ int ecopy = errno;
+#endif
if (connectResult == -1) {
switch (errno) {
case EISCONN:
@@ -456,7 +459,7 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16
qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)",
addr.toString().toLatin1().constData(), port,
socketState == QAbstractSocket::ConnectingState
- ? "Connection in progress" : socketErrorString.toLatin1().constData());
+ ? "Connection in progress" : strerror(ecopy));
#endif
return false;
}
@@ -524,6 +527,9 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16
}
if (bindResult < 0) {
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ int ecopy = errno;
+#endif
switch(errno) {
case EADDRINUSE:
setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString);
@@ -543,7 +549,7 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16
#if defined (QNATIVESOCKETENGINE_DEBUG)
qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)",
- address.toString().toLatin1().constData(), port, socketErrorString.toLatin1().constData());
+ address.toString().toLatin1().constData(), port, strerror(ecopy));
#endif
return false;
@@ -563,6 +569,9 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16
bool QNativeSocketEnginePrivate::nativeListen(int backlog)
{
if (qt_safe_listen(socketDescriptor, backlog) < 0) {
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ int ecopy = errno;
+#endif
switch (errno) {
case EADDRINUSE:
setError(QAbstractSocket::AddressInUseError,
@@ -574,7 +583,7 @@ bool QNativeSocketEnginePrivate::nativeListen(int backlog)
#if defined (QNATIVESOCKETENGINE_DEBUG)
qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == false (%s)",
- backlog, socketErrorString.toLatin1().constData());
+ backlog, strerror(ecopy));
#endif
return false;
}
diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp
index 1646940cb8..ab6c2a6590 100644
--- a/src/network/socket/qnativesocketengine_winrt.cpp
+++ b/src/network/socket/qnativesocketengine_winrt.cpp
@@ -477,16 +477,15 @@ void QNativeSocketEngine::close()
{
Q_D(QNativeSocketEngine);
if (d->socketDescriptor != -1) {
- IClosable *socket = 0;
+ ComPtr<IClosable> socket;
if (d->socketType == QAbstractSocket::TcpSocket && d->tcp)
- d->tcp->QueryInterface(IID_PPV_ARGS(&socket));
+ d->tcp.As(&socket);
else if (d->socketType == QAbstractSocket::UdpSocket && d->udp)
- d->udp->QueryInterface(IID_PPV_ARGS(&socket));
+ d->udp.As(&socket);
if (socket) {
d->closingDown = true;
socket->Close();
- socket->Release();
d->socketDescriptor = -1;
}
d->socketDescriptor = -1;
@@ -624,11 +623,10 @@ qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress
*addr = returnAddress;
*port = returnPort;
arg = d->pendingDatagrams.takeFirst();
+ arg->Release();
// TODO: fill data
Q_UNUSED(data);
- arg->Release();
- delete arg;
--i;
return maxlen;
}
@@ -833,8 +831,8 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
SocketHandler *handler = gSocketHandler();
switch (socketType) {
case QAbstractSocket::TcpSocket: {
- if (FAILED(RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_StreamSocket).Get(),
- reinterpret_cast<IInspectable **>(&tcp)))) {
+ HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_StreamSocket).Get(), &tcp);
+ if (FAILED(hr)) {
qWarning("Failed to create StreamSocket instance");
return false;
}
@@ -842,8 +840,8 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
return true;
}
case QAbstractSocket::UdpSocket: {
- if (FAILED(RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_DatagramSocket).Get(),
- reinterpret_cast<IInspectable **>(&udp)))) {
+ HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_DatagramSocket).Get(), &udp);
+ if (FAILED(hr)) {
qWarning("Failed to create stream socket");
return false;
}
@@ -1256,7 +1254,7 @@ HRESULT QNativeSocketEnginePrivate::handleWriteCompleted(IAsyncOperationWithProg
HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, IDatagramSocketMessageReceivedEventArgs *args)
{
Q_Q(QNativeSocketEngine);
- Q_UNUSED(socket)
+ Q_UNUSED(socket);
pendingDatagrams.append(args);
emit q->readReady();
diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h
index ec2e1b3ad4..bf23faeb45 100644
--- a/src/network/socket/qnativesocketengine_winrt_p.h
+++ b/src/network/socket/qnativesocketengine_winrt_p.h
@@ -193,10 +193,8 @@ public:
bool checkProxy(const QHostAddress &address);
bool fetchConnectionParameters();
private:
- union {
- ABI::Windows::Networking::Sockets::IStreamSocket *tcp;
- ABI::Windows::Networking::Sockets::IDatagramSocket *udp;
- };
+ Microsoft::WRL::ComPtr<ABI::Windows::Networking::Sockets::IStreamSocket> tcp;
+ Microsoft::WRL::ComPtr<ABI::Windows::Networking::Sockets::IDatagramSocket> udp;
Microsoft::WRL::ComPtr<ABI::Windows::Networking::Sockets::IStreamSocketListener> tcpListener;
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IBuffer> readBuffer;
QBuffer readBytes;
diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp
index a113ec156b..4b71f34b3a 100644
--- a/src/network/ssl/qsslcertificate.cpp
+++ b/src/network/ssl/qsslcertificate.cpp
@@ -265,6 +265,22 @@ bool QSslCertificate::isBlacklisted() const
}
/*!
+ \since 5.4
+ Returns \c true if this certificate is self signed; otherwise
+ returns \c false.
+
+ A certificate is considered self-signed its issuer and subject
+ are identical.
+*/
+bool QSslCertificate::isSelfSigned() const
+{
+ if (!d->x509)
+ return false;
+
+ return (q_X509_check_issued(d->x509, d->x509) == X509_V_OK);
+}
+
+/*!
Clears the contents of this certificate, making it a null
certificate.
@@ -963,6 +979,26 @@ QList<QSslError> QSslCertificate::verify(QList<QSslCertificate> certificateChain
return QSslSocketBackendPrivate::verify(certificateChain, hostName);
}
+/*!
+ \since 5.4
+
+ Imports a PKCS#12 (pfx) file from the specified \a device. A PKCS#12
+ file is a bundle that can contain a number of certificates and keys.
+ This method reads a single \a key, its \a certificate and any
+ associated \a caCertificates from the bundle. If a \a passPhrase is
+ specified then this will be used to decrypt the bundle. Returns
+ \c true if the PKCS#12 file was successfully loaded.
+
+ \note The \a device must be open and ready to be read from.
+ */
+bool QSslCertificate::importPKCS12(QIODevice *device,
+ QSslKey *key, QSslCertificate *certificate,
+ QList<QSslCertificate> *caCertificates,
+ const QByteArray &passPhrase)
+{
+ return QSslSocketBackendPrivate::importPKCS12(device, key, certificate, caCertificates, passPhrase);
+}
+
void QSslCertificatePrivate::init(const QByteArray &data, QSsl::EncodingFormat format)
{
if (!data.isEmpty()) {
diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h
index 988071eb9d..2217eb7fb9 100644
--- a/src/network/ssl/qsslcertificate.h
+++ b/src/network/ssl/qsslcertificate.h
@@ -105,6 +105,7 @@ public:
}
#endif
bool isBlacklisted() const;
+ bool isSelfSigned() const;
void clear();
// Certificate info
@@ -141,6 +142,11 @@ public:
static QList<QSslError> verify(QList<QSslCertificate> certificateChain, const QString &hostName = QString());
+ static bool importPKCS12(QIODevice *device,
+ QSslKey *key, QSslCertificate *cert,
+ QList<QSslCertificate> *caCertificates=0,
+ const QByteArray &passPhrase=QByteArray());
+
Qt::HANDLE handle() const;
private:
diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp
index 14881931af..64b75f98ec 100644
--- a/src/network/ssl/qsslconfiguration.cpp
+++ b/src/network/ssl/qsslconfiguration.cpp
@@ -208,6 +208,7 @@ bool QSslConfiguration::operator==(const QSslConfiguration &other) const
d->localCertificateChain == other.d->localCertificateChain &&
d->privateKey == other.d->privateKey &&
d->sessionCipher == other.d->sessionCipher &&
+ d->sessionProtocol == other.d->sessionProtocol &&
d->ciphers == other.d->ciphers &&
d->caCertificates == other.d->caCertificates &&
d->protocol == other.d->protocol &&
@@ -512,6 +513,18 @@ QSslCipher QSslConfiguration::sessionCipher() const
}
/*!
+ Returns the socket's SSL/TLS protocol or UnknownProtocol if the
+ connection isn't encrypted. The socket's protocol for the session
+ is set during the handshake phase.
+
+ \sa protocol(), setProtocol()
+*/
+QSsl::SslProtocol QSslConfiguration::sessionProtocol() const
+{
+ return d->sessionProtocol;
+}
+
+/*!
Returns the \l {QSslKey} {SSL key} assigned to this connection or
a null key if none has been assigned yet.
diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h
index 587187ca06..4c5799bf28 100644
--- a/src/network/ssl/qsslconfiguration.h
+++ b/src/network/ssl/qsslconfiguration.h
@@ -109,6 +109,7 @@ public:
QSslCertificate peerCertificate() const;
QList<QSslCertificate> peerCertificateChain() const;
QSslCipher sessionCipher() const;
+ QSsl::SslProtocol sessionProtocol() const;
// Private keys, for server sockets
QSslKey privateKey() const;
diff --git a/src/network/ssl/qsslconfiguration_p.h b/src/network/ssl/qsslconfiguration_p.h
index d183c3335c..29bd4053ad 100644
--- a/src/network/ssl/qsslconfiguration_p.h
+++ b/src/network/ssl/qsslconfiguration_p.h
@@ -81,7 +81,8 @@ class QSslConfigurationPrivate: public QSharedData
{
public:
QSslConfigurationPrivate()
- : protocol(QSsl::SecureProtocols),
+ : sessionProtocol(QSsl::UnknownProtocol),
+ protocol(QSsl::SecureProtocols),
peerVerifyMode(QSslSocket::AutoVerifyPeer),
peerVerifyDepth(0),
allowRootCertOnDemandLoading(true),
@@ -98,6 +99,7 @@ public:
QSslKey privateKey;
QSslCipher sessionCipher;
+ QSsl::SslProtocol sessionProtocol;
QList<QSslCipher> ciphers;
QList<QSslCertificate> caCertificates;
diff --git a/src/network/ssl/qsslkey.cpp b/src/network/ssl/qsslkey.cpp
index 95eed6e4b3..b43e28589f 100644
--- a/src/network/ssl/qsslkey.cpp
+++ b/src/network/ssl/qsslkey.cpp
@@ -96,6 +96,38 @@ void QSslKeyPrivate::clear(bool deep)
}
}
+bool QSslKeyPrivate::fromEVP_PKEY(EVP_PKEY *pkey)
+{
+ if (pkey->type == 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));
+
+ return true;
+ }
+ else if (pkey->type == EVP_PKEY_DSA) {
+ isNull = false;
+ algorithm = QSsl::Dsa;
+ type = QSsl::PrivateKey;
+
+ dsa = q_DSA_new();
+ memcpy(rsa, q_EVP_PKEY_get1_DSA(pkey), sizeof(DSA));
+
+ return true;
+ }
+ else {
+ // Unknown key type. This could be handled as opaque, but then
+ // we'd eventually leak memory since we wouldn't be able to free
+ // the underlying EVP_PKEY structure. For now, we won't support
+ // this.
+ }
+
+ return false;
+}
+
/*!
\internal
diff --git a/src/network/ssl/qsslkey.h b/src/network/ssl/qsslkey.h
index 145d4a28f1..59063e2e57 100644
--- a/src/network/ssl/qsslkey.h
+++ b/src/network/ssl/qsslkey.h
@@ -95,6 +95,7 @@ public:
private:
QExplicitlySharedDataPointer<QSslKeyPrivate> d;
friend class QSslCertificate;
+ friend class QSslSocketBackendPrivate;
};
Q_DECLARE_SHARED(QSslKey)
diff --git a/src/network/ssl/qsslkey_p.h b/src/network/ssl/qsslkey_p.h
index 54d12d76fb..658be85621 100644
--- a/src/network/ssl/qsslkey_p.h
+++ b/src/network/ssl/qsslkey_p.h
@@ -79,6 +79,7 @@ public:
void clear(bool deep = true);
+ bool fromEVP_PKEY(EVP_PKEY *pkey);
void decodePem(const QByteArray &pem, const QByteArray &passPhrase,
bool deepClear = true);
QByteArray pemHeader() const;
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index 90f6e25b97..8fd9114b2e 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -880,6 +880,7 @@ QSslConfiguration QSslSocket::sslConfiguration() const
QSslConfigurationPrivate *copy = new QSslConfigurationPrivate(d->configuration);
copy->ref.store(0); // the QSslConfiguration constructor refs up
copy->sessionCipher = d->sessionCipher();
+ copy->sessionProtocol = d->sessionProtocol();
return QSslConfiguration(copy);
}
@@ -1075,6 +1076,20 @@ QSslCipher QSslSocket::sessionCipher() const
}
/*!
+ Returns the socket's SSL/TLS protocol or UnknownProtocol if the
+ connection isn't encrypted. The socket's protocol for the session
+ is set during the handshake phase.
+
+ \sa protocol(), setProtocol()
+*/
+QSsl::SslProtocol QSslSocket::sessionProtocol() const
+{
+ Q_D(const QSslSocket);
+ return d->sessionProtocol();
+}
+
+
+/*!
Sets the socket's private \l {QSslKey} {key} to \a key. The
private key and the local \l {QSslCertificate} {certificate} are
used by clients and servers that must prove their identity to
@@ -1667,6 +1682,32 @@ QString QSslSocket::sslLibraryVersionString()
}
/*!
+ \since 5.4
+ Returns the version number of the SSL library in use at compile
+ time. If no SSL support is available then this will return an
+ undefined value.
+
+ \sa sslLibraryVersionNumber()
+*/
+long QSslSocket::sslLibraryBuildVersionNumber()
+{
+ return QSslSocketPrivate::sslLibraryBuildVersionNumber();
+}
+
+/*!
+ \since 5.4
+ Returns the version string of the SSL library in use at compile
+ time. If no SSL support is available then this will return an
+ empty value.
+
+ \sa sslLibraryVersionString()
+*/
+QString QSslSocket::sslLibraryBuildVersionString()
+{
+ return QSslSocketPrivate::sslLibraryBuildVersionString();
+}
+
+/*!
Starts a delayed SSL handshake for a client connection. This
function can be called when the socket is in the \l ConnectedState
but still in the \l UnencryptedMode. If it is not yet connected,
@@ -2098,6 +2139,7 @@ void QSslConfigurationPrivate::deepCopyDefaultConfiguration(QSslConfigurationPri
ptr->localCertificateChain = global->localCertificateChain;
ptr->privateKey = global->privateKey;
ptr->sessionCipher = global->sessionCipher;
+ ptr->sessionProtocol = global->sessionProtocol;
ptr->ciphers = global->ciphers;
ptr->caCertificates = global->caCertificates;
ptr->protocol = global->protocol;
diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h
index d89933efda..9cc5e02de3 100644
--- a/src/network/ssl/qsslsocket.h
+++ b/src/network/ssl/qsslsocket.h
@@ -140,6 +140,7 @@ public:
QSslCertificate peerCertificate() const;
QList<QSslCertificate> peerCertificateChain() const;
QSslCipher sessionCipher() const;
+ QSsl::SslProtocol sessionProtocol() const;
// Private keys, for server sockets.
void setPrivateKey(const QSslKey &key);
@@ -182,6 +183,8 @@ public:
static bool supportsSsl();
static long sslLibraryVersionNumber();
static QString sslLibraryVersionString();
+ static long sslLibraryBuildVersionNumber();
+ static QString sslLibraryBuildVersionString();
void ignoreSslErrors(const QList<QSslError> &errors);
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 0315749cb3..f869039687 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -62,6 +62,7 @@
#include "qsslsocket.h"
#include "qsslcertificate_p.h"
#include "qsslcipher_p.h"
+#include "qsslkey_p.h"
#include <QtCore/qdatetime.h>
#include <QtCore/qdebug.h>
@@ -585,6 +586,16 @@ QString QSslSocketPrivate::sslLibraryVersionString()
return QString::fromLatin1(versionString);
}
+long QSslSocketPrivate::sslLibraryBuildVersionNumber()
+{
+ return OPENSSL_VERSION_NUMBER;
+}
+
+QString QSslSocketPrivate::sslLibraryBuildVersionString()
+{
+ return QLatin1String(OPENSSL_VERSION_TEXT);
+}
+
/*!
\internal
@@ -1429,6 +1440,28 @@ QSslCipher QSslSocketBackendPrivate::sessionCipher() const
return sessionCipher ? QSslCipher_from_SSL_CIPHER(sessionCipher) : QSslCipher();
}
+QSsl::SslProtocol QSslSocketBackendPrivate::sessionProtocol() const
+{
+ if (!ssl)
+ return QSsl::UnknownProtocol;
+ int ver = q_SSL_version(ssl);
+
+ switch (ver) {
+ case 0x2:
+ return QSsl::SslV2;
+ case 0x300:
+ return QSsl::SslV3;
+ case 0x301:
+ return QSsl::TlsV1_0;
+ case 0x302:
+ return QSsl::TlsV1_1;
+ case 0x303:
+ return QSsl::TlsV1_2;
+ }
+
+ return QSsl::UnknownProtocol;
+}
+
void QSslSocketBackendPrivate::continueHandshake()
{
Q_Q(QSslSocket);
@@ -1703,4 +1736,72 @@ QList<QSslError> QSslSocketBackendPrivate::verify(QList<QSslCertificate> certifi
return errors;
}
+bool QSslSocketBackendPrivate::importPKCS12(QIODevice *device,
+ QSslKey *key, QSslCertificate *cert,
+ QList<QSslCertificate> *caCertificates,
+ const QByteArray &passPhrase)
+{
+ if (!supportsSsl())
+ return false;
+
+ // These are required
+ Q_ASSERT(device);
+ Q_ASSERT(key);
+ Q_ASSERT(cert);
+
+ // Read the file into a BIO
+ QByteArray pkcs12data = device->readAll();
+ if (pkcs12data.size() == 0)
+ return false;
+
+ BIO *bio = q_BIO_new_mem_buf(const_cast<char *>(pkcs12data.constData()), pkcs12data.size());
+
+ // Create the PKCS#12 object
+ PKCS12 *p12 = q_d2i_PKCS12_bio(bio, 0);
+ if (!p12) {
+ qWarning("Unable to read PKCS#12 structure, %s", q_ERR_error_string(q_ERR_get_error(), 0));
+ q_BIO_free(bio);
+ return false;
+ }
+
+ // Extract the data
+ EVP_PKEY *pkey;
+ X509 *x509;
+ STACK_OF(X509) *ca = 0;
+
+ if (!q_PKCS12_parse(p12, passPhrase.constData(), &pkey, &x509, &ca)) {
+ qWarning("Unable to parse PKCS#12 structure, %s", q_ERR_error_string(q_ERR_get_error(), 0));
+ q_PKCS12_free(p12);
+ q_BIO_free(bio);
+ return false;
+ }
+
+ // Convert to Qt types
+ if (!key->d->fromEVP_PKEY(pkey)) {
+ qWarning("Unable to convert private key");
+ q_sk_pop_free(reinterpret_cast<STACK *>(ca), reinterpret_cast<void(*)(void*)>(q_sk_free));
+ q_X509_free(x509);
+ q_EVP_PKEY_free(pkey);
+ q_PKCS12_free(p12);
+ q_BIO_free(bio);
+
+ return false;
+ }
+
+ *cert = QSslCertificatePrivate::QSslCertificate_from_X509(x509);
+
+ if (caCertificates)
+ *caCertificates = QSslSocketBackendPrivate::STACKOFX509_to_QSslCertificates(ca);
+
+ // Clean up
+ q_sk_pop_free(reinterpret_cast<STACK *>(ca), reinterpret_cast<void(*)(void*)>(q_sk_free));
+ q_X509_free(x509);
+ q_EVP_PKEY_free(pkey);
+ q_PKCS12_free(p12);
+ q_BIO_free(bio);
+
+ return true;
+}
+
+
QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h
index c8b23e6cad..f4f2fe842c 100644
--- a/src/network/ssl/qsslsocket_openssl_p.h
+++ b/src/network/ssl/qsslsocket_openssl_p.h
@@ -131,6 +131,7 @@ public:
void disconnectFromHost();
void disconnected();
QSslCipher sessionCipher() const;
+ QSsl::SslProtocol sessionProtocol() const;
void continueHandshake();
bool checkSslErrors();
#ifdef Q_OS_WIN
@@ -145,6 +146,10 @@ public:
Q_AUTOTEST_EXPORT static bool isMatchingHostname(const QString &cn, const QString &hostname);
static QList<QSslError> verify(QList<QSslCertificate> certificateChain, const QString &hostName);
static QString getErrorsFromOpenSsl();
+ static bool importPKCS12(QIODevice *device,
+ QSslKey *key, QSslCertificate *cert,
+ QList<QSslCertificate> *caCertificates,
+ const QByteArray &passPhrase);
};
#ifdef Q_OS_WIN
diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
index 4e6200f880..6f22ab726f 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -146,6 +146,7 @@ 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)
#if OPENSSL_VERSION_NUMBER < 0x00908000L
DEFINEFUNC3(X509 *, d2i_X509, X509 **a, a, unsigned char **b, b, long c, c, return 0, return)
@@ -186,6 +187,7 @@ DEFINEFUNC2(int, PEM_write_bio_DSA_PUBKEY, BIO *a, a, DSA *b, b, return 0, retur
DEFINEFUNC2(int, PEM_write_bio_RSA_PUBKEY, BIO *a, a, RSA *b, b, return 0, return)
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)
@@ -239,6 +241,7 @@ DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, retu
#else
DEFINEFUNC(SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, return)
#endif
+DEFINEFUNC(int, SSL_version, const SSL *a, a, return 0, return)
DEFINEFUNC2(int, SSL_get_error, SSL *a, a, int b, b, return -1, return)
DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return 0, return)
DEFINEFUNC(X509 *, SSL_get_peer_certificate, SSL *a, a, return 0, return)
@@ -316,6 +319,7 @@ DEFINEFUNC2(int, ASN1_STRING_print, BIO *a, a, const ASN1_STRING *b, b, return 0
#else
DEFINEFUNC2(int, ASN1_STRING_print, BIO *a, a, ASN1_STRING *b, b, return 0, return)
#endif
+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(int, X509_verify_cert, X509_STORE_CTX *a, a, return -1, return)
@@ -370,6 +374,11 @@ DEFINEFUNC(EC_KEY *, EC_KEY_new_by_curve_name, int nid, nid, return 0, return)
DEFINEFUNC(void, EC_KEY_free, EC_KEY *ecdh, ecdh, return, DUMMYARG)
#endif // OPENSSL_NO_EC
+DEFINEFUNC5(int, PKCS12_parse, PKCS12 *p12, p12, const char *pass, pass, EVP_PKEY **pkey, pkey, \
+ X509 **cert, cert, STACK_OF(X509) **ca, ca, return 1, return);
+DEFINEFUNC2(PKCS12 *, d2i_PKCS12_bio, BIO *bio, bio, PKCS12 **pkcs12, pkcs12, return 0, return);
+DEFINEFUNC(void, PKCS12_free, PKCS12 *pkcs12, pkcs12, return, DUMMYARG)
+
#define RESOLVEFUNC(func) \
if (!(_q_##func = _q_PTR_##func(libs.first->resolve(#func))) \
&& !(_q_##func = _q_PTR_##func(libs.second->resolve(#func)))) \
@@ -688,6 +697,7 @@ bool q_resolveOpenSslSymbols()
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)
@@ -720,6 +730,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(PEM_write_bio_RSA_PUBKEY)
RESOLVEFUNC(RAND_seed)
RESOLVEFUNC(RAND_status)
+ RESOLVEFUNC(RSA_new)
RESOLVEFUNC(RSA_free)
RESOLVEFUNC(sk_new_null)
RESOLVEFUNC(sk_push)
@@ -748,6 +759,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(SSL_free)
RESOLVEFUNC(SSL_get_ciphers)
RESOLVEFUNC(SSL_get_current_cipher)
+ RESOLVEFUNC(SSL_version)
RESOLVEFUNC(SSL_get_error)
RESOLVEFUNC(SSL_get_peer_cert_chain)
RESOLVEFUNC(SSL_get_peer_certificate)
@@ -821,6 +833,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(BASIC_CONSTRAINTS_free)
RESOLVEFUNC(AUTHORITY_KEYID_free)
RESOLVEFUNC(ASN1_STRING_print)
+ RESOLVEFUNC(X509_check_issued)
RESOLVEFUNC(X509_get_issuer_name)
RESOLVEFUNC(X509_get_subject_name)
RESOLVEFUNC(X509_verify_cert)
@@ -851,6 +864,9 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(EC_KEY_new_by_curve_name)
RESOLVEFUNC(EC_KEY_free)
#endif // OPENSSL_NO_EC
+ RESOLVEFUNC(PKCS12_parse)
+ RESOLVEFUNC(d2i_PKCS12_bio)
+ RESOLVEFUNC(PKCS12_free)
symbolsResolved = true;
delete libs.first;
diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h
index 68f5709b93..66f45f4706 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols_p.h
+++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h
@@ -233,6 +233,7 @@ 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);
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
// 0.9.8 broke SC and BC by changing this function's signature.
@@ -277,6 +278,7 @@ int q_PEM_write_bio_DSA_PUBKEY(BIO *a, DSA *b);
int q_PEM_write_bio_RSA_PUBKEY(BIO *a, RSA *b);
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 *));
@@ -330,6 +332,7 @@ const SSL_CIPHER *q_SSL_get_current_cipher(SSL *a);
#else
SSL_CIPHER *q_SSL_get_current_cipher(SSL *a);
#endif
+int q_SSL_version(const SSL *a);
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);
@@ -407,6 +410,7 @@ int q_ASN1_STRING_print(BIO *a, const ASN1_STRING *b);
#else
int q_ASN1_STRING_print(BIO *a, ASN1_STRING *b);
#endif
+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);
int q_X509_verify_cert(X509_STORE_CTX *ctx);
@@ -441,6 +445,12 @@ void q_EC_KEY_free(EC_KEY *ecdh);
#define q_SSL_CTX_set_tmp_ecdh(ctx, ecdh) q_SSL_CTX_ctrl((ctx), SSL_CTRL_SET_TMP_ECDH, 0, (char *)ecdh)
#endif // OPENSSL_NO_EC
+// PKCS#12 support
+int q_PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca);
+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
diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h
index 6281753225..0033a46d98 100644
--- a/src/network/ssl/qsslsocket_p.h
+++ b/src/network/ssl/qsslsocket_p.h
@@ -129,6 +129,8 @@ public:
static bool supportsSsl();
static long sslLibraryVersionNumber();
static QString sslLibraryVersionString();
+ static long sslLibraryBuildVersionNumber();
+ static QString sslLibraryBuildVersionString();
static void ensureInitialized();
static void deinitialize();
static QList<QSslCipher> defaultCiphers();
@@ -190,6 +192,7 @@ public:
virtual void disconnectFromHost() = 0;
virtual void disconnected() = 0;
virtual QSslCipher sessionCipher() const = 0;
+ virtual QSsl::SslProtocol sessionProtocol() const = 0;
virtual void continueHandshake() = 0;
Q_AUTOTEST_EXPORT static bool rootCertOnDemandLoadingSupported();
diff --git a/src/opengl/gl2paintengineex/qglgradientcache.cpp b/src/opengl/gl2paintengineex/qglgradientcache.cpp
index 6160554472..d2b6842a8a 100644
--- a/src/opengl/gl2paintengineex/qglgradientcache.cpp
+++ b/src/opengl/gl2paintengineex/qglgradientcache.cpp
@@ -89,11 +89,12 @@ void QGL2GradientCache::freeResource(QOpenGLContext *)
void QGL2GradientCache::cleanCache()
{
+ QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
QMutexLocker lock(&m_mutex);
QGLGradientColorTableHash::const_iterator it = cache.constBegin();
for (; it != cache.constEnd(); ++it) {
const CacheInfo &cache_info = it.value();
- glDeleteTextures(1, &cache_info.texId);
+ funcs->glDeleteTextures(1, &cache_info.texId);
}
cache.clear();
}
@@ -129,6 +130,7 @@ GLuint QGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity)
GLuint QGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity)
{
+ QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
if (cache.size() == maxCacheSize()) {
int elem_to_remove = qrand() % maxCacheSize();
quint64 key = cache.keys()[elem_to_remove];
@@ -136,7 +138,7 @@ GLuint QGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient &gra
// need to call glDeleteTextures on each removed cache entry:
QGLGradientColorTableHash::const_iterator it = cache.constFind(key);
do {
- glDeleteTextures(1, &it.value().texId);
+ funcs->glDeleteTextures(1, &it.value().texId);
} while (++it != cache.constEnd() && it.key() == key);
cache.remove(key); // may remove more than 1, but OK
}
@@ -144,10 +146,10 @@ GLuint QGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient &gra
CacheInfo cache_entry(gradient.stops(), opacity, gradient.interpolationMode());
uint buffer[1024];
generateGradientColorTable(gradient, buffer, paletteSize(), opacity);
- glGenTextures(1, &cache_entry.texId);
- glBindTexture(GL_TEXTURE_2D, cache_entry.texId);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, paletteSize(), 1,
- 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+ funcs->glGenTextures(1, &cache_entry.texId);
+ funcs->glBindTexture(GL_TEXTURE_2D, cache_entry.texId);
+ funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, paletteSize(), 1,
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
return cache.insert(hash_val, cache_entry).value().texId;
}
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 5d4ca42dc2..5045d4a2ae 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -86,6 +86,10 @@
#include <QDebug>
+#ifndef QT_OPENGL_ES_2
+# include <qopenglfunctions_1_1.h>
+#endif
+
QT_BEGIN_NAMESPACE
@@ -106,7 +110,7 @@ QGL2PaintEngineExPrivate::~QGL2PaintEngineExPrivate()
}
if (elementIndicesVBOId != 0) {
- funcs.glDeleteBuffers(1, &elementIndicesVBOId);
+ glDeleteBuffers(1, &elementIndicesVBOId);
elementIndicesVBOId = 0;
}
}
@@ -193,7 +197,7 @@ void QGL2PaintEngineExPrivate::updateBrushTexture()
// Get the image data for the pattern
QImage texImage = qt_imageForBrush(style, false);
- funcs.glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
+ glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
ctx->d_func()->bindTexture(texImage, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption);
updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform);
}
@@ -206,7 +210,7 @@ void QGL2PaintEngineExPrivate::updateBrushTexture()
// for opacity to the cache.
GLuint texId = QGL2GradientCache::cacheForContext(ctx)->getBuffer(*g, 1.0);
- funcs.glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
+ glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
glBindTexture(GL_TEXTURE_2D, texId);
if (g->spread() == QGradient::RepeatSpread || g->type() == QGradient::ConicalGradient)
@@ -231,7 +235,7 @@ void QGL2PaintEngineExPrivate::updateBrushTexture()
wrapMode = GL_CLAMP_TO_EDGE;
}
- funcs.glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
+ glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
QGLTexture *tex = ctx->d_func()->bindTexture(currentBrushPixmap, GL_TEXTURE_2D, GL_RGBA,
QGLContext::InternalBindOption |
QGLContext::CanFlipNativePixmapBindOption);
@@ -428,9 +432,9 @@ void QGL2PaintEngineExPrivate::updateMatrix()
// Set the PMV matrix attribute. As we use an attributes rather than uniforms, we only
// need to do this once for every matrix change and persists across all shader programs.
- funcs.glVertexAttrib3fv(QT_PMV_MATRIX_1_ATTR, pmvMatrix[0]);
- funcs.glVertexAttrib3fv(QT_PMV_MATRIX_2_ATTR, pmvMatrix[1]);
- funcs.glVertexAttrib3fv(QT_PMV_MATRIX_3_ATTR, pmvMatrix[2]);
+ glVertexAttrib3fv(QT_PMV_MATRIX_1_ATTR, pmvMatrix[0]);
+ glVertexAttrib3fv(QT_PMV_MATRIX_2_ATTR, pmvMatrix[1]);
+ glVertexAttrib3fv(QT_PMV_MATRIX_3_ATTR, pmvMatrix[2]);
dasher.setInvScale(inverseScale);
stroker.setInvScale(inverseScale);
@@ -540,11 +544,11 @@ void QGL2PaintEngineEx::beginNativePainting()
d->nativePaintingActive = true;
- d->funcs.glUseProgram(0);
+ d->glUseProgram(0);
// Disable all the vertex attribute arrays:
for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i)
- d->funcs.glDisableVertexAttribArray(i);
+ d->glDisableVertexAttribArray(i);
#ifndef QT_OPENGL_ES_2
if (!d->ctx->contextHandle()->isOpenGLES()) {
@@ -569,12 +573,15 @@ void QGL2PaintEngineEx::beginNativePainting()
const QSize sz = d->device->size();
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0, sz.width(), sz.height(), 0, -999999, 999999);
+ QOpenGLFunctions_1_1 *gl1funcs = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_1_1>();
+ gl1funcs->initializeOpenGLFunctions();
- glMatrixMode(GL_MODELVIEW);
- glLoadMatrixf(&mv_matrix[0][0]);
+ gl1funcs->glMatrixMode(GL_PROJECTION);
+ gl1funcs->glLoadIdentity();
+ gl1funcs->glOrtho(0, sz.width(), sz.height(), 0, -999999, 999999);
+
+ gl1funcs->glMatrixMode(GL_MODELVIEW);
+ gl1funcs->glLoadMatrixf(&mv_matrix[0][0]);
}
}
#endif
@@ -591,13 +598,13 @@ void QGL2PaintEngineEx::beginNativePainting()
void QGL2PaintEngineExPrivate::resetGLState()
{
glDisable(GL_BLEND);
- funcs.glActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE0);
glDisable(GL_STENCIL_TEST);
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
glDepthMask(true);
glDepthFunc(GL_LESS);
- funcs.glClearDepthf(1);
+ glClearDepthf(1);
glStencilMask(0xff);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_ALWAYS, 0, 0xff);
@@ -608,7 +615,7 @@ void QGL2PaintEngineExPrivate::resetGLState()
if (!ctx->contextHandle()->isOpenGLES()) {
// gl_Color, corresponding to vertex attribute 3, may have been changed
float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
- funcs.glVertexAttrib4fv(3, color);
+ glVertexAttrib4fv(3, color);
}
#endif
}
@@ -758,7 +765,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
qreal scaleFactor = cache->iscale / inverseScale;
if (scaleFactor < 0.5 || scaleFactor > 2.0) {
#ifdef QT_OPENGL_CACHE_AS_VBOS
- funcs.glDeleteBuffers(1, &cache->vbo);
+ glDeleteBuffers(1, &cache->vbo);
cache->vbo = 0;
Q_ASSERT(cache->ibo == 0);
#else
@@ -785,9 +792,9 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
cache->primitiveType = GL_TRIANGLE_FAN;
cache->iscale = inverseScale;
#ifdef QT_OPENGL_CACHE_AS_VBOS
- funcs.glGenBuffers(1, &cache->vbo);
- funcs.glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
- funcs.glBufferData(GL_ARRAY_BUFFER, floatSizeInBytes, vertexCoordinateArray.data(), GL_STATIC_DRAW);
+ glGenBuffers(1, &cache->vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
+ glBufferData(GL_ARRAY_BUFFER, floatSizeInBytes, vertexCoordinateArray.data(), GL_STATIC_DRAW);
cache->ibo = 0;
#else
cache->vertices = (float *) malloc(floatSizeInBytes);
@@ -798,7 +805,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
prepareForDraw(currentBrush.isOpaque());
#ifdef QT_OPENGL_CACHE_AS_VBOS
- funcs.glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, 0);
#else
setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, cache->vertices);
@@ -1024,9 +1031,9 @@ void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(const float *data,
}
// Inc. for front-facing triangle
- funcs.glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_INCR_WRAP);
+ glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_INCR_WRAP);
// Dec. for back-facing "holes"
- funcs.glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_DECR_WRAP);
+ glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_DECR_WRAP);
glStencilMask(~GL_STENCIL_HIGH_BIT);
drawVertexArrays(data, stops, stopCount, GL_TRIANGLE_FAN);
@@ -1375,9 +1382,9 @@ void QGL2PaintEngineEx::renderHintsChanged()
if (!d->ctx->contextHandle()->isOpenGLES()) {
if ((state()->renderHints & QPainter::Antialiasing)
|| (state()->renderHints & QPainter::HighQualityAntialiasing))
- glEnable(GL_MULTISAMPLE);
+ d->glEnable(GL_MULTISAMPLE);
else
- glDisable(GL_MULTISAMPLE);
+ d->glDisable(GL_MULTISAMPLE);
}
#endif
@@ -1423,7 +1430,7 @@ void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, c
bindOptions |= QGLContext::TemporarilyCachedBindOption;
#endif
- d->funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
+ d->glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
QGLTexture *texture =
ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, bindOptions);
@@ -1465,7 +1472,7 @@ void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const
ensureActive();
d->transferMode(ImageDrawingMode);
- d->funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
+ d->glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
QGLContext::BindOptions bindOptions = QGLContext::InternalBindOption;
#ifdef QGL_USE_TEXTURE_POOL
@@ -1526,8 +1533,8 @@ bool QGL2PaintEngineEx::drawTexture(const QRectF &dest, GLuint textureId, const
ensureActive();
d->transferMode(ImageDrawingMode);
- d->funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
- glBindTexture(GL_TEXTURE_2D, textureId);
+ d->glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
+ d->glBindTexture(GL_TEXTURE_2D, textureId);
QGLRect srcRect(src.left(), src.bottom(), src.right(), src.top());
@@ -1812,7 +1819,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFo
glEnable(GL_BLEND);
glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR);
- funcs.glBlendColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
+ glBlendColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
} else {
// Other brush styles need two passes.
@@ -1829,7 +1836,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFo
glEnable(GL_BLEND);
glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
- funcs.glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT);
+ glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT);
glBindTexture(GL_TEXTURE_2D, cache->texture());
updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
@@ -1864,7 +1871,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFo
QGLTextureGlyphCache::FilterMode filterMode = (s->matrix.type() > QTransform::TxTranslate)?QGLTextureGlyphCache::Linear:QGLTextureGlyphCache::Nearest;
if (lastMaskTextureUsed != cache->texture() || cache->filterMode() != filterMode) {
- funcs.glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT);
+ glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT);
if (lastMaskTextureUsed != cache->texture()) {
glBindTexture(GL_TEXTURE_2D, cache->texture());
lastMaskTextureUsed = cache->texture();
@@ -1965,7 +1972,7 @@ void QGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::PixmapFragmen
allOpaque &= (opacity >= 0.99f);
}
- funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
+ glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
QGLTexture *texture = ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA,
QGLContext::InternalBindOption
| QGLContext::CanFlipNativePixmapBindOption);
@@ -2039,17 +2046,17 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
// go after beginPaint:
d->device->beginPaint();
- d->funcs.initializeOpenGLFunctions();
+ d->initializeOpenGLFunctions();
d->shaderManager = new QGLEngineShaderManager(d->ctx);
- glDisable(GL_STENCIL_TEST);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_SCISSOR_TEST);
+ d->glDisable(GL_STENCIL_TEST);
+ d->glDisable(GL_DEPTH_TEST);
+ d->glDisable(GL_SCISSOR_TEST);
#if !defined(QT_OPENGL_ES_2)
if (!d->ctx->contextHandle()->isOpenGLES())
- glDisable(GL_MULTISAMPLE);
+ d->glDisable(GL_MULTISAMPLE);
#endif
d->glyphCacheFormat = QFontEngine::Format_A8;
@@ -2075,7 +2082,7 @@ bool QGL2PaintEngineEx::end()
Q_D(QGL2PaintEngineEx);
QGLContext *ctx = d->ctx;
- d->funcs.glUseProgram(0);
+ d->glUseProgram(0);
d->transferMode(BrushDrawingMode);
d->device->endPaint();
@@ -2089,11 +2096,11 @@ bool QGL2PaintEngineEx::end()
#ifdef QT_OPENGL_CACHE_AS_VBOS
if (!d->unusedVBOSToClean.isEmpty()) {
- glDeleteBuffers(d->unusedVBOSToClean.size(), d->unusedVBOSToClean.constData());
+ d->glDeleteBuffers(d->unusedVBOSToClean.size(), d->unusedVBOSToClean.constData());
d->unusedVBOSToClean.clear();
}
if (!d->unusedIBOSToClean.isEmpty()) {
- glDeleteBuffers(d->unusedIBOSToClean.size(), d->unusedIBOSToClean.constData());
+ d->glDeleteBuffers(d->unusedIBOSToClean.size(), d->unusedIBOSToClean.constData());
d->unusedIBOSToClean.clear();
}
#endif
@@ -2115,7 +2122,7 @@ void QGL2PaintEngineEx::ensureActive()
if (d->needsSync) {
d->transferMode(BrushDrawingMode);
- glViewport(0, 0, d->width, d->height);
+ d->glViewport(0, 0, d->width, d->height);
d->needsSync = false;
d->lastMaskTextureUsed = 0;
d->shaderManager->setDirty();
@@ -2436,7 +2443,7 @@ void QGL2PaintEngineEx::setState(QPainterState *new_state)
if (old_state == s || old_state->clipChanged) {
if (old_state && old_state != s && old_state->canRestoreClip) {
d->updateClipScissorTest();
- glDepthFunc(GL_LEQUAL);
+ d->glDepthFunc(GL_LEQUAL);
} else {
d->regenerateClip();
}
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
index 15ed5bc57d..e851ccac18 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
@@ -165,7 +165,7 @@ private:
Q_DISABLE_COPY(QGL2PaintEngineEx)
};
-class QGL2PaintEngineExPrivate : public QPaintEngineExPrivate
+class QGL2PaintEngineExPrivate : public QPaintEngineExPrivate, protected QOpenGLExtensions
{
Q_DECLARE_PUBLIC(QGL2PaintEngineEx)
public:
@@ -261,8 +261,6 @@ public:
EngineMode mode;
QFontEngine::GlyphFormat glyphCacheFormat;
- QOpenGLExtensions funcs;
-
// Dirty flags
bool matrixDirty; // Implies matrix uniforms are also dirty
bool compositionModeDirty;
@@ -327,9 +325,9 @@ void QGL2PaintEngineExPrivate::setVertexAttributePointer(unsigned int arrayIndex
vertexAttribPointers[arrayIndex] = pointer;
if (arrayIndex == QT_OPACITY_ATTR)
- funcs.glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, pointer);
+ glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, pointer);
else
- funcs.glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, pointer);
+ glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, pointer);
}
QT_END_NAMESPACE
diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
index f1da50a6b9..aa1d7decdb 100644
--- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
+++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
@@ -96,6 +96,7 @@ void QGLTextureGlyphCache::createTextureData(int width, int height)
qWarning("QGLTextureGlyphCache::createTextureData: Called with no context");
return;
}
+ QOpenGLFunctions *funcs = ctx->contextHandle()->functions();
// create in QImageTextureGlyphCache baseclass is meant to be called
// only to create the initial image and does not preserve the content,
@@ -117,8 +118,8 @@ void QGLTextureGlyphCache::createTextureData(int width, int height)
if (!m_textureResource)
m_textureResource = new QGLGlyphTexture(ctx);
- glGenTextures(1, &m_textureResource->m_texture);
- glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
+ funcs->glGenTextures(1, &m_textureResource->m_texture);
+ funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
m_textureResource->m_width = width;
m_textureResource->m_height = height;
@@ -127,18 +128,18 @@ void QGLTextureGlyphCache::createTextureData(int width, int height)
QVarLengthArray<uchar> data(width * height * 4);
for (int i = 0; i < data.size(); ++i)
data[i] = 0;
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
+ funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
} else {
QVarLengthArray<uchar> data(width * height);
for (int i = 0; i < data.size(); ++i)
data[i] = 0;
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &data[0]);
+ funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &data[0]);
}
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
m_filterMode = Nearest;
}
@@ -149,6 +150,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height)
qWarning("QGLTextureGlyphCache::resizeTextureData: Called with no context");
return;
}
+ QOpenGLFunctions *funcs = ctx->contextHandle()->functions();
int oldWidth = m_textureResource->m_width;
int oldHeight = m_textureResource->m_height;
@@ -165,44 +167,42 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height)
if (!QGLFramebufferObject::hasOpenGLFramebufferObjects() || ctx->d_ptr->workaround_brokenFBOReadBack) {
QImageTextureGlyphCache::resizeTextureData(width, height);
Q_ASSERT(image().depth() == 8);
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits());
- glDeleteTextures(1, &oldTexture);
+ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits());
+ funcs->glDeleteTextures(1, &oldTexture);
return;
}
- QOpenGLFunctions *funcs = ctx->contextHandle()->functions();
-
// ### the QTextureGlyphCache API needs to be reworked to allow
// ### resizeTextureData to fail
funcs->glBindFramebuffer(GL_FRAMEBUFFER, m_textureResource->m_fbo);
GLuint tmp_texture;
- glGenTextures(1, &tmp_texture);
- glBindTexture(GL_TEXTURE_2D, tmp_texture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ funcs->glGenTextures(1, &tmp_texture);
+ funcs->glBindTexture(GL_TEXTURE_2D, tmp_texture);
+ funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
m_filterMode = Nearest;
- glBindTexture(GL_TEXTURE_2D, 0);
+ funcs->glBindTexture(GL_TEXTURE_2D, 0);
funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, tmp_texture, 0);
funcs->glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
- glBindTexture(GL_TEXTURE_2D, oldTexture);
+ funcs->glBindTexture(GL_TEXTURE_2D, oldTexture);
if (pex != 0)
pex->transferMode(BrushDrawingMode);
- glDisable(GL_STENCIL_TEST);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_SCISSOR_TEST);
- glDisable(GL_BLEND);
+ funcs->glDisable(GL_STENCIL_TEST);
+ funcs->glDisable(GL_DEPTH_TEST);
+ funcs->glDisable(GL_SCISSOR_TEST);
+ funcs->glDisable(GL_BLEND);
- glViewport(0, 0, oldWidth, oldHeight);
+ funcs->glViewport(0, 0, oldWidth, oldHeight);
QGLShaderProgram *blitProgram = 0;
if (pex == 0) {
@@ -257,21 +257,21 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height)
blitProgram->setUniformValue("imageTexture", QT_IMAGE_TEXTURE_UNIT);
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ funcs->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
+ funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
- glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight);
+ funcs->glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight);
funcs->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER, 0);
- glDeleteTextures(1, &tmp_texture);
- glDeleteTextures(1, &oldTexture);
+ funcs->glDeleteTextures(1, &tmp_texture);
+ funcs->glDeleteTextures(1, &oldTexture);
funcs->glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_ptr->current_fbo);
if (pex != 0) {
- glViewport(0, 0, pex->width, pex->height);
+ funcs->glViewport(0, 0, pex->width, pex->height);
pex->updateClipScissorTest();
}
}
@@ -283,16 +283,17 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed sub
qWarning("QGLTextureGlyphCache::fillTexture: Called with no context");
return;
}
+ QOpenGLFunctions *funcs = ctx->contextHandle()->functions();
if (!QGLFramebufferObject::hasOpenGLFramebufferObjects() || ctx->d_ptr->workaround_brokenFBOReadBack) {
QImageTextureGlyphCache::fillTexture(c, glyph, subPixelPosition);
- glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
+ funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
const QImage &texture = image();
const uchar *bits = texture.constBits();
bits += c.y * texture.bytesPerLine() + c.x;
for (int i=0; i<c.h; ++i) {
- glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, c.w, 1, GL_ALPHA, GL_UNSIGNED_BYTE, bits);
+ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, c.w, 1, GL_ALPHA, GL_UNSIGNED_BYTE, bits);
bits += texture.bytesPerLine();
}
return;
@@ -329,14 +330,14 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed sub
}
}
- glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
+ funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
if (mask.format() == QImage::Format_RGB32) {
GLenum format = GL_RGBA;
#if !defined(QT_OPENGL_ES_2)
if (!ctx->contextHandle()->isOpenGLES())
format = GL_BGRA;
#endif
- glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, format, GL_UNSIGNED_BYTE, mask.bits());
+ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, format, GL_UNSIGNED_BYTE, mask.bits());
} else {
// glTexSubImage2D() might cause some garbage to appear in the texture if the mask width is
// not a multiple of four bytes. The bug appeared on a computer with 32-bit Windows Vista
@@ -349,16 +350,16 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed sub
if (!ctx->d_ptr->workaround_brokenAlphaTexSubImage_init) {
// don't know which driver versions exhibit this bug, so be conservative for now
- const QByteArray vendorString(reinterpret_cast<const char*>(glGetString(GL_VENDOR)));
+ const QByteArray vendorString(reinterpret_cast<const char*>(funcs->glGetString(GL_VENDOR)));
ctx->d_ptr->workaround_brokenAlphaTexSubImage = vendorString.indexOf("NVIDIA") >= 0;
ctx->d_ptr->workaround_brokenAlphaTexSubImage_init = true;
}
if (ctx->d_ptr->workaround_brokenAlphaTexSubImage) {
for (int i = 0; i < maskHeight; ++i)
- glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, maskWidth, 1, GL_ALPHA, GL_UNSIGNED_BYTE, mask.scanLine(i));
+ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, maskWidth, 1, GL_ALPHA, GL_UNSIGNED_BYTE, mask.scanLine(i));
} else {
- glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_ALPHA, GL_UNSIGNED_BYTE, mask.bits());
+ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_ALPHA, GL_UNSIGNED_BYTE, mask.bits());
}
}
}
diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
index 5ffbea8708..5c160ffd59 100644
--- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
+++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
@@ -92,7 +92,7 @@ struct QGLGlyphTexture : public QOpenGLSharedResource
if (ctx && m_fbo)
ctx->contextHandle()->functions()->glDeleteFramebuffers(1, &m_fbo);
if (m_width || m_height)
- glDeleteTextures(1, &m_texture);
+ ctx->contextHandle()->functions()->glDeleteTextures(1, &m_texture);
}
void invalidateResource()
diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro
index 5cd553a5e8..9c62d41d3e 100644
--- a/src/opengl/opengl.pro
+++ b/src/opengl/opengl.pro
@@ -12,7 +12,6 @@ load(qt_module)
contains(QT_CONFIG, opengl):CONFIG += opengl
contains(QT_CONFIG, opengles2):CONFIG += opengles2
-contains(QT_CONFIG, egl):CONFIG += egl
HEADERS += qgl.h \
qgl_p.h \
@@ -54,5 +53,3 @@ SOURCES += qglshaderprogram.cpp \
gl2paintengineex/qpaintengineex_opengl2.cpp \
gl2paintengineex/qglcustomshaderstage.cpp \
gl2paintengineex/qtextureglyphcache_gl.cpp
-
-SOURCES += qgl_qpa.cpp
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 02ea6e45e3..d1417cfde5 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -70,6 +70,15 @@
#include "qlibrary.h"
#include <qmutex.h>
+#include "qsurfaceformat.h"
+#include <private/qapplication_p.h>
+#include <qpa/qplatformopenglcontext.h>
+#include <qpa/qplatformwindow.h>
+
+#ifndef QT_OPENGL_ES_2
+#include <qopenglfunctions_1_1.h>
+#endif
+
// #define QT_GL_CONTEXT_RESOURCE_DEBUG
QT_BEGIN_NAMESPACE
@@ -107,6 +116,7 @@ bool qgl_hasExtension(QOpenGLExtensions::OpenGLExtension extension)
}
QOpenGLExtensions::OpenGLExtensions extensions;
+
/*
Returns the GL extensions for the current QOpenGLContext. If there is no
current QOpenGLContext, a default context will be created and the extensions
@@ -121,6 +131,20 @@ QOpenGLExtensions* qgl_extensions()
return 0;
}
+QOpenGLFunctions *qgl_functions()
+{
+ return qgl_extensions(); // QOpenGLExtensions is just a subclass of QOpenGLFunctions
+}
+
+#ifndef QT_OPENGL_ES_2
+QOpenGLFunctions_1_1 *qgl1_functions()
+{
+ QOpenGLFunctions_1_1 *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_1_1>();
+ f->initializeOpenGLFunctions();
+ return f;
+}
+#endif
+
struct QGLThreadContext {
~QGLThreadContext() {
if (context)
@@ -420,6 +444,80 @@ QGLFormat::~QGLFormat()
}
/*!
+ Returns an OpenGL format for the window format specified by \a format.
+*/
+QGLFormat QGLFormat::fromSurfaceFormat(const QSurfaceFormat &format)
+{
+ QGLFormat retFormat;
+ if (format.alphaBufferSize() >= 0)
+ retFormat.setAlphaBufferSize(format.alphaBufferSize());
+ if (format.blueBufferSize() >= 0)
+ retFormat.setBlueBufferSize(format.blueBufferSize());
+ if (format.greenBufferSize() >= 0)
+ retFormat.setGreenBufferSize(format.greenBufferSize());
+ if (format.redBufferSize() >= 0)
+ retFormat.setRedBufferSize(format.redBufferSize());
+ if (format.depthBufferSize() >= 0)
+ retFormat.setDepthBufferSize(format.depthBufferSize());
+ if (format.samples() > 1) {
+ retFormat.setSampleBuffers(true);
+ retFormat.setSamples(format.samples());
+ }
+ if (format.stencilBufferSize() > 0) {
+ retFormat.setStencil(true);
+ retFormat.setStencilBufferSize(format.stencilBufferSize());
+ }
+ retFormat.setDoubleBuffer(format.swapBehavior() != QSurfaceFormat::SingleBuffer);
+ retFormat.setStereo(format.stereo());
+ retFormat.setVersion(format.majorVersion(), format.minorVersion());
+ retFormat.setProfile(static_cast<QGLFormat::OpenGLContextProfile>(format.profile()));
+ return retFormat;
+}
+
+/*!
+ Returns a window format for the OpenGL format specified by \a format.
+*/
+QSurfaceFormat QGLFormat::toSurfaceFormat(const QGLFormat &format)
+{
+ QSurfaceFormat retFormat;
+ if (format.alpha())
+ retFormat.setAlphaBufferSize(format.alphaBufferSize() == -1 ? 1 : format.alphaBufferSize());
+ if (format.blueBufferSize() >= 0)
+ retFormat.setBlueBufferSize(format.blueBufferSize());
+ if (format.greenBufferSize() >= 0)
+ retFormat.setGreenBufferSize(format.greenBufferSize());
+ if (format.redBufferSize() >= 0)
+ retFormat.setRedBufferSize(format.redBufferSize());
+ if (format.depth())
+ retFormat.setDepthBufferSize(format.depthBufferSize() == -1 ? 1 : format.depthBufferSize());
+ retFormat.setSwapBehavior(format.doubleBuffer() ? QSurfaceFormat::DoubleBuffer : QSurfaceFormat::SingleBuffer);
+ if (format.sampleBuffers())
+ retFormat.setSamples(format.samples() == -1 ? 4 : format.samples());
+ if (format.stencil())
+ retFormat.setStencilBufferSize(format.stencilBufferSize() == -1 ? 1 : format.stencilBufferSize());
+ retFormat.setStereo(format.stereo());
+ retFormat.setMajorVersion(format.majorVersion());
+ retFormat.setMinorVersion(format.minorVersion());
+ retFormat.setProfile(static_cast<QSurfaceFormat::OpenGLContextProfile>(format.profile()));
+ // QGLFormat has no way to set DeprecatedFunctions, that is, to tell that forward
+ // compatibility should not be requested. Some drivers fail to ignore the fwdcompat
+ // bit with compatibility profiles so make sure it is not set.
+ if (format.profile() == QGLFormat::CompatibilityProfile)
+ retFormat.setOption(QSurfaceFormat::DeprecatedFunctions);
+ return retFormat;
+}
+
+void QGLContextPrivate::setupSharing() {
+ Q_Q(QGLContext);
+ QOpenGLContext *sharedContext = guiGlContext->shareContext();
+ if (sharedContext) {
+ QGLContext *actualSharedContext = QGLContext::fromOpenGLContext(sharedContext);
+ sharing = true;
+ QGLContextGroup::addShare(q, actualSharedContext);
+ }
+}
+
+/*!
\fn bool QGLFormat::doubleBuffer() const
Returns \c true if double buffering is enabled; otherwise returns
@@ -1113,8 +1211,11 @@ QGLFormat::OpenGLContextProfile QGLFormat::profile() const
\warning This function must not be called until the QApplication
object has been created.
*/
-
-
+bool QGLFormat::hasOpenGL()
+{
+ return QApplicationPrivate::platformIntegration()
+ ->hasCapability(QPlatformIntegration::OpenGL);
+}
/*!
\fn bool QGLFormat::hasOpenGLOverlays()
@@ -1125,6 +1226,10 @@ QGLFormat::OpenGLContextProfile QGLFormat::profile() const
\warning This function must not be called until the QApplication
object has been created.
*/
+bool QGLFormat::hasOpenGLOverlays()
+{
+ return false;
+}
QGLFormat::OpenGLVersionFlags Q_AUTOTEST_EXPORT qOpenGLVersionFlagsFromString(const QString &versionString)
{
@@ -1355,7 +1460,7 @@ QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags()
}
}
- QString versionString(QLatin1String(reinterpret_cast<const char*>(glGetString(GL_VERSION))));
+ QString versionString(QLatin1String(reinterpret_cast<const char*>(qgl_functions()->glGetString(GL_VERSION))));
OpenGLVersionFlags versionFlags = qOpenGLVersionFlagsFromString(versionString);
if (currentCtx) {
currentCtx->d_func()->version_flags_cached = true;
@@ -1631,6 +1736,60 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format)
QGLContext* QGLContext::currentCtx = 0;
/*
+ QGLTemporaryContext implementation
+*/
+class QGLTemporaryContextPrivate
+{
+public:
+ QWindow *window;
+ QOpenGLContext *context;
+
+ QGLContext *oldContext;
+};
+
+QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
+ : d(new QGLTemporaryContextPrivate)
+{
+ d->oldContext = const_cast<QGLContext *>(QGLContext::currentContext());
+
+ d->window = new QWindow;
+ d->window->setSurfaceType(QWindow::OpenGLSurface);
+ d->window->setGeometry(QRect(0, 0, 3, 3));
+ d->window->create();
+
+ d->context = new QOpenGLContext;
+#if !defined(QT_OPENGL_ES)
+ if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
+ // On desktop, request latest released version
+ QSurfaceFormat format;
+#if defined(Q_OS_MAC)
+ // OS X is limited to OpenGL 3.2 Core Profile at present
+ // so set that here. If we use compatibility profile it
+ // only reports 2.x contexts.
+ format.setMajorVersion(3);
+ format.setMinorVersion(2);
+ format.setProfile(QSurfaceFormat::CoreProfile);
+#else
+ format.setMajorVersion(4);
+ format.setMinorVersion(3);
+#endif
+ d->context->setFormat(format);
+ }
+#endif // QT_OPENGL_ES
+ d->context->create();
+ d->context->makeCurrent(d->window);
+}
+
+QGLTemporaryContext::~QGLTemporaryContext()
+{
+ if (d->oldContext)
+ d->oldContext->makeCurrent();
+
+ delete d->context;
+ delete d->window;
+}
+
+/*
Read back the contents of the currently bound framebuffer, used in
QGLWidget::grabFrameBuffer(), QGLPixelbuffer::toImage() and
QGLFramebufferObject::toImage()
@@ -1687,7 +1846,7 @@ QImage qt_gl_read_frame_buffer(const QSize &size, bool alpha_format, bool includ
return QImage();
int w = size.width();
int h = size.height();
- glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
+ qgl_functions()->glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
convertFromGLImage(img, w, h, alpha_format, include_alpha);
return img;
}
@@ -1701,28 +1860,14 @@ QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alp
int h = size.height();
#ifndef QT_OPENGL_ES
if (!QOpenGLContext::currentContext()->isOpenGLES()) {
- //### glGetTexImage not in GL ES 2.0, need to do something else here!
- glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
+
+ qgl1_functions()->glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
}
#endif // QT_OPENGL_ES
convertFromGLImage(img, w, h, alpha_format, include_alpha);
return img;
}
-// returns the highest number closest to v, which is a power of 2
-// NB! assumes 32 bit ints
-int qt_next_power_of_two(int v)
-{
- v--;
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
- ++v;
- return v;
-}
-
Q_GLOBAL_STATIC(QGLTextureCache, qt_gl_texture_cache)
QGLTextureCache::QGLTextureCache()
@@ -1981,6 +2126,47 @@ QGLContext::QGLContext(const QGLFormat &format)
d->init(0, format);
}
+void qDeleteQGLContext(void *handle)
+{
+ QGLContext *context = static_cast<QGLContext *>(handle);
+ delete context;
+}
+
+QGLContext::QGLContext(QOpenGLContext *context)
+ : d_ptr(new QGLContextPrivate(this))
+{
+ Q_D(QGLContext);
+ d->init(0, QGLFormat::fromSurfaceFormat(context->format()));
+ d->guiGlContext = context;
+ d->guiGlContext->setQGLContextHandle(this, qDeleteQGLContext);
+ d->ownContext = false;
+ d->valid = context->isValid();
+ d->setupSharing();
+}
+
+QOpenGLContext *QGLContext::contextHandle() const
+{
+ Q_D(const QGLContext);
+ return d->guiGlContext;
+}
+
+/*!
+ Returns a OpenGL context for the window context specified by the \a context
+ parameter.
+*/
+QGLContext *QGLContext::fromOpenGLContext(QOpenGLContext *context)
+{
+ if (!context)
+ return 0;
+ if (context->qGLContextHandle()) {
+ return reinterpret_cast<QGLContext *>(context->qGLContextHandle());
+ }
+ QGLContext *glContext = new QGLContext(context);
+ //Don't call create on context. This can cause the platformFormat to be set on the widget, which
+ //will cause the platformWindow to be recreated.
+ return glContext;
+}
+
/*!
Destroys the OpenGL context and frees its resources.
*/
@@ -2193,7 +2379,7 @@ QGLTexture *QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
q->deleteTexture(texture->id);
texture = 0;
} else {
- glBindTexture(target, texture->id);
+ qgl_functions()->glBindTexture(target, texture->id);
return texture;
}
}
@@ -2245,6 +2431,7 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
const qint64 key, QGLContext::BindOptions options)
{
Q_Q(QGLContext);
+ QOpenGLFunctions *funcs = qgl_functions();
#ifdef QGL_BIND_TEXTURE_DEBUG
printf("QGLContextPrivate::bindTexture(), imageSize=(%d,%d), internalFormat =0x%x, options=%x, key=%llx\n",
@@ -2255,14 +2442,14 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
#ifndef QT_NO_DEBUG
// Reset the gl error stack...git
- while (glGetError() != GL_NO_ERROR) ;
+ while (funcs->glGetError() != GL_NO_ERROR) ;
#endif
// Scale the pixmap if needed. GL textures needs to have the
// dimensions 2^n+2(border) x 2^m+2(border), unless we're using GL
// 2.0 or use the GL_TEXTURE_RECTANGLE texture target
- int tx_w = qt_next_power_of_two(image.width());
- int tx_h = qt_next_power_of_two(image.height());
+ int tx_w = qNextPowerOfTwo(image.width() - 1);
+ int tx_h = qNextPowerOfTwo(image.height() - 1);
QImage img = image;
@@ -2280,9 +2467,9 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
GLuint filtering = options & QGLContext::LinearFilteringBindOption ? GL_LINEAR : GL_NEAREST;
GLuint tx_id;
- glGenTextures(1, &tx_id);
- glBindTexture(target, tx_id);
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filtering);
+ funcs->glGenTextures(1, &tx_id);
+ funcs->glBindTexture(target, tx_id);
+ funcs->glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filtering);
QOpenGLContext *ctx = QOpenGLContext::currentContext();
bool genMipmap = !ctx->isOpenGLES();
@@ -2293,23 +2480,23 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
{
#if !defined(QT_OPENGL_ES_2)
if (genMipmap) {
- glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
- glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
+ funcs->glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
+ funcs->glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
} else {
- glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
+ funcs->glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
genMipmap = true;
}
#else
- glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
+ funcs->glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
genMipmap = true;
#endif
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, options & QGLContext::LinearFilteringBindOption
- ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST);
+ funcs->glTexParameteri(target, GL_TEXTURE_MIN_FILTER, options & QGLContext::LinearFilteringBindOption
+ ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST);
#ifdef QGL_BIND_TEXTURE_DEBUG
printf(" - generating mipmaps (%d ms)\n", time.elapsed());
#endif
} else {
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filtering);
+ funcs->glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filtering);
}
QImage::Format target_format = img.format();
@@ -2438,12 +2625,12 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
#endif
const QImage &constRef = img; // to avoid detach in bits()...
- glTexImage2D(target, 0, internalFormat, img.width(), img.height(), 0, externalFormat,
- pixel_type, constRef.bits());
+ funcs->glTexImage2D(target, 0, internalFormat, img.width(), img.height(), 0, externalFormat,
+ pixel_type, constRef.bits());
if (genMipmap && ctx->isOpenGLES())
q->functions()->glGenerateMipmap(target);
#ifndef QT_NO_DEBUG
- GLenum error = glGetError();
+ GLenum error = funcs->glGetError();
if (error != GL_NO_ERROR) {
qWarning(" - texture upload failed, error code 0x%x, enum: %d (%x)\n", error, target, target);
}
@@ -2491,7 +2678,7 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target,
q->deleteTexture(texture->id);
texture = 0;
} else {
- glBindTexture(target, texture->id);
+ qgl_functions()->glBindTexture(target, texture->id);
return texture;
}
}
@@ -2532,7 +2719,8 @@ int QGLContextPrivate::maxTextureSize()
if (max_texture_size != -1)
return max_texture_size;
- glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
+ QOpenGLFunctions *funcs = qgl_functions();
+ funcs->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
#ifndef QT_OPENGL_ES
Q_Q(QGLContext);
@@ -2541,8 +2729,9 @@ int QGLContextPrivate::maxTextureSize()
GLint size;
GLint next = 64;
- glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
- glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size);
+ funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions();
+ gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size);
if (size == 0) {
return max_texture_size;
}
@@ -2552,8 +2741,8 @@ int QGLContextPrivate::maxTextureSize()
if (next > max_texture_size)
break;
- glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
- glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next);
+ funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next);
} while (next > size);
max_texture_size = size;
@@ -2670,7 +2859,7 @@ void QGLContext::deleteTexture(GLuint id)
{
if (QGLTextureCache::instance()->remove(this, id))
return;
- glDeleteTextures(1, &id);
+ qgl_functions()->glDeleteTextures(1, &id);
}
void qt_add_rect_to_array(const QRectF &r, GLfloat *array)
@@ -2706,6 +2895,7 @@ void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, GLfloat *
static void qDrawTextureRect(const QRectF &target, GLint textureWidth, GLint textureHeight, GLenum textureTarget)
{
+ QOpenGLFunctions *funcs = qgl_functions();
GLfloat tx = 1.0f;
GLfloat ty = 1.0f;
@@ -2716,8 +2906,9 @@ static void qDrawTextureRect(const QRectF &target, GLint textureWidth, GLint tex
#else
if (textureTarget != GL_TEXTURE_2D && !QOpenGLContext::currentContext()->isOpenGLES()) {
if (textureWidth == -1 || textureHeight == -1) {
- glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth);
- glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight);
+ QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions();
+ gl1funcs->glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth);
+ gl1funcs->glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight);
}
tx = GLfloat(textureWidth);
@@ -2732,15 +2923,16 @@ static void qDrawTextureRect(const QRectF &target, GLint textureWidth, GLint tex
GLfloat vertexArray[4*2];
qt_add_rect_to_array(target, vertexArray);
- glVertexPointer(2, GL_FLOAT, 0, vertexArray);
- glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray);
+ QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions();
+ gl1funcs->glVertexPointer(2, GL_FLOAT, 0, vertexArray);
+ gl1funcs->glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray);
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ gl1funcs->glEnableClientState(GL_VERTEX_ARRAY);
+ gl1funcs->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ funcs->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ gl1funcs->glDisableClientState(GL_VERTEX_ARRAY);
+ gl1funcs->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
#endif // !QT_OPENGL_ES_2
@@ -2781,6 +2973,7 @@ void QGLContext::drawTexture(const QRectF &target, GLuint textureId, GLenum text
#endif
#ifndef QT_OPENGL_ES_2
+ QOpenGLFunctions *funcs = qgl_functions();
if (!contextHandle()->isOpenGLES()) {
#ifdef QT_OPENGL_ES
if (textureTarget != GL_TEXTURE_2D) {
@@ -2788,22 +2981,22 @@ void QGLContext::drawTexture(const QRectF &target, GLuint textureId, GLenum text
return;
}
#else
- const bool wasEnabled = glIsEnabled(GL_TEXTURE_2D);
+ const bool wasEnabled = funcs->glIsEnabled(GL_TEXTURE_2D);
GLint oldTexture;
- glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture);
+ funcs->glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture);
#endif
- glEnable(textureTarget);
- glBindTexture(textureTarget, textureId);
+ funcs->glEnable(textureTarget);
+ funcs->glBindTexture(textureTarget, textureId);
qDrawTextureRect(target, -1, -1, textureTarget);
#ifdef QT_OPENGL_ES
- glDisable(textureTarget);
+ funcs->glDisable(textureTarget);
#else
if (!wasEnabled)
- glDisable(textureTarget);
- glBindTexture(textureTarget, oldTexture);
+ funcs->glDisable(textureTarget);
+ funcs->glBindTexture(textureTarget, oldTexture);
#endif
return;
}
@@ -2844,18 +3037,20 @@ void QGLContext::drawTexture(const QPointF &point, GLuint textureId, GLenum text
Q_UNUSED(textureTarget);
#else
if (!contextHandle()->isOpenGLES()) {
- const bool wasEnabled = glIsEnabled(GL_TEXTURE_2D);
+ QOpenGLFunctions *funcs = qgl_functions();
+ const bool wasEnabled = funcs->glIsEnabled(GL_TEXTURE_2D);
GLint oldTexture;
- glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture);
+ funcs->glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture);
- glEnable(textureTarget);
- glBindTexture(textureTarget, textureId);
+ funcs->glEnable(textureTarget);
+ funcs->glBindTexture(textureTarget, textureId);
GLint textureWidth;
GLint textureHeight;
- glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth);
- glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight);
+ QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions();
+ gl1funcs->glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth);
+ gl1funcs->glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight);
if (d_ptr->active_engine &&
d_ptr->active_engine->type() == QPaintEngine::OpenGL2) {
@@ -2872,8 +3067,8 @@ void QGLContext::drawTexture(const QPointF &point, GLuint textureId, GLenum text
qDrawTextureRect(QRectF(point, QSizeF(textureWidth, textureHeight)), textureWidth, textureHeight, textureTarget);
if (!wasEnabled)
- glDisable(textureTarget);
- glBindTexture(textureTarget, oldTexture);
+ funcs->glDisable(textureTarget);
+ funcs->glBindTexture(textureTarget, oldTexture);
return;
}
#endif
@@ -3031,7 +3226,10 @@ bool QGLContext::areSharing(const QGLContext *context1, const QGLContext *contex
Returns a colormap index for the color c, in ColorIndex mode. Used
by qglColor() and qglClearColor().
*/
-
+uint QGLContext::colorIndex(const QColor&) const
+{
+ return 0;
+}
/*!
\fn bool QGLContext::initialized() const
@@ -3079,7 +3277,10 @@ bool QGLContext::areSharing(const QGLContext *context1, const QGLContext *contex
also be used to draw transparent graphics with a QPainter. See the
examples/opengl/overlay_x11 example for details.
*/
-
+QColor QGLContext::overlayTransparentColor() const
+{
+ return QColor(); // Invalid color
+}
/*!
Creates the GL context. Returns \c true if it was successful in
@@ -3239,6 +3440,51 @@ void QGLContext::moveToThread(QThread *thread)
the virtual function chooseVisual() which finds an appropriate X
visual. On other platforms it may work differently.
*/
+bool QGLContext::chooseContext(const QGLContext* shareContext)
+{
+ Q_D(QGLContext);
+ if(!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) {
+ // Unlike in Qt 4, the only possible target is a widget backed by an OpenGL-based
+ // QWindow. Pixmaps in particular are not supported anymore as paint devices since
+ // starting from Qt 5 QPixmap is raster-backed on almost all platforms.
+ d->valid = false;
+ }else {
+ QWidget *widget = static_cast<QWidget *>(d->paintDevice);
+ QGLFormat glformat = format();
+ QSurfaceFormat winFormat = QGLFormat::toSurfaceFormat(glformat);
+ if (widget->testAttribute(Qt::WA_TranslucentBackground))
+ winFormat.setAlphaBufferSize(qMax(winFormat.alphaBufferSize(), 8));
+
+ QWindow *window = widget->windowHandle();
+ if (!window->handle()
+ || window->surfaceType() != QWindow::OpenGLSurface
+ || window->requestedFormat() != winFormat)
+ {
+ window->setSurfaceType(QWindow::OpenGLSurface);
+ window->setFormat(winFormat);
+ window->destroy();
+ window->create();
+ }
+
+ if (d->ownContext)
+ delete d->guiGlContext;
+ d->ownContext = true;
+ QOpenGLContext *shareGlContext = shareContext ? shareContext->d_func()->guiGlContext : 0;
+ d->guiGlContext = new QOpenGLContext;
+ d->guiGlContext->setFormat(winFormat);
+ d->guiGlContext->setShareContext(shareGlContext);
+ d->valid = d->guiGlContext->create();
+
+ if (d->valid)
+ d->guiGlContext->setQGLContextHandle(this, qDeleteQGLContext);
+
+ d->glFormat = QGLFormat::fromSurfaceFormat(d->guiGlContext->format());
+ d->setupSharing();
+ }
+
+
+ return d->valid;
+}
/*!
\fn void QGLContext::reset()
@@ -3247,7 +3493,33 @@ void QGLContext::moveToThread(QThread *thread)
\sa create(), isValid()
*/
-
+void QGLContext::reset()
+{
+ Q_D(QGLContext);
+ if (!d->valid)
+ return;
+ d->cleanup();
+
+ d->crWin = false;
+ d->sharing = false;
+ d->valid = false;
+ d->transpColor = QColor();
+ d->initDone = false;
+ QGLContextGroup::removeShare(this);
+ if (d->guiGlContext) {
+ if (QOpenGLContext::currentContext() == d->guiGlContext)
+ doneCurrent();
+ if (d->ownContext) {
+ if (d->guiGlContext->thread() == QThread::currentThread())
+ delete d->guiGlContext;
+ else
+ d->guiGlContext->deleteLater();
+ } else
+ d->guiGlContext->setQGLContextHandle(0,0);
+ d->guiGlContext = 0;
+ }
+ d->ownContext = false;
+}
/*!
\fn void QGLContext::makeCurrent()
@@ -3263,7 +3535,26 @@ void QGLContext::moveToThread(QThread *thread)
make sure you've first pushed the context to the relevant thread
from the UI thread using moveToThread().
*/
+void QGLContext::makeCurrent()
+{
+ Q_D(QGLContext);
+ if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget)
+ return;
+ QWidget *widget = static_cast<QWidget *>(d->paintDevice);
+ if (!widget->windowHandle())
+ return;
+
+ if (d->guiGlContext->makeCurrent(widget->windowHandle())) {
+ if (!d->workaroundsCached) {
+ d->workaroundsCached = true;
+ const char *renderer = reinterpret_cast<const char *>(d->guiGlContext->functions()->glGetString(GL_RENDERER));
+ if (renderer && strstr(renderer, "Mali")) {
+ d->workaround_brokenFBOReadBack = true;
+ }
+ }
+ }
+}
/*!
\fn void QGLContext::swapBuffers() const
@@ -3271,7 +3562,18 @@ void QGLContext::moveToThread(QThread *thread)
Call this to finish a frame of OpenGL rendering, and make sure to
call makeCurrent() again before you begin a new frame.
*/
+void QGLContext::swapBuffers() const
+{
+ Q_D(const QGLContext);
+ if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget)
+ return;
+ QWidget *widget = static_cast<QWidget *>(d->paintDevice);
+ if (!widget->windowHandle())
+ return;
+
+ d->guiGlContext->swapBuffers(widget->windowHandle());
+}
/*!
\fn void QGLContext::doneCurrent()
@@ -3279,7 +3581,11 @@ void QGLContext::moveToThread(QThread *thread)
Makes no GL context the current context. Normally, you do not need
to call this function; QGLContext calls it as necessary.
*/
-
+void QGLContext::doneCurrent()
+{
+ Q_D(QGLContext);
+ d->guiGlContext->doneCurrent();
+}
/*!
\fn QPaintDevice* QGLContext::device() const
@@ -3289,7 +3595,6 @@ void QGLContext::moveToThread(QThread *thread)
\sa QGLContext::QGLContext()
*/
-
/*****************************************************************************
QGLWidget implementation
*****************************************************************************/
@@ -3688,6 +3993,11 @@ QGLWidget::~QGLWidget()
\a proc. 0 is returned if a pointer to the function could not be
obtained.
*/
+QFunctionPointer QGLContext::getProcAddress(const QString &procName) const
+{
+ Q_D(const QGLContext);
+ return d->guiGlContext->getProcAddress(procName.toLatin1());
+}
/*!
\fn bool QGLWidget::isValid() const
@@ -3775,8 +4085,10 @@ void QGLWidget::swapBuffers()
\sa context()
*/
-
-
+const QGLContext* QGLWidget::overlayContext() const
+{
+ return 0;
+}
/*!
\fn void QGLWidget::makeOverlayCurrent()
@@ -3789,7 +4101,9 @@ void QGLWidget::swapBuffers()
\sa makeCurrent()
*/
-
+void QGLWidget::makeOverlayCurrent()
+{
+}
/*!
\obsolete
@@ -3865,8 +4179,28 @@ void QGLWidget::setFormat(const QGLFormat &format)
\sa context(), isSharing()
*/
+void QGLWidget::setContext(QGLContext *context,
+ const QGLContext* shareContext,
+ bool deleteOldContext)
+{
+ Q_D(QGLWidget);
+ if (context == 0) {
+ qWarning("QGLWidget::setContext: Cannot set null context");
+ return;
+ }
+
+ if (context->device() == 0) // a context may refere to more than 1 window.
+ context->setDevice(this); //but its better to point to 1 of them than none of them.
+
+ QGLContext* oldcx = d->glcx;
+ d->glcx = context;
+ if (!d->glcx->isValid())
+ d->glcx->create(shareContext ? shareContext : oldcx);
+ if (deleteOldContext)
+ delete oldcx;
+}
/*!
\fn void QGLWidget::updateGL()
@@ -3892,7 +4226,9 @@ void QGLWidget::updateGL()
The widget's rendering context will become the current context and
initializeGL() will be called if it hasn't already been called.
*/
-
+void QGLWidget::updateOverlayGL()
+{
+}
/*!
This virtual function is called once before the first call to
@@ -3921,7 +4257,7 @@ void QGLWidget::initializeGL()
void QGLWidget::paintGL()
{
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ qgl_functions()->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
@@ -3994,6 +4330,20 @@ void QGLWidget::resizeOverlayGL(int, int)
{
}
+bool QGLWidget::event(QEvent *e)
+{
+ Q_D(QGLWidget);
+
+ // A re-parent will destroy the window and re-create it. We should not reset the context while it happens.
+ if (e->type() == QEvent::ParentAboutToChange)
+ d->parent_changing = true;
+
+ if (e->type() == QEvent::ParentChange)
+ d->parent_changing = false;
+
+ return QWidget::event(e);
+}
+
/*!
\fn void QGLWidget::paintEvent(QPaintEvent *event)
@@ -4019,7 +4369,21 @@ void QGLWidget::paintEvent(QPaintEvent *)
Handles resize events that are passed in the \a event parameter.
Calls the virtual function resizeGL().
*/
+void QGLWidget::resizeEvent(QResizeEvent *e)
+{
+ Q_D(QGLWidget);
+
+ QWidget::resizeEvent(e);
+ if (!isValid())
+ return;
+ makeCurrent();
+ if (!d->glcx->initialized())
+ glInit();
+ const qreal scaleFactor = (window() && window()->windowHandle()) ?
+ window()->windowHandle()->devicePixelRatio() : 1.0;
+ resizeGL(width() * scaleFactor, height() * scaleFactor);
+}
/*!
Renders the current scene on a pixmap and returns the pixmap.
@@ -4148,7 +4512,7 @@ void QGLWidget::glDraw()
makeCurrent();
#ifndef QT_OPENGL_ES
if (d->glcx->deviceIsPixmap() && !d->glcx->contextHandle()->isOpenGLES())
- glDrawBuffer(GL_FRONT);
+ qgl1_functions()->glDrawBuffer(GL_FRONT);
#endif
QSize readback_target_size = d->glcx->d_ptr->readback_target_size;
if (!d->glcx->initialized()) {
@@ -4170,7 +4534,7 @@ void QGLWidget::glDraw()
if (d->autoSwap)
swapBuffers();
} else {
- glFlush();
+ qgl_functions()->glFlush();
}
}
@@ -4188,20 +4552,20 @@ void QGLWidget::qglColor(const QColor& c) const
{
#if !defined(QT_OPENGL_ES_2)
#ifdef QT_OPENGL_ES
- glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());
+ qgl_functions()->glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());
#else
Q_D(const QGLWidget);
const QGLContext *ctx = QGLContext::currentContext();
if (ctx && !ctx->contextHandle()->isOpenGLES()) {
if (ctx->format().rgba())
- glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());
+ qgl1_functions()->glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());
else if (!d->cmap.isEmpty()) { // QGLColormap in use?
int i = d->cmap.find(c.rgb());
if (i < 0)
i = d->cmap.findNearest(c.rgb());
- glIndexi(i);
+ qgl1_functions()->glIndexi(i);
} else
- glIndexi(ctx->colorIndex(c));
+ qgl1_functions()->glIndexi(ctx->colorIndex(c));
}
#endif //QT_OPENGL_ES
#else
@@ -4220,23 +4584,23 @@ void QGLWidget::qglColor(const QColor& c) const
void QGLWidget::qglClearColor(const QColor& c) const
{
#ifdef QT_OPENGL_ES
- glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
+ qgl_functions()->glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
#else
Q_D(const QGLWidget);
const QGLContext *ctx = QGLContext::currentContext();
if (ctx && !ctx->contextHandle()->isOpenGLES()) {
if (ctx->format().rgba())
- glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
+ qgl_functions()->glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
else if (!d->cmap.isEmpty()) { // QGLColormap in use?
int i = d->cmap.find(c.rgb());
if (i < 0)
i = d->cmap.findNearest(c.rgb());
- glClearIndex(i);
+ qgl1_functions()->glClearIndex(i);
} else {
- glClearIndex(ctx->colorIndex(c));
+ qgl1_functions()->glClearIndex(ctx->colorIndex(c));
}
} else {
- glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
+ qgl_functions()->glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
}
#endif
}
@@ -4305,6 +4669,11 @@ QImage QGLWidget::convertToGLFormat(const QImage& img)
\sa setColormap(), QGLColormap::isEmpty()
*/
+const QGLColormap & QGLWidget::colormap() const
+{
+ Q_D(const QGLWidget);
+ return d->cmap;
+}
/*!
\fn void QGLWidget::setColormap(const QGLColormap & cmap)
@@ -4314,47 +4683,56 @@ QImage QGLWidget::convertToGLFormat(const QImage& img)
\sa colormap()
*/
+void QGLWidget::setColormap(const QGLColormap & c)
+{
+ Q_UNUSED(c);
+}
#ifndef QT_OPENGL_ES
static void qt_save_gl_state()
{
- glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
- glPushAttrib(GL_ALL_ATTRIB_BITS);
- glMatrixMode(GL_TEXTURE);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
-
- glShadeModel(GL_FLAT);
- glDisable(GL_CULL_FACE);
- glDisable(GL_LIGHTING);
- glDisable(GL_STENCIL_TEST);
- glDisable(GL_DEPTH_TEST);
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ QOpenGLFunctions *funcs = qgl_functions();
+ QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions();
+
+ gl1funcs->glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
+ gl1funcs->glPushAttrib(GL_ALL_ATTRIB_BITS);
+ gl1funcs->glMatrixMode(GL_TEXTURE);
+ gl1funcs->glPushMatrix();
+ gl1funcs->glLoadIdentity();
+ gl1funcs->glMatrixMode(GL_PROJECTION);
+ gl1funcs->glPushMatrix();
+ gl1funcs->glMatrixMode(GL_MODELVIEW);
+ gl1funcs->glPushMatrix();
+
+ gl1funcs->glShadeModel(GL_FLAT);
+ funcs->glDisable(GL_CULL_FACE);
+ funcs->glDisable(GL_LIGHTING);
+ funcs->glDisable(GL_STENCIL_TEST);
+ funcs->glDisable(GL_DEPTH_TEST);
+ funcs->glEnable(GL_BLEND);
+ funcs->glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
static void qt_restore_gl_state()
{
- glMatrixMode(GL_TEXTURE);
- glPopMatrix();
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- glPopAttrib();
- glPopClientAttrib();
+ QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions();
+
+ gl1funcs->glMatrixMode(GL_TEXTURE);
+ gl1funcs->glPopMatrix();
+ gl1funcs->glMatrixMode(GL_PROJECTION);
+ gl1funcs->glPopMatrix();
+ gl1funcs->glMatrixMode(GL_MODELVIEW);
+ gl1funcs->glPopMatrix();
+ gl1funcs->glPopAttrib();
+ gl1funcs->glPopClientAttrib();
}
static void qt_gl_draw_text(QPainter *p, int x, int y, const QString &str,
const QFont &font)
{
GLfloat color[4];
- glGetFloatv(GL_CURRENT_COLOR, &color[0]);
+ qgl_functions()->glGetFloatv(GL_CURRENT_COLOR, &color[0]);
QColor col;
col.setRgbF(color[0], color[1], color[2],color[3]);
@@ -4404,10 +4782,11 @@ void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font)
if (str.isEmpty() || !isValid())
return;
+ QOpenGLFunctions *funcs = qgl_functions();
GLint view[4];
- bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST);
+ bool use_scissor_testing = funcs->glIsEnabled(GL_SCISSOR_TEST);
if (!use_scissor_testing)
- glGetIntegerv(GL_VIEWPORT, &view[0]);
+ funcs->glGetIntegerv(GL_VIEWPORT, &view[0]);
int width = d->glcx->device()->width();
int height = d->glcx->device()->height();
bool auto_swap = autoBufferSwap();
@@ -4422,8 +4801,8 @@ void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font)
reuse_painter = true;
p = engine->painter();
- glDisable(GL_DEPTH_TEST);
- glViewport(0, 0, width, height);
+ funcs->glDisable(GL_DEPTH_TEST);
+ funcs->glViewport(0, 0, width, height);
} else {
setAutoBufferSwap(false);
// disable glClear() as a result of QPainter::begin()
@@ -4435,11 +4814,11 @@ void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font)
if (!use_scissor_testing && viewport != rect()) {
// if the user hasn't set a scissor box, we set one that
// covers the current viewport
- glScissor(view[0], view[1], view[2], view[3]);
- glEnable(GL_SCISSOR_TEST);
+ funcs->glScissor(view[0], view[1], view[2], view[3]);
+ funcs->glEnable(GL_SCISSOR_TEST);
} else if (use_scissor_testing) {
// use the scissor box set by the user
- glEnable(GL_SCISSOR_TEST);
+ funcs->glEnable(GL_SCISSOR_TEST);
}
qt_gl_draw_text(p, x, y, str, font);
@@ -4494,15 +4873,17 @@ void QGLWidget::renderText(double x, double y, double z, const QString &str, con
if (str.isEmpty() || !isValid())
return;
+ QOpenGLFunctions *funcs = qgl_functions();
bool auto_swap = autoBufferSwap();
int width = d->glcx->device()->width();
int height = d->glcx->device()->height();
GLdouble model[4 * 4], proj[4 * 4];
GLint view[4];
- glGetDoublev(GL_MODELVIEW_MATRIX, &model[0]);
- glGetDoublev(GL_PROJECTION_MATRIX, &proj[0]);
- glGetIntegerv(GL_VIEWPORT, &view[0]);
+ QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions();
+ gl1funcs->glGetDoublev(GL_MODELVIEW_MATRIX, &model[0]);
+ gl1funcs->glGetDoublev(GL_PROJECTION_MATRIX, &proj[0]);
+ funcs->glGetIntegerv(GL_VIEWPORT, &view[0]);
GLdouble win_x = 0, win_y = 0, win_z = 0;
qgluProject(x, y, z, &model[0], &proj[0], &view[0],
&win_x, &win_y, &win_z);
@@ -4512,8 +4893,8 @@ void QGLWidget::renderText(double x, double y, double z, const QString &str, con
QPainter *p;
bool reuse_painter = false;
- bool use_depth_testing = glIsEnabled(GL_DEPTH_TEST);
- bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST);
+ bool use_depth_testing = funcs->glIsEnabled(GL_DEPTH_TEST);
+ bool use_scissor_testing = funcs->glIsEnabled(GL_SCISSOR_TEST);
qt_save_gl_state();
@@ -4529,16 +4910,16 @@ void QGLWidget::renderText(double x, double y, double z, const QString &str, con
QRect viewport(view[0], view[1], view[2], view[3]);
if (!use_scissor_testing && viewport != rect()) {
- glScissor(view[0], view[1], view[2], view[3]);
- glEnable(GL_SCISSOR_TEST);
+ funcs->glScissor(view[0], view[1], view[2], view[3]);
+ funcs->glEnable(GL_SCISSOR_TEST);
} else if (use_scissor_testing) {
- glEnable(GL_SCISSOR_TEST);
+ funcs->glEnable(GL_SCISSOR_TEST);
}
- glViewport(0, 0, width, height);
- glAlphaFunc(GL_GREATER, 0.0);
- glEnable(GL_ALPHA_TEST);
+ funcs->glViewport(0, 0, width, height);
+ gl1funcs->glAlphaFunc(GL_GREATER, 0.0);
+ funcs->glEnable(GL_ALPHA_TEST);
if (use_depth_testing)
- glEnable(GL_DEPTH_TEST);
+ funcs->glEnable(GL_DEPTH_TEST);
// The only option in Qt 5 is the shader-based OpenGL 2 paint engine.
// Setting fixed pipeline transformations is futile. Instead, pass the
@@ -4731,6 +5112,11 @@ QPaintEngine *QGLWidget::paintEngine() const
return qt_qgl_paint_engine();
}
+void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget *shareWidget)
+{
+ initContext(context, shareWidget);
+}
+
/*
This is the shared initialization for all platforms. Called from QGLWidgetPrivate::init()
*/
@@ -4751,6 +5137,19 @@ void QGLWidgetPrivate::initContext(QGLContext *context, const QGLWidget* shareWi
glcx = new QGLContext(QGLFormat::defaultFormat(), q);
}
+bool QGLWidgetPrivate::renderCxPm(QPixmap*)
+{
+ return false;
+}
+
+/*! \internal
+ Free up any allocated colormaps. This fn is only called for
+ top-level widgets.
+*/
+void QGLWidgetPrivate::cleanupColormaps()
+{
+}
+
Q_GLOBAL_STATIC(QString, qt_gl_lib_name)
void qt_set_gl_library_name(const QString& name)
@@ -4976,10 +5375,11 @@ QSize QGLTexture::bindCompressedTextureDDS(const char *buf, int len)
const GLubyte *pixels =
reinterpret_cast<const GLubyte *>(buf + ddsHeader->dwSize + 4);
- glGenTextures(1, &id);
- glBindTexture(GL_TEXTURE_2D, id);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ QOpenGLFunctions *funcs = qgl_functions();
+ funcs->glGenTextures(1, &id);
+ funcs->glBindTexture(GL_TEXTURE_2D, id);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
int size;
int offset = 0;
@@ -5072,23 +5472,24 @@ QSize QGLTexture::bindCompressedTexturePVR(const char *buf, int len)
}
// Create the texture.
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glGenTextures(1, &id);
- glBindTexture(GL_TEXTURE_2D, id);
+ QOpenGLFunctions *funcs = qgl_functions();
+ funcs->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ funcs->glGenTextures(1, &id);
+ funcs->glBindTexture(GL_TEXTURE_2D, id);
if (pvrHeader->mipMapCount) {
if ((options & QGLContext::LinearFilteringBindOption) != 0) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
} else {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
}
} else if ((options & QGLContext::LinearFilteringBindOption) != 0) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
} else {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
// Load the compressed mipmap levels.
@@ -5114,7 +5515,7 @@ QSize QGLTexture::bindCompressedTexturePVR(const char *buf, int len)
}
// Restore the default pixel alignment for later texture uploads.
- glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ funcs->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
// Set the invert flag for the texture. The "vertical flip"
// flag in PVR is the opposite sense to our sense of inversion.
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index 22fc3f4ad0..6dd939c2de 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -346,7 +346,7 @@ public:
private:
static void freeTextureFunc(QOpenGLFunctions *, GLuint id) {
- glDeleteTextures(1, &id);
+ QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &id);
}
};
diff --git a/src/opengl/qgl_qpa.cpp b/src/opengl/qgl_qpa.cpp
deleted file mode 100644
index 61d295f173..0000000000
--- a/src/opengl/qgl_qpa.cpp
+++ /dev/null
@@ -1,464 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtOpenGL 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QApplication>
-#include <private/qapplication_p.h>
-#include <QPixmap>
-#include <QDebug>
-
-#include <qpa/qplatformopenglcontext.h>
-#include <qpa/qplatformwindow.h>
-#include <QtGui/QSurfaceFormat>
-
-#include "qgl.h"
-#include "qgl_p.h"
-
-QT_BEGIN_NAMESPACE
-
-/*!
- Returns an OpenGL format for the window format specified by \a format.
-*/
-QGLFormat QGLFormat::fromSurfaceFormat(const QSurfaceFormat &format)
-{
- QGLFormat retFormat;
- if (format.alphaBufferSize() >= 0)
- retFormat.setAlphaBufferSize(format.alphaBufferSize());
- if (format.blueBufferSize() >= 0)
- retFormat.setBlueBufferSize(format.blueBufferSize());
- if (format.greenBufferSize() >= 0)
- retFormat.setGreenBufferSize(format.greenBufferSize());
- if (format.redBufferSize() >= 0)
- retFormat.setRedBufferSize(format.redBufferSize());
- if (format.depthBufferSize() >= 0)
- retFormat.setDepthBufferSize(format.depthBufferSize());
- if (format.samples() > 1) {
- retFormat.setSampleBuffers(true);
- retFormat.setSamples(format.samples());
- }
- if (format.stencilBufferSize() > 0) {
- retFormat.setStencil(true);
- retFormat.setStencilBufferSize(format.stencilBufferSize());
- }
- retFormat.setDoubleBuffer(format.swapBehavior() != QSurfaceFormat::SingleBuffer);
- retFormat.setStereo(format.stereo());
- retFormat.setVersion(format.majorVersion(), format.minorVersion());
- retFormat.setProfile(static_cast<QGLFormat::OpenGLContextProfile>(format.profile()));
- return retFormat;
-}
-
-/*!
- Returns a window format for the OpenGL format specified by \a format.
-*/
-QSurfaceFormat QGLFormat::toSurfaceFormat(const QGLFormat &format)
-{
- QSurfaceFormat retFormat;
- if (format.alpha())
- retFormat.setAlphaBufferSize(format.alphaBufferSize() == -1 ? 1 : format.alphaBufferSize());
- if (format.blueBufferSize() >= 0)
- retFormat.setBlueBufferSize(format.blueBufferSize());
- if (format.greenBufferSize() >= 0)
- retFormat.setGreenBufferSize(format.greenBufferSize());
- if (format.redBufferSize() >= 0)
- retFormat.setRedBufferSize(format.redBufferSize());
- if (format.depth())
- retFormat.setDepthBufferSize(format.depthBufferSize() == -1 ? 1 : format.depthBufferSize());
- retFormat.setSwapBehavior(format.doubleBuffer() ? QSurfaceFormat::DoubleBuffer : QSurfaceFormat::SingleBuffer);
- if (format.sampleBuffers())
- retFormat.setSamples(format.samples() == -1 ? 4 : format.samples());
- if (format.stencil())
- retFormat.setStencilBufferSize(format.stencilBufferSize() == -1 ? 1 : format.stencilBufferSize());
- retFormat.setStereo(format.stereo());
- retFormat.setMajorVersion(format.majorVersion());
- retFormat.setMinorVersion(format.minorVersion());
- retFormat.setProfile(static_cast<QSurfaceFormat::OpenGLContextProfile>(format.profile()));
- // QGLFormat has no way to set DeprecatedFunctions, that is, to tell that forward
- // compatibility should not be requested. Some drivers fail to ignore the fwdcompat
- // bit with compatibility profiles so make sure it is not set.
- if (format.profile() == QGLFormat::CompatibilityProfile)
- retFormat.setOption(QSurfaceFormat::DeprecatedFunctions);
- return retFormat;
-}
-
-void QGLContextPrivate::setupSharing() {
- Q_Q(QGLContext);
- QOpenGLContext *sharedContext = guiGlContext->shareContext();
- if (sharedContext) {
- QGLContext *actualSharedContext = QGLContext::fromOpenGLContext(sharedContext);
- sharing = true;
- QGLContextGroup::addShare(q, actualSharedContext);
- }
-}
-
-bool QGLFormat::hasOpenGL()
-{
- return QApplicationPrivate::platformIntegration()
- ->hasCapability(QPlatformIntegration::OpenGL);
-}
-
-void qDeleteQGLContext(void *handle)
-{
- QGLContext *context = static_cast<QGLContext *>(handle);
- delete context;
-}
-
-bool QGLContext::chooseContext(const QGLContext* shareContext)
-{
- Q_D(QGLContext);
- if(!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) {
- // Unlike in Qt 4, the only possible target is a widget backed by an OpenGL-based
- // QWindow. Pixmaps in particular are not supported anymore as paint devices since
- // starting from Qt 5 QPixmap is raster-backed on almost all platforms.
- d->valid = false;
- }else {
- QWidget *widget = static_cast<QWidget *>(d->paintDevice);
- QGLFormat glformat = format();
- QSurfaceFormat winFormat = QGLFormat::toSurfaceFormat(glformat);
- if (widget->testAttribute(Qt::WA_TranslucentBackground))
- winFormat.setAlphaBufferSize(qMax(winFormat.alphaBufferSize(), 8));
-
- QWindow *window = widget->windowHandle();
- if (!window->handle()
- || window->surfaceType() != QWindow::OpenGLSurface
- || window->requestedFormat() != winFormat)
- {
- window->setSurfaceType(QWindow::OpenGLSurface);
- window->setFormat(winFormat);
- window->destroy();
- window->create();
- }
-
- if (d->ownContext)
- delete d->guiGlContext;
- d->ownContext = true;
- QOpenGLContext *shareGlContext = shareContext ? shareContext->d_func()->guiGlContext : 0;
- d->guiGlContext = new QOpenGLContext;
- d->guiGlContext->setFormat(winFormat);
- d->guiGlContext->setShareContext(shareGlContext);
- d->valid = d->guiGlContext->create();
-
- if (d->valid)
- d->guiGlContext->setQGLContextHandle(this,qDeleteQGLContext);
-
- d->glFormat = QGLFormat::fromSurfaceFormat(d->guiGlContext->format());
- d->setupSharing();
- }
-
-
- return d->valid;
-}
-
-void QGLContext::reset()
-{
- Q_D(QGLContext);
- if (!d->valid)
- return;
- d->cleanup();
-
- d->crWin = false;
- d->sharing = false;
- d->valid = false;
- d->transpColor = QColor();
- d->initDone = false;
- QGLContextGroup::removeShare(this);
- if (d->guiGlContext) {
- if (QOpenGLContext::currentContext() == d->guiGlContext)
- doneCurrent();
- if (d->ownContext) {
- if (d->guiGlContext->thread() == QThread::currentThread())
- delete d->guiGlContext;
- else
- d->guiGlContext->deleteLater();
- } else
- d->guiGlContext->setQGLContextHandle(0,0);
- d->guiGlContext = 0;
- }
- d->ownContext = false;
-}
-
-void QGLContext::makeCurrent()
-{
- Q_D(QGLContext);
- if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget)
- return;
-
- QWidget *widget = static_cast<QWidget *>(d->paintDevice);
- if (!widget->windowHandle())
- return;
-
- if (d->guiGlContext->makeCurrent(widget->windowHandle())) {
- if (!d->workaroundsCached) {
- d->workaroundsCached = true;
- const char *renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
- if (renderer && strstr(renderer, "Mali")) {
- d->workaround_brokenFBOReadBack = true;
- }
- }
- }
-}
-
-void QGLContext::doneCurrent()
-{
- Q_D(QGLContext);
- d->guiGlContext->doneCurrent();
-}
-
-void QGLContext::swapBuffers() const
-{
- Q_D(const QGLContext);
- if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget)
- return;
-
- QWidget *widget = static_cast<QWidget *>(d->paintDevice);
- if (!widget->windowHandle())
- return;
-
- d->guiGlContext->swapBuffers(widget->windowHandle());
-}
-
-QFunctionPointer QGLContext::getProcAddress(const QString &procName) const
-{
- Q_D(const QGLContext);
- return d->guiGlContext->getProcAddress(procName.toLatin1());
-}
-
-void QGLWidget::setContext(QGLContext *context,
- const QGLContext* shareContext,
- bool deleteOldContext)
-{
- Q_D(QGLWidget);
- if (context == 0) {
- qWarning("QGLWidget::setContext: Cannot set null context");
- return;
- }
-
- if (context->device() == 0) // a context may refere to more than 1 window.
- context->setDevice(this); //but its better to point to 1 of them than none of them.
-
- QGLContext* oldcx = d->glcx;
- d->glcx = context;
-
- if (!d->glcx->isValid())
- d->glcx->create(shareContext ? shareContext : oldcx);
-
- if (deleteOldContext)
- delete oldcx;
-}
-
-void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget *shareWidget)
-{
- initContext(context, shareWidget);
-}
-
-bool QGLFormat::hasOpenGLOverlays()
-{
- return false;
-}
-
-QColor QGLContext::overlayTransparentColor() const
-{
- return QColor(); // Invalid color
-}
-
-uint QGLContext::colorIndex(const QColor&) const
-{
- return 0;
-}
-
-/*
- QGLTemporaryContext implementation
-*/
-class QGLTemporaryContextPrivate
-{
-public:
- QWindow *window;
- QOpenGLContext *context;
-
- QGLContext *oldContext;
-};
-
-QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
- : d(new QGLTemporaryContextPrivate)
-{
- d->oldContext = const_cast<QGLContext *>(QGLContext::currentContext());
-
- d->window = new QWindow;
- d->window->setSurfaceType(QWindow::OpenGLSurface);
- d->window->setGeometry(QRect(0, 0, 3, 3));
- d->window->create();
-
- d->context = new QOpenGLContext;
-#if !defined(QT_OPENGL_ES)
- if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
- // On desktop, request latest released version
- QSurfaceFormat format;
-#if defined(Q_OS_MAC)
- // OS X is limited to OpenGL 3.2 Core Profile at present
- // so set that here. If we use compatibility profile it
- // only reports 2.x contexts.
- format.setMajorVersion(3);
- format.setMinorVersion(2);
- format.setProfile(QSurfaceFormat::CoreProfile);
-#else
- format.setMajorVersion(4);
- format.setMinorVersion(3);
-#endif
- d->context->setFormat(format);
- }
-#endif // QT_OPENGL_ES
- d->context->create();
- d->context->makeCurrent(d->window);
-}
-
-QGLTemporaryContext::~QGLTemporaryContext()
-{
- if (d->oldContext)
- d->oldContext->makeCurrent();
-
- delete d->context;
- delete d->window;
-}
-
-
-bool QGLWidgetPrivate::renderCxPm(QPixmap*)
-{
- return false;
-}
-
-/*! \internal
- Free up any allocated colormaps. This fn is only called for
- top-level widgets.
-*/
-void QGLWidgetPrivate::cleanupColormaps()
-{
-}
-
-bool QGLWidget::event(QEvent *e)
-{
- Q_D(QGLWidget);
-
- // A re-parent will destroy the window and re-create it. We should not reset the context while it happens.
- if (e->type() == QEvent::ParentAboutToChange)
- d->parent_changing = true;
-
- if (e->type() == QEvent::ParentChange)
- d->parent_changing = false;
-
- return QWidget::event(e);
-}
-
-void QGLWidget::resizeEvent(QResizeEvent *e)
-{
- Q_D(QGLWidget);
-
- QWidget::resizeEvent(e);
- if (!isValid())
- return;
- makeCurrent();
- if (!d->glcx->initialized())
- glInit();
- const qreal scaleFactor = (window() && window()->windowHandle()) ?
- window()->windowHandle()->devicePixelRatio() : 1.0;
-
- resizeGL(width() * scaleFactor, height() * scaleFactor);
-}
-
-
-const QGLContext* QGLWidget::overlayContext() const
-{
- return 0;
-}
-
-void QGLWidget::makeOverlayCurrent()
-{
-}
-
-
-void QGLWidget::updateOverlayGL()
-{
-}
-
-const QGLColormap & QGLWidget::colormap() const
-{
- Q_D(const QGLWidget);
- return d->cmap;
-}
-
-void QGLWidget::setColormap(const QGLColormap & c)
-{
- Q_UNUSED(c);
-}
-
-QGLContext::QGLContext(QOpenGLContext *context)
- : d_ptr(new QGLContextPrivate(this))
-{
- Q_D(QGLContext);
- d->init(0, QGLFormat::fromSurfaceFormat(context->format()));
- d->guiGlContext = context;
- d->guiGlContext->setQGLContextHandle(this,qDeleteQGLContext);
- d->ownContext = false;
- d->valid = context->isValid();
- d->setupSharing();
-}
-
-QOpenGLContext *QGLContext::contextHandle() const
-{
- Q_D(const QGLContext);
- return d->guiGlContext;
-}
-
-/*!
- Returns a OpenGL context for the window context specified by the \a context
- parameter.
-*/
-QGLContext *QGLContext::fromOpenGLContext(QOpenGLContext *context)
-{
- if (!context)
- return 0;
- if (context->qGLContextHandle()) {
- return reinterpret_cast<QGLContext *>(context->qGLContextHandle());
- }
- QGLContext *glContext = new QGLContext(context);
- //Don't call create on context. This can cause the platformFormat to be set on the widget, which
- //will cause the platformWindow to be recreated.
- return glContext;
-}
-
-QT_END_NAMESPACE
diff --git a/src/opengl/qglbuffer.cpp b/src/opengl/qglbuffer.cpp
index 1c9545990f..525fc15829 100644
--- a/src/opengl/qglbuffer.cpp
+++ b/src/opengl/qglbuffer.cpp
@@ -347,9 +347,9 @@ bool QGLBuffer::read(int offset, void *data, int count)
Q_D(QGLBuffer);
if (!d->funcs->hasOpenGLFeature(QOpenGLFunctions::Buffers) || !d->guard->id())
return false;
- while (glGetError() != GL_NO_ERROR) ; // Clear error state.
+ while (d->funcs->glGetError() != GL_NO_ERROR) ; // Clear error state.
d->funcs->glGetBufferSubData(d->type, offset, count, data);
- return glGetError() == GL_NO_ERROR;
+ return d->funcs->glGetError() == GL_NO_ERROR;
#else
Q_UNUSED(offset);
Q_UNUSED(data);
diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp
index 419055f1a3..57498f8929 100644
--- a/src/opengl/qglframebufferobject.cpp
+++ b/src/opengl/qglframebufferobject.cpp
@@ -61,11 +61,11 @@ extern QImage qt_gl_read_frame_buffer(const QSize&, bool, bool);
#ifndef QT_NO_DEBUG
#define QT_RESET_GLERROR() \
{ \
- while (glGetError() != GL_NO_ERROR) {} \
+ while (QOpenGLContext::currentContext()->functions()->glGetError() != GL_NO_ERROR) {} \
}
#define QT_CHECK_GLERROR() \
{ \
- GLenum err = glGetError(); \
+ GLenum err = QOpenGLContext::currentContext()->functions()->glGetError(); \
if (err != GL_NO_ERROR) { \
qDebug("[%s line %d] GL Error: %d", \
__FILE__, __LINE__, (int)err); \
@@ -94,6 +94,10 @@ extern QImage qt_gl_read_frame_buffer(const QSize&, bool, bool);
#define GL_DEPTH_COMPONENT24 0x81A6
#endif
+#ifndef GL_DEPTH_COMPONENT24_OES
+#define GL_DEPTH_COMPONENT24_OES 0x81A6
+#endif
+
#ifndef GL_READ_FRAMEBUFFER
#define GL_READ_FRAMEBUFFER 0x8CA8
#endif
@@ -460,7 +464,7 @@ namespace
void freeTextureFunc(QGLContext *ctx, GLuint id)
{
Q_UNUSED(ctx);
- glDeleteTextures(1, &id);
+ ctx->contextHandle()->functions()->glDeleteTextures(1, &id);
}
}
@@ -493,10 +497,10 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
QT_CHECK_GLERROR();
// init texture
if (samples == 0) {
- glGenTextures(1, &texture);
- glBindTexture(target, texture);
- glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ funcs.glGenTextures(1, &texture);
+ funcs.glBindTexture(target, texture);
+ funcs.glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
if (mipmap) {
int width = size.width();
int height = size.height();
@@ -505,26 +509,26 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
width = qMax(1, width >> 1);
height = qMax(1, height >> 1);
++level;
- glTexImage2D(target, level, internal_format, width, height, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ funcs.glTexImage2D(target, level, internal_format, width, height, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
}
}
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ funcs.glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ funcs.glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ funcs.glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ funcs.glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
funcs.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
target, texture, 0);
QT_CHECK_GLERROR();
valid = checkFramebufferStatus();
- glBindTexture(target, 0);
+ funcs.glBindTexture(target, 0);
color_buffer = 0;
} else {
mipmap = false;
GLint maxSamples;
- glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
+ funcs.glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
samples = qBound(0, int(samples), int(maxSamples));
@@ -694,7 +698,7 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
if (color_buffer)
funcs.glDeleteRenderbuffers(1, &color_buffer);
else
- glDeleteTextures(1, &texture);
+ funcs.glDeleteTextures(1, &texture);
if (depth_buffer)
funcs.glDeleteRenderbuffers(1, &depth_buffer);
if (stencil_buffer && depth_buffer != stencil_buffer)
diff --git a/src/opengl/qglpaintdevice.cpp b/src/opengl/qglpaintdevice.cpp
index 6a8d5c042e..1af4762e6a 100644
--- a/src/opengl/qglpaintdevice.cpp
+++ b/src/opengl/qglpaintdevice.cpp
@@ -164,18 +164,19 @@ void QGLWidgetGLPaintDevice::setWidget(QGLWidget* w)
void QGLWidgetGLPaintDevice::beginPaint()
{
QGLPaintDevice::beginPaint();
+ QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
if (!glWidget->d_func()->disable_clear_on_painter_begin && glWidget->autoFillBackground()) {
if (glWidget->testAttribute(Qt::WA_TranslucentBackground))
- glClearColor(0.0, 0.0, 0.0, 0.0);
+ funcs->glClearColor(0.0, 0.0, 0.0, 0.0);
else {
const QColor &c = glWidget->palette().brush(glWidget->backgroundRole()).color();
float alpha = c.alphaF();
- glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha);
+ funcs->glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha);
}
if (context()->d_func()->workaround_needsFullClearOnEveryFrame)
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ funcs->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
else
- glClear(GL_COLOR_BUFFER_BIT);
+ funcs->glClear(GL_COLOR_BUFFER_BIT);
}
}
diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp
index 12b26e5381..4205761472 100644
--- a/src/opengl/qglpixelbuffer.cpp
+++ b/src/opengl/qglpixelbuffer.cpp
@@ -124,7 +124,7 @@ void QGLPBufferGLPaintDevice::beginPaint()
void QGLPBufferGLPaintDevice::endPaint()
{
- glFlush();
+ QOpenGLContext::currentContext()->functions()->glFlush();
QGLPaintDevice::endPaint();
}
@@ -235,7 +235,7 @@ bool QGLPixelBuffer::makeCurrent()
d->fbo = new QOpenGLFramebufferObject(d->req_size, format);
d->fbo->bind();
d->glDevice.setFbo(d->fbo->handle());
- glViewport(0, 0, d->req_size.width(), d->req_size.height());
+ QOpenGLContext::currentContext()->functions()->glViewport(0, 0, d->req_size.width(), d->req_size.height());
}
return true;
}
@@ -338,7 +338,7 @@ void QGLPixelBuffer::updateDynamicTexture(GLuint texture_id) const
if (d->invalid || !d->fbo)
return;
- QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ const QGLContext *ctx = QGLContext::currentContext();
if (!ctx)
return;
@@ -352,19 +352,19 @@ void QGLPixelBuffer::updateDynamicTexture(GLuint texture_id) const
#define GL_DRAW_FRAMEBUFFER 0x8CA9
#endif
- QOpenGLExtensions extensions(ctx);
+ QOpenGLExtensions extensions(ctx->contextHandle());
if (d->blit_fbo) {
QOpenGLFramebufferObject::blitFramebuffer(d->blit_fbo, d->fbo);
extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, d->blit_fbo->handle());
}
- glBindTexture(GL_TEXTURE_2D, texture_id);
+ extensions.glBindTexture(GL_TEXTURE_2D, texture_id);
#ifndef QT_OPENGL_ES
- GLenum format = ctx->isOpenGLES() ? GL_RGBA : GL_RGBA8;
- glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, d->req_size.width(), d->req_size.height(), 0);
+ GLenum format = ctx->contextHandle()->isOpenGLES() ? GL_RGBA : GL_RGBA8;
+ extensions.glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, d->req_size.width(), d->req_size.height(), 0);
#else
- glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, d->req_size.width(), d->req_size.height(), 0);
+ extensions.glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, d->req_size.width(), d->req_size.height(), 0);
#endif
if (d->blit_fbo)
@@ -629,17 +629,18 @@ GLuint QGLPixelBuffer::generateDynamicTexture() const
}
GLuint texture;
+ QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
- glGenTextures(1, &texture);
- glBindTexture(GL_TEXTURE_2D, texture);
+ funcs->glGenTextures(1, &texture);
+ funcs->glBindTexture(GL_TEXTURE_2D, texture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, d->req_size.width(), d->req_size.height(), 0,
- GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, d->req_size.width(), d->req_size.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, 0);
return texture;
}
diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp
index 6173ad1288..9cd6ada058 100644
--- a/src/opengl/qglshaderprogram.cpp
+++ b/src/opengl/qglshaderprogram.cpp
@@ -3074,8 +3074,9 @@ int QGLShaderProgram::maxGeometryOutputVertices() const
{
GLint n = 0;
#if !defined(QT_OPENGL_ES_2)
+ Q_D(const QGLShaderProgram);
if (!QOpenGLContext::currentContext()->isOpenGLES())
- glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, &n);
+ d->glfuncs->glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, &n);
#endif
return n;
}
@@ -3229,7 +3230,7 @@ bool QGLShader::hasOpenGLShaders(ShaderType type, const QGLContext *context)
if (!resolved)
return false;
- if ((type & Geometry) && !QByteArray((const char *) glGetString(GL_EXTENSIONS)).contains("GL_EXT_geometry_shader4"))
+ if ((type & Geometry) && !QByteArray((const char *) functions.glGetString(GL_EXTENSIONS)).contains("GL_EXT_geometry_shader4"))
return false;
return true;
diff --git a/src/platformheaders/doc/qtplatformheaders.qdocconf b/src/platformheaders/doc/qtplatformheaders.qdocconf
new file mode 100644
index 0000000000..65fe660b40
--- /dev/null
+++ b/src/platformheaders/doc/qtplatformheaders.qdocconf
@@ -0,0 +1,53 @@
+include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
+
+# Name of the project which must match the outputdir. Determines the .index file
+project = QtPlatformHeaders
+
+# Directories in which to search for files to document and images.
+# By default set to the root directory of the project for sources
+# and headers and qdoc will therefore generate output for each file.
+# Images should be placed in <rootdir>/dic/images and examples in
+# <rootdir>/examples.
+# Paths are relative to the location of this file.
+
+headerdirs += ..
+sourcedirs += ..
+exampledirs += .. \
+ snippets
+
+imagedirs += images
+
+depends += qtdoc qtcore qtgui qtwidgets
+
+examplesinstallpath = platformheaders
+
+# The following parameters are for creating a qhp file, the qhelpgenerator
+# program can convert the qhp file into a qch file which can be opened in
+# Qt Assistant and/or Qt Creator.
+
+# Defines the name of the project. You cannot use operators (+, =, -) in
+# the name. Properties for this project are set using a qhp.<projectname>.property
+# format.
+qhp.projects = QtPlatformHeaders
+
+# Sets the name of the output qhp file.
+qhp.QtPlatformHeaders.file = qtplatformheaders.qhp
+
+# Namespace for the output file. This namespace is used to distinguish between
+# different documentation files in Creator/Assistant.
+qhp.QtPlatformHeaders.namespace = org.qt-project.qtplatformheaders.$QT_VERSION_TAG
+
+# Title for the package, will be the main title for the package in
+# Assistant/Creator.
+qhp.QtPlatformHeaders.indexTitle = Qt Platform Headers
+
+# Only update the name of the project for the next variables.
+qhp.QtPlatformHeaders.virtualFolder = qtplatformheaders
+qhp.QtPlatformHeaders.subprojects = classes
+qhp.QtPlatformHeaders.subprojects.classes.title = C++ Classes
+qhp.QtPlatformHeaders.subprojects.classes.indexTitle = Qt Platform Headers C++ Classes
+qhp.QtPlatformHeaders.subprojects.classes.selectors = class fake:headerfile
+qhp.QtPlatformHeaders.subprojects.classes.sortPages = true
+
+navigation.landingpage = "Qt Platform Headers"
+navigation.cppclassespage = "Qt Platform Headers C++ Classes"
diff --git a/src/platformheaders/doc/snippets/qxcbwindowfunctions/main.cpp b/src/platformheaders/doc/snippets/qxcbwindowfunctions/main.cpp
new file mode 100644
index 0000000000..d4cb965bda
--- /dev/null
+++ b/src/platformheaders/doc/snippets/qxcbwindowfunctions/main.cpp
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Digia Plc and its Subsidiary(-ies) 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 <QtWidgets>
+#include <QtPlatformHeaders/qxcbwindowfunctions.h>
+
+//! [0]
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ QPushButton topLevelWidget("Hello World!");
+ topLevelWidget.winId(); //have to create the QWindow
+
+ QWindow *tlwWindow = topLevelWidget.windowHandle();
+
+ QXcbWindowFunctions::setWmWindowType(tlwWindow, QXcbWindowFunctions::Dock);
+
+ topLevelWidget.show();
+
+ return app.exec();
+}
+//! [0]
+
diff --git a/src/platformheaders/doc/src/qtplatformheaders.qdoc b/src/platformheaders/doc/src/qtplatformheaders.qdoc
new file mode 100644
index 0000000000..74df288d3d
--- /dev/null
+++ b/src/platformheaders/doc/src/qtplatformheaders.qdoc
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \module QtPlatformHeaders
+ \title Qt Platform Headers C++ Classes
+ \ingroup modules
+
+ \brief The Qt Platform Headers module offers header-only inline classes that
+ encapsulate platform-specific information that is tied to a given runtime
+ configuration of a platform plugin.
+*/
+
+/*!
+ \page qtplatformheaders-index.html
+ \title Qt Platform Headers
+
+ \brief The Qt Platform Headers module offers header-only inline classes that
+ encapsulate platform-specific information that is tied to a given runtime
+ configuration of a platform plugin.
+
+ Some applications may need to interface Qt with other frameworks. This often
+ means using graphics contexts or other types of native handles created by
+ one framework with another. For example, on some platforms, QOpenGLContext
+ offers the ability to wrap an existing native OpenGL context, instead of
+ creating a new one. This existing native context can be created by some
+ other third-party code.
+
+ The type of such native handles is highly platform specific and in some
+ cases the platform plugin will need more information to adopt a handle, just
+ the handle in itself will not be sufficient. Therefore the public API
+ consists of functions taking or returning a QVariant that contains a
+ platform-specific value type. See for example
+ QOpenGLContext::setNativeHandle() and QOpenGLContext::nativeHandle(). When
+ running on Linux/X11, using the xcb platform plugin and the GLX windowing
+ system interface, the variant contains a QGLXNativeContext. On other
+ platforms a different class will be used. These classes are all placed in
+ the Qt Platform Headers module.
+
+ Platform headers can be used in conjunction with
+ QGuiApplication::platformFunction() to give a type safe interface to
+ platform specific functionality. It is possible for headers defined in
+ QtPlatformHeaders to define typedefs for functions that can be returned by
+ a platform plugin from QGuiApplication::platformFunction(). Headers in
+ QtPlatformHeaders can also implement wrapper functions for the function
+ pointer, giving a static function that can be called from any context after
+ the platform integration has been created. An implementation of this
+ pattern is QXcbWindowFunctions::setWmWindowType(). This function retrieves
+ a function pointer from QGuiApplication::platformFunction, and executes
+ that function if the requested function was returned.
+
+ \note Similar to the other QPA APIs, there are no binary compatibility
+ guarantees for these classes, meaning that an application using these
+ classes is only guaranteed to work with the Qt version it was developed
+ against. Unlike QPA however, source compatibility is guaranteed.
+
+ \sa QXcbWindowFunctions
+ */
diff --git a/src/platformheaders/eglfsfunctions/eglfsfunctions.pri b/src/platformheaders/eglfsfunctions/eglfsfunctions.pri
new file mode 100644
index 0000000000..e4e645f5a5
--- /dev/null
+++ b/src/platformheaders/eglfsfunctions/eglfsfunctions.pri
@@ -0,0 +1 @@
+HEADERS += $$PWD/qeglfsfunctions.h
diff --git a/src/plugins/platforms/winrt/qwinrtplatformtheme.cpp b/src/platformheaders/eglfsfunctions/qeglfsfunctions.h
index d4034ec571..702d0b2f8c 100644
--- a/src/plugins/platforms/winrt/qwinrtplatformtheme.cpp
+++ b/src/platformheaders/eglfsfunctions/qeglfsfunctions.h
@@ -39,38 +39,29 @@
**
****************************************************************************/
-#include "qwinrtplatformtheme.h"
-#include "qwinrtplatformmessagedialoghelper.h"
+#ifndef QEGLFSFUNCTIONS_H
+#define QEGLFSFUNCTIONS_H
-QT_BEGIN_NAMESPACE
+#include <QtCore/QByteArray>
+#include <QtGui/QGuiApplication>
-QWinRTPlatformTheme::QWinRTPlatformTheme()
-{
-}
+QT_BEGIN_NAMESPACE
-bool QWinRTPlatformTheme::usePlatformNativeDialog(QPlatformTheme::DialogType type) const
+class QEglFSFunctions
{
-#if !(defined(Q_OS_WINPHONE) && _MSC_VER<=1700)
- if (type == QPlatformTheme::MessageDialog)
- return true;
-#else
- Q_UNUSED(type)
-#endif // !(Q_OS_WINPHONE && _MSC_VER<=1700)
- return false;
-}
+public:
+ typedef void (*LoadKeymapType)(const QString &filename);
+ static QByteArray loadKeymapTypeIdentifier() { return QByteArrayLiteral("EglFSLoadKeymap"); }
-QPlatformDialogHelper *QWinRTPlatformTheme::createPlatformDialogHelper(QPlatformTheme::DialogType type) const
-{
-#if !(defined(Q_OS_WINPHONE) && _MSC_VER<=1700)
- switch (type) {
- case QPlatformTheme::MessageDialog:
- return new QWinRTPlatformMessageDialogHelper();
- default:
- return QPlatformTheme::createPlatformDialogHelper(type);
+ static void loadKeymap(const QString &filename)
+ {
+ LoadKeymapType func = reinterpret_cast<LoadKeymapType>(QGuiApplication::platformFunction(loadKeymapTypeIdentifier()));
+ if (func)
+ func(filename);
}
-#else // !(Q_OS_WINPHONE && _MSC_VER<=1700)
- return QPlatformTheme::createPlatformDialogHelper(type);
-#endif // Q_OS_WINPHONE && _MSC_VER<=1700
-}
+};
+
QT_END_NAMESPACE
+
+#endif // QEGLFSFUNCTIONS_H
diff --git a/src/platformheaders/eglfsfunctions/qeglfsfunctions.qdoc b/src/platformheaders/eglfsfunctions/qeglfsfunctions.qdoc
new file mode 100644
index 0000000000..b8dae9b13f
--- /dev/null
+++ b/src/platformheaders/eglfsfunctions/qeglfsfunctions.qdoc
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QEglFSFunctions
+ \inmodule QtPlatformHeaders
+
+ \brief The QEglFSFunctions class is an inline class containing
+ platform-specific functionality for the eglfs platform plugin that is
+ typically used on systems running Embedded Linux or Android.
+
+ \note There is no binary compatibility guarantee for this class,
+ meaning that an application using it is only guaranteed to work with the Qt
+ version it was developed against.
+*/
+
+/*!
+ \typedef QEglFSFunctions::LoadKeymapType
+
+ Function type for loadKeymap.
+*/
+
+/*!
+ \fn QByteArray QEglFSFunctions::loadKeymapTypeIdentifier()
+
+ \return the identifier that can be passed to
+ QGuiApplication::platformFunction() to query the entry point for the
+ loadKeymap function implementation.
+*/
+
+/*!
+ \fn void QEglFSFunctions::loadKeymap(const QString &filename)
+
+ Loads and switches to the keymap from \a filename. When \a filename is
+ empty, the default keymap, which is either the built-on one or the keymap
+ given in the plugin specification, is restored.
+
+ \note This is functional only when the evdev keyboard support code is
+ compiled in to the platform plugin. When using external generic plugins via
+ the \c{-plugin} argument, or when the environment variable
+ \c{QT_QPA_EGLFS_DISABLE_INPUT} is set or when building Qt without evdev
+ support, this function will have no effect.
+*/
diff --git a/src/platformheaders/nativecontexts/nativecontexts.pri b/src/platformheaders/nativecontexts/nativecontexts.pri
new file mode 100644
index 0000000000..cfb190e4fa
--- /dev/null
+++ b/src/platformheaders/nativecontexts/nativecontexts.pri
@@ -0,0 +1,4 @@
+HEADERS += $$PWD/qglxnativecontext.h \
+ $$PWD/qeglnativecontext.h \
+ $$PWD/qcocoanativecontext.h \
+ $$PWD/qwglnativecontext.h
diff --git a/src/platformheaders/nativecontexts/qcocoanativecontext.h b/src/platformheaders/nativecontexts/qcocoanativecontext.h
new file mode 100644
index 0000000000..34994089c4
--- /dev/null
+++ b/src/platformheaders/nativecontexts/qcocoanativecontext.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/legal
+ **
+ ** 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 Digia. For licensing terms and
+ ** conditions see http://qt.digia.com/licensing. For further information
+ ** use the contact form at http://qt.digia.com/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 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Digia gives you certain additional
+ ** rights. These rights are described in the Digia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU
+ ** General Public License version 3.0 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU General Public License version 3.0 requirements will be
+ ** met: http://www.gnu.org/copyleft/gpl.html.
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#ifndef QCOCOANATIVECONTEXT_H
+#define QCOCOANATIVECONTEXT_H
+
+#include <QtCore/QMetaType>
+#include <AppKit/NSOpenGL.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QCocoaNativeContext
+{
+ QCocoaNativeContext()
+ : m_context(0)
+ { }
+
+ QCocoaNativeContext(NSOpenGLContext *ctx)
+ : m_context(ctx)
+ { }
+
+ NSOpenGLContext *context() const { return m_context; }
+
+private:
+ NSOpenGLContext *m_context;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QCocoaNativeContext)
+
+#endif // QCOCOANATIVECONTEXT_H
diff --git a/src/platformheaders/nativecontexts/qcocoanativecontext.qdoc b/src/platformheaders/nativecontexts/qcocoanativecontext.qdoc
new file mode 100644
index 0000000000..96b33ce5f8
--- /dev/null
+++ b/src/platformheaders/nativecontexts/qcocoanativecontext.qdoc
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QCocoaNativeContext
+ \inmodule QtPlatformHeaders
+ \since 5.4
+
+ \brief A class encapsulating a Cocoa NSOpenGLContext.
+
+ \note There is no binary compatibility guarantee for this class, meaning
+ that an application using it is only guaranteed to work with the Qt version it was
+ developed against.
+
+ \sa QOpenGLContext::setNativeHandle(), QOpenGLContext::nativeHandle()
+ */
+
+/*!
+ \fn NSOpenGLContext *QCocoaNativeContext::context() const
+
+ \return the context.
+ */
+
+/*!
+ \fn QCocoaNativeContext::QCocoaNativeContext()
+
+ Construct a new instance with no handles.
+ */
+
+/*!
+ \fn QCocoaNativeContext::QCocoaNativeContext(NSOpenGLContext *ctx)
+
+ Constructs a new instance with the provided \a ctx handle.
+ */
diff --git a/src/platformheaders/nativecontexts/qeglnativecontext.h b/src/platformheaders/nativecontexts/qeglnativecontext.h
new file mode 100644
index 0000000000..a2411419ef
--- /dev/null
+++ b/src/platformheaders/nativecontexts/qeglnativecontext.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEGLNATIVECONTEXT_H
+#define QEGLNATIVECONTEXT_H
+
+#include <QtCore/QMetaType>
+#include <EGL/egl.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QEGLNativeContext
+{
+ QEGLNativeContext()
+ : m_context(0),
+ m_display(0)
+ { }
+
+ QEGLNativeContext(EGLContext ctx, EGLDisplay dpy)
+ : m_context(ctx),
+ m_display(dpy)
+ { }
+
+ EGLContext context() const { return m_context; }
+ EGLDisplay display() const { return m_display; }
+
+private:
+ EGLContext m_context;
+ EGLDisplay m_display;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QEGLNativeContext)
+
+#endif // QEGLNATIVECONTEXT_H
diff --git a/src/platformheaders/nativecontexts/qeglnativecontext.qdoc b/src/platformheaders/nativecontexts/qeglnativecontext.qdoc
new file mode 100644
index 0000000000..edadbdfa83
--- /dev/null
+++ b/src/platformheaders/nativecontexts/qeglnativecontext.qdoc
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QEGLNativeContext
+ \inmodule QtPlatformHeaders
+ \since 5.4
+
+ \brief A class encapsulating an EGL context and display handle
+
+ \note There is no binary compatibility guarantee for this class, meaning
+ that an application using it is only guaranteed to work with the Qt version it was
+ developed against.
+
+ \sa QOpenGLContext::setNativeHandle(), QOpenGLContext::nativeHandle()
+ */
+
+/*!
+ \fn EGLContext QEGLNativeContext::context() const
+
+ \return the EGL context.
+ */
+
+/*!
+ \fn EGLDisplay QEGLNativeContext::display() const
+
+ \return the EGL display.
+ */
+
+/*!
+ \fn QEGLNativeContext::QEGLNativeContext()
+
+ Construct a new instance with no handles.
+ */
+
+/*!
+ \fn QEGLNativeContext::QEGLNativeContext(EGLContext ctx, EGLDisplay dpy)
+
+ Constructs a new instance with the provided \a ctx and \a dpy handles.
+ */
diff --git a/src/platformheaders/nativecontexts/qglxnativecontext.h b/src/platformheaders/nativecontexts/qglxnativecontext.h
new file mode 100644
index 0000000000..21ae334c25
--- /dev/null
+++ b/src/platformheaders/nativecontexts/qglxnativecontext.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGLXNATIVECONTEXT_H
+#define QGLXNATIVECONTEXT_H
+
+#include <QtCore/QMetaType>
+#include <X11/Xlib.h>
+#include <GL/glx.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QGLXNativeContext
+{
+ QGLXNativeContext()
+ : m_context(0),
+ m_display(0),
+ m_window(0),
+ m_visualId(0)
+ { }
+
+ QGLXNativeContext(GLXContext ctx, Display *dpy = 0, Window wnd = 0, VisualID vid = 0)
+ : m_context(ctx),
+ m_display(dpy),
+ m_window(wnd),
+ m_visualId(vid)
+ { }
+
+ GLXContext context() const { return m_context; }
+ Display *display() const { return m_display; }
+ Window window() const { return m_window; }
+ VisualID visualId() const { return m_visualId; }
+
+private:
+ GLXContext m_context;
+ Display *m_display;
+ Window m_window;
+ VisualID m_visualId;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QGLXNativeContext)
+
+#endif // QGLXNATIVECONTEXT_H
diff --git a/src/platformheaders/nativecontexts/qglxnativecontext.qdoc b/src/platformheaders/nativecontexts/qglxnativecontext.qdoc
new file mode 100644
index 0000000000..81f3c0b2ca
--- /dev/null
+++ b/src/platformheaders/nativecontexts/qglxnativecontext.qdoc
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QGLXNativeContext
+ \inmodule QtPlatformHeaders
+ \since 5.4
+
+ \brief A class encapsulating a GLXContext and related native handles.
+
+ \note Only context() is guaranteed to be valid. The other handles may be all \c 0. They are
+ useful however when QOpenGLContext::setNativeHandle() is used to adopt a legacy context
+ created by glXCreateContext. To adopt such a context, either the Window or VisualID
+ that had been used to create the context needs to be known, otherwise the adoption will
+ fail. For modern contexts created with an FBConfig, these are not necessary, the
+ GLXContext itself is sufficient. The Display is optional.
+
+ \note There is no binary compatibility guarantee for this class, meaning
+ that an application using it is only guaranteed to work with the Qt version it was
+ developed against.
+
+ \sa QOpenGLContext::setNativeHandle(), QOpenGLContext::nativeHandle()
+ */
+
+/*!
+ \fn GLXContext QGLXNativeContext::context() const
+
+ \return the GLXContext.
+ */
+
+/*!
+ \fn Display *QGLXNativeContext::display() const
+
+ \return a pointer to the X11 display or \c NULL if not available.
+ */
+
+/*!
+ \fn Window QGLXNativeContext::window() const
+
+ \return the X11 Window or \c 0 if not available.
+ */
+
+/*!
+ \fn VisualID QGLXNativeContext::visualId() const
+
+ \return the X11 visual ID or \c 0 if not available.
+ */
+
+/*!
+ \fn QGLXNativeContext::QGLXNativeContext()
+
+ Construct a new instance with no handles.
+ */
+
+/*!
+ \fn QGLXNativeContext::QGLXNativeContext(GLXContext ctx, Display *dpy = 0, Window wnd = 0, VisualID vid = 0)
+
+ Constructs a new instance with the provided \a ctx, \a dpy, \a wnd, \a vid handles.
+ */
diff --git a/src/platformheaders/nativecontexts/qwglnativecontext.h b/src/platformheaders/nativecontexts/qwglnativecontext.h
new file mode 100644
index 0000000000..4a68633703
--- /dev/null
+++ b/src/platformheaders/nativecontexts/qwglnativecontext.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWGLNATIVECONTEXT_H
+#define QWGLNATIVECONTEXT_H
+
+#include <QtCore/QMetaType>
+#include <wingdi.h>
+#include <GL/gl.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWGLNativeContext
+{
+public:
+ QWGLNativeContext()
+ : m_context(0),
+ m_window(0)
+ { }
+
+ QWGLNativeContext(HGLRC ctx, HWND wnd)
+ : m_context(ctx),
+ m_window(wnd)
+ { }
+
+ HGLRC context() const { return m_context; }
+ HWND window() const { return m_window; }
+
+private:
+ HGLRC m_context;
+ HWND m_window;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QWGLNativeContext)
+
+#endif // QWGLNATIVECONTEXT_H
diff --git a/src/platformheaders/nativecontexts/qwglnativecontext.qdoc b/src/platformheaders/nativecontexts/qwglnativecontext.qdoc
new file mode 100644
index 0000000000..86ae291aaa
--- /dev/null
+++ b/src/platformheaders/nativecontexts/qwglnativecontext.qdoc
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QWGLNativeContext
+ \inmodule QtPlatformHeaders
+ \since 5.4
+
+ \brief A class encapsulating a WGL context on Windows with desktop OpenGL (opengl32.dll)
+
+ \note There is no binary compatibility guarantee for this class,
+ meaning that an application using it is only guaranteed to work with the Qt
+ version it was developed against.
+
+ QWGLNativeContext is a value class that can be passed to
+ QOpenGLContext::setNativeHandle(). When creating a QOpenGLContext with the
+ native handle set, no new context will get created. Instead, the provided
+ handles are used, without taking ownership. This allows wrapping a context
+ created by an external framework or rendering engine. The typical usage will
+ be similar to the following snippet:
+
+ \code
+ #include <QtPlatformSupport/QWGLNativeContext>
+ ...create and retrieve the WGL context and the corresponding window...
+ QOpenGLContext *context = new QOpenGLContext;
+ QWGLNativeContext nativeContext(hglrc, hwnd);
+ context->setNativeHandle(QVariant::fromValue(nativeContext));
+ context->create();
+ ...
+ \endcode
+
+ The window is needed because the its pixel format will be queried. When the
+ adoption is successful, QOpenGLContext::format() will return a QSurfaceFormat
+ describing this pixel format.
+
+ It is recommended to restrict the usage of QOpenGLContexts created this way.
+ Various platform-specific behavior and issues may prevent such contexts to be
+ made current with windows (surfaces) created by Qt due to non-matching pixel
+ formats for example. A potentially safer solution is to use the wrapped
+ context only to set up sharing and perform Qt-based rendering offscreen,
+ using a separate, dedicated QOpenGLContext. The resulting textures are then
+ accessible in the foreign context too.
+
+ \code
+ ...like above...
+ QOpenGLContext *qtcontext = new QOpenGLContext;
+ qtcontext->setShareContext(context);
+ qtcontext->setFormat(context->format());
+ qtcontext->create();
+ ...use qtcontext for rendering with Qt...
+ \endcode
+
+ In addition to being used with QOpenGLContext::setNativeHandle(), this class
+ is used also to retrieve the native context handle, that is, a HGLRC value,
+ from a QOpenGLContext. Calling QOpenGLContext::nativeHandle() returns a
+ QVariant which, on Windows with opengl32.dll at least, will contain a
+ QWGLNativeContext:
+
+ \code
+ QVariant nativeHandle = context->nativeHandle();
+ if (!nativeHandle.isNull() && nativeHandle.canConvert<QWGLNativeContext>()) {
+ QWGLNativeContext nativeContext = nativeHandle.value<QWGLNativeContext>();
+ HGLRC hglrc = nativeContext.context();
+ ...
+ }
+ \endcode
+
+ \sa QOpenGLContext::setNativeHandle(), QOpenGLContext::nativeHandle()
+ */
+
+/*!
+ \fn HGLRC QWGLNativeContext::context() const
+
+ \return the WGL context.
+ */
+
+/*!
+ \fn HWND QWGLNativeContext::window() const
+
+ \note The window handle is not available when the QWGLNativeContext is
+ queried from a regular, non-adopted QOpenGLContext using
+ QOpenGLContext::nativeHandle(). This is because the \e windows platform
+ plugin creates WGL contexts using a dummy window that is not available
+ afterwards. Instead, the native window handle (HWND) is queriable from a
+ QWindow via QPlatformNativeInterface::nativeResourceForWindow() using the \e
+ "handle" resource key. Note however that the window will not have its pixel
+ format set until it is first associated with a context via
+ QOpenGLContext::makeCurrent().
+
+ \return handle for the window for which the context was created.
+ */
+
+/*!
+ \fn QWGLNativeContext::QWGLNativeContext()
+
+ Construct a new instance with no handles.
+ */
+
+/*!
+ \fn QWGLNativeContext::QWGLNativeContext(HGLRC ctx, HWND wnd)
+
+ Constructs a new instance with the provided \a ctx context handle and \a wnd window handle.
+
+ \note The window specified by \a wnd must have its pixel format set to a
+ format compatible with the context's. If no SetPixelFormat() call was made on
+ any device context belonging to the window, adopting the context will fail.
+ */
diff --git a/src/platformheaders/platformheaders.pro b/src/platformheaders/platformheaders.pro
new file mode 100644
index 0000000000..a3132ecf23
--- /dev/null
+++ b/src/platformheaders/platformheaders.pro
@@ -0,0 +1,14 @@
+# Only headers here, no library is wanted.
+TEMPLATE = subdirs
+VERSION = $$MODULE_VERSION
+MODULE_INCNAME = QtPlatformHeaders
+
+include(nativecontexts/nativecontexts.pri)
+include(xcbfunctions/xcbfunctions.pri)
+include(eglfsfunctions/eglfsfunctions.pri)
+
+QMAKE_DOCS = $$PWD/doc/qtplatformheaders.qdocconf
+
+load(qt_module_headers)
+load(qt_docs)
+load(qt_installs)
diff --git a/src/platformheaders/xcbfunctions/qxcbwindowfunctions.h b/src/platformheaders/xcbfunctions/qxcbwindowfunctions.h
new file mode 100644
index 0000000000..48fc0c13b6
--- /dev/null
+++ b/src/platformheaders/xcbfunctions/qxcbwindowfunctions.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXCBWINDOWFUNCTIONS_H
+#define QXCBWINDOWFUNCTIONS_H
+
+#include <QtCore/QByteArray>
+#include <QtGui/QGuiApplication>
+
+QT_BEGIN_NAMESPACE
+
+class QWindow;
+
+class QXcbWindowFunctions {
+public:
+ enum WmWindowType {
+ Normal = 0x000001,
+ Desktop = 0x000002,
+ Dock = 0x000004,
+ Toolbar = 0x000008,
+ Menu = 0x000010,
+ Utility = 0x000020,
+ Splash = 0x000040,
+ Dialog = 0x000080,
+ DropDownMenu = 0x000100,
+ PopupMenu = 0x000200,
+ Tooltip = 0x000400,
+ Notification = 0x000800,
+ Combo = 0x001000,
+ Dnd = 0x002000,
+ KdeOverride = 0x004000
+ };
+
+ Q_DECLARE_FLAGS(WmWindowTypes, WmWindowType)
+
+ typedef void (*SetWmWindowType)(QWindow *window, QXcbWindowFunctions::WmWindowTypes windowType);
+ static const QByteArray setWmWindowTypeIdentifier() { return QByteArrayLiteral("XcbSetWmWindowType"); }
+
+ static void setWmWindowType(QWindow *window, WmWindowType type)
+ {
+ SetWmWindowType func = reinterpret_cast<SetWmWindowType>(QGuiApplication::platformFunction(setWmWindowTypeIdentifier()));
+ if (func)
+ func(window, type);
+ }
+};
+
+
+QT_END_NAMESPACE
+
+#endif // QXCBWINDOWFUNCTIONS_H
diff --git a/src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc b/src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc
new file mode 100644
index 0000000000..458dbb213d
--- /dev/null
+++ b/src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QXcbWindowFunctions
+ \inmodule QtPlatformHeaders
+
+ \brief The QXcbWindowFunctions class is an inline class containing
+ miscellaneous functionality for xcb window specific functionality.
+
+ A commen usage pattern is as follows:
+ \snippet qxcbwindowfunctions/main.cpp 0
+
+ \note There is no binary compatibility guarantee for this class,
+ meaning that an application using it is only guaranteed to work with the Qt
+ version it was developed against.
+*/
+
+/*!
+ \enum QXcbWindowFunctions::WmWindowType
+
+ This enum represents the supported WM_WINDOW_TYPE atoms.
+
+ \value Normal
+ \value Desktop
+ \value Dock
+ \value Toolbar
+ \value Menu
+ \value Utility
+ \value Splash
+ \value Dialog
+ \value DropDownMenu
+ \value PopupMenu
+ \value Tooltip
+ \value Notification
+ \value Combo
+ \value Dnd
+ \value KdeOverride
+*/
+
+/*!
+ \typedef QXcbWindowFunctions::SetWmWindowType
+
+ This is the typedef for the function returned by QGuiApplication::platformFunction when passed setWmWindowTypeIdentifier.
+*/
+
+/*!
+ \fn QByteArray QXcbWindowFunctions::setWmWindowTypeIdentifier()
+
+ This function returnes the bytearray that can be used to query
+ QGuiApplication::platformFunction to retrieve the SetWmWindowType function.
+*/
+
+/*!
+ \fn void QXcbWindowFunctions::setWmWindowType(QWindow *window, WmWindowType type)
+
+ This is a convenience function that can be used directly instead of resolving the function pointer.
+ \a window and \a type will be relayed to the function retrieved by QGuiApplication
+*/
diff --git a/src/platformheaders/xcbfunctions/xcbfunctions.pri b/src/platformheaders/xcbfunctions/xcbfunctions.pri
new file mode 100644
index 0000000000..8844913cd1
--- /dev/null
+++ b/src/platformheaders/xcbfunctions/xcbfunctions.pri
@@ -0,0 +1 @@
+HEADERS += $$PWD/qxcbwindowfunctions.h
diff --git a/src/platformsupport/accessibility/accessibility.pri b/src/platformsupport/accessibility/accessibility.pri
new file mode 100644
index 0000000000..fb56edbf1a
--- /dev/null
+++ b/src/platformsupport/accessibility/accessibility.pri
@@ -0,0 +1,9 @@
+contains(QT_CONFIG, accessibility) {
+ INCLUDEPATH += $$PWD
+
+ HEADERS += \
+ $$PWD/qaccessiblebridgeutils_p.h
+
+ SOURCES += \
+ $$PWD/qaccessiblebridgeutils.cpp
+}
diff --git a/src/platformsupport/accessibility/qaccessiblebridgeutils.cpp b/src/platformsupport/accessibility/qaccessiblebridgeutils.cpp
new file mode 100644
index 0000000000..7140bb6e2d
--- /dev/null
+++ b/src/platformsupport/accessibility/qaccessiblebridgeutils.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qaccessiblebridgeutils_p.h"
+#include <QtCore/qmath.h>
+
+#ifndef QT_NO_ACCESSIBILITY
+
+QT_BEGIN_NAMESPACE
+
+namespace QAccessibleBridgeUtils {
+
+static bool performAction(QAccessibleInterface *iface, const QString &actionName)
+{
+ if (QAccessibleActionInterface *actionIface = iface->actionInterface()) {
+ if (actionIface->actionNames().contains(actionName)) {
+ actionIface->doAction(actionName);
+ return true;
+ }
+ }
+ return false;
+}
+
+QStringList effectiveActionNames(QAccessibleInterface *iface)
+{
+ QStringList actions;
+ if (QAccessibleActionInterface *actionIface = iface->actionInterface())
+ actions = actionIface->actionNames();
+
+ if (iface->valueInterface()) {
+ if (!actions.contains(QAccessibleActionInterface::increaseAction()))
+ actions << QAccessibleActionInterface::increaseAction();
+ if (!actions.contains(QAccessibleActionInterface::decreaseAction()))
+ actions << QAccessibleActionInterface::decreaseAction();
+ }
+ return actions;
+}
+
+bool performEffectiveAction(QAccessibleInterface *iface, const QString &actionName)
+{
+ if (!iface)
+ return false;
+ if (performAction(iface, actionName))
+ return true;
+ if (actionName != QAccessibleActionInterface::increaseAction()
+ && actionName != QAccessibleActionInterface::decreaseAction())
+ return false;
+
+ QAccessibleValueInterface *valueIface = iface->valueInterface();
+ if (!valueIface)
+ return false;
+ bool success;
+ const QVariant currentVariant = valueIface->currentValue();
+ double stepSize = valueIface->minimumStepSize().toDouble(&success);
+ if (!success || qFuzzyIsNull(stepSize)) {
+ const double min = valueIface->minimumValue().toDouble(&success);
+ if (!success)
+ return false;
+ const double max = valueIface->maximumValue().toDouble(&success);
+ if (!success)
+ return false;
+ stepSize = (max - min) / 10; // this is pretty arbitrary, we just need to provide something
+ const int typ = currentVariant.type();
+ if (typ != QMetaType::Float && typ != QMetaType::Double) {
+ // currentValue is an integer. Round it up to ensure stepping in case it was below 1
+ stepSize = qCeil(stepSize);
+ }
+ }
+ const double current = currentVariant.toDouble(&success);
+ if (!success)
+ return false;
+ if (actionName == QAccessibleActionInterface::decreaseAction())
+ stepSize = -stepSize;
+ valueIface->setCurrentValue(current + stepSize);
+ return true;
+}
+
+} //namespace
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/text/qrawfont_qpa.cpp b/src/platformsupport/accessibility/qaccessiblebridgeutils_p.h
index 7de6ef0e8b..d05934b844 100644
--- a/src/gui/text/qrawfont_qpa.cpp
+++ b/src/platformsupport/accessibility/qaccessiblebridgeutils_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -39,32 +39,23 @@
**
****************************************************************************/
-#include <QtCore/qglobal.h>
+#ifndef QACCESSIBLEBRIDGEUTILS_H
+#define QACCESSIBLEBRIDGEUTILS_H
-#if !defined(QT_NO_RAWFONT)
+#ifndef QT_NO_ACCESSIBILITY
-#include "qrawfont_p.h"
-#include <qpa/qplatformintegration.h>
-#include <qpa/qplatformfontdatabase.h>
-#include <private/qguiapplication_p.h>
+#include <QtCore/qstringlist.h>
+#include <QtGui/qaccessible.h>
QT_BEGIN_NAMESPACE
-void QRawFontPrivate::platformCleanUp()
-{
-}
-
-void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData, qreal pixelSize,
- QFont::HintingPreference hintingPreference)
-{
- Q_ASSERT(fontEngine == 0);
-
- QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
- fontEngine = pfdb->fontEngine(fontData, pixelSize, hintingPreference);
- if (fontEngine != 0)
- fontEngine->ref.ref();
+namespace QAccessibleBridgeUtils {
+ QStringList effectiveActionNames(QAccessibleInterface *iface);
+ bool performEffectiveAction(QAccessibleInterface *iface, const QString &actionName);
}
QT_END_NAMESPACE
-#endif // QT_NO_RAWFONT
+#endif
+
+#endif //QACCESSIBLEBRIDGEUTILS_H
diff --git a/src/platformsupport/eglconvenience/eglconvenience.pri b/src/platformsupport/eglconvenience/eglconvenience.pri
index 7600cc952b..8ada53d2c1 100644
--- a/src/platformsupport/eglconvenience/eglconvenience.pri
+++ b/src/platformsupport/eglconvenience/eglconvenience.pri
@@ -40,15 +40,4 @@ contains(QT_CONFIG,egl) {
$$PWD/qxlibeglintegration.cpp
}
CONFIG += egl
-
-} else: contains(QT_CONFIG,dynamicgl) {
- HEADERS += \
- $$PWD/qeglconvenience_p.h \
- $$PWD/qeglplatformcontext_p.h \
- $$PWD/qeglpbuffer_p.h
-
- SOURCES += \
- $$PWD/qeglconvenience.cpp \
- $$PWD/qeglplatformcontext.cpp \
- $$PWD/qeglpbuffer.cpp
}
diff --git a/src/platformsupport/eglconvenience/qeglcompositor.cpp b/src/platformsupport/eglconvenience/qeglcompositor.cpp
index 0e0a2d9375..028f92f3cf 100644
--- a/src/platformsupport/eglconvenience/qeglcompositor.cpp
+++ b/src/platformsupport/eglconvenience/qeglcompositor.cpp
@@ -105,6 +105,29 @@ void QEGLCompositor::renderAll()
windows.at(i)->composited();
}
+struct BlendStateBinder
+{
+ BlendStateBinder() : m_blend(false) {
+ glDisable(GL_BLEND);
+ }
+ void set(bool blend) {
+ if (blend != m_blend) {
+ if (blend) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ } else {
+ glDisable(GL_BLEND);
+ }
+ m_blend = blend;
+ }
+ }
+ ~BlendStateBinder() {
+ if (m_blend)
+ glDisable(GL_BLEND);
+ }
+ bool m_blend;
+};
+
void QEGLCompositor::render(QEGLPlatformWindow *window)
{
const QPlatformTextureList *textures = window->textures();
@@ -114,29 +137,37 @@ void QEGLCompositor::render(QEGLPlatformWindow *window)
const QRect targetWindowRect(QPoint(0, 0), window->screen()->geometry().size());
glViewport(0, 0, targetWindowRect.width(), targetWindowRect.height());
+ float currentOpacity = 1.0f;
+ BlendStateBinder blend;
+
for (int i = 0; i < textures->count(); ++i) {
uint textureId = textures->textureId(i);
glBindTexture(GL_TEXTURE_2D, textureId);
QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i),
targetWindowRect);
+ const float opacity = window->window()->opacity();
+ if (opacity != currentOpacity) {
+ currentOpacity = opacity;
+ m_blitter->setOpacity(currentOpacity);
+ }
if (textures->count() > 1 && i == textures->count() - 1) {
// Backingstore for a widget with QOpenGLWidget subwidgets
- m_blitter->setSwizzleRB(true);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ blend.set(true);
m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
- glDisable(GL_BLEND);
} else if (textures->count() == 1) {
// A regular QWidget window
- m_blitter->setSwizzleRB(true);
+ const bool translucent = window->window()->requestedFormat().alphaBufferSize() > 0;
+ blend.set(translucent);
m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
} else {
// Texture from an FBO belonging to a QOpenGLWidget
- m_blitter->setSwizzleRB(false);
+ blend.set(false);
m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginBottomLeft);
}
}
+
+ m_blitter->setOpacity(1.0f);
}
QEGLCompositor *QEGLCompositor::instance()
diff --git a/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp b/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp
index ab92bac37d..3cb31e36ec 100644
--- a/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp
+++ b/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp
@@ -41,6 +41,7 @@
#include <QtGui/QOpenGLShaderProgram>
#include <QtGui/QOpenGLContext>
+#include <QtGui/QPainter>
#include "qeglplatformbackingstore_p.h"
#include "qeglcompositor_p.h"
@@ -209,9 +210,16 @@ void QEGLPlatformBackingStore::composited()
}
}
-void QEGLPlatformBackingStore::beginPaint(const QRegion &rgn)
+void QEGLPlatformBackingStore::beginPaint(const QRegion &region)
{
- m_dirty |= rgn;
+ m_dirty |= region;
+
+ if (m_image.hasAlphaChannel()) {
+ QPainter p(&m_image);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ foreach (const QRect &r, region.rects())
+ p.fillRect(r, Qt::transparent);
+ }
}
void QEGLPlatformBackingStore::resize(const QSize &size, const QRegion &staticContents)
@@ -223,7 +231,8 @@ void QEGLPlatformBackingStore::resize(const QSize &size, const QRegion &staticCo
if (!dstWin || (!dstWin->isRaster() && dstWin->window()->surfaceType() != QSurface::RasterGLSurface))
return;
- m_image = QImage(size, QImage::Format_RGB32);
+ m_image = QImage(size, QImage::Format_RGBA8888);
+
m_window->create();
screen->compositingContext()->makeCurrent(dstWin->window());
diff --git a/src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h b/src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h
index cb1e5999b0..8b0566afa6 100644
--- a/src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h
+++ b/src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h
@@ -61,7 +61,7 @@ public:
QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
- void beginPaint(const QRegion &) Q_DECL_OVERRIDE;
+ void beginPaint(const QRegion &region) Q_DECL_OVERRIDE;
void flush(QWindow *window, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE;
diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
index eec6463c21..9691d12682 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
+++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
@@ -44,6 +44,7 @@
#include "qeglpbuffer_p.h"
#include <qpa/qplatformwindow.h>
#include <QOpenGLContext>
+#include <QtPlatformHeaders/QEGLNativeContext>
#include <QDebug>
QT_BEGIN_NAMESPACE
@@ -108,25 +109,21 @@ QT_BEGIN_NAMESPACE
#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
#endif
-QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display)
- : m_eglDisplay(display)
- , m_eglConfig(q_configFromGLFormat(display, format))
- , m_swapInterval(-1)
- , m_swapIntervalEnvChecked(false)
- , m_swapIntervalFromEnv(-1)
-{
- init(format, share);
-}
-
QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
- EGLConfig config)
+ EGLConfig *config, const QVariant &nativeHandle)
: m_eglDisplay(display)
- , m_eglConfig(config)
, m_swapInterval(-1)
, m_swapIntervalEnvChecked(false)
, m_swapIntervalFromEnv(-1)
{
- init(format, share);
+ if (nativeHandle.isNull()) {
+ m_eglConfig = config ? *config : q_configFromGLFormat(display, format);
+ m_ownsContext = true;
+ init(format, share);
+ } else {
+ m_ownsContext = false;
+ adopt(nativeHandle, share);
+ }
}
void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLContext *share)
@@ -198,6 +195,59 @@ void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLCont
q_printEglConfig(m_eglDisplay, m_eglConfig);
}
+ updateFormatFromGL();
+}
+
+void QEGLPlatformContext::adopt(const QVariant &nativeHandle, QPlatformOpenGLContext *share)
+{
+ if (!nativeHandle.canConvert<QEGLNativeContext>()) {
+ qWarning("QEGLPlatformContext: Requires a QEGLNativeContext");
+ return;
+ }
+ QEGLNativeContext handle = nativeHandle.value<QEGLNativeContext>();
+ EGLContext context = handle.context();
+ if (!context) {
+ qWarning("QEGLPlatformContext: No EGLContext given");
+ return;
+ }
+
+ // A context belonging to a given EGLDisplay cannot be used with another one.
+ if (handle.display() != m_eglDisplay) {
+ qWarning("QEGLPlatformContext: Cannot adopt context from different display");
+ return;
+ }
+
+ // Figure out the EGLConfig.
+ EGLint value = 0;
+ eglQueryContext(m_eglDisplay, context, EGL_CONFIG_ID, &value);
+ EGLint n = 0;
+ EGLConfig cfg;
+ const EGLint attribs[] = { EGL_CONFIG_ID, value, EGL_NONE };
+ if (eglChooseConfig(m_eglDisplay, attribs, &cfg, 1, &n) && n == 1) {
+ m_eglConfig = cfg;
+ m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig);
+ } else {
+ qWarning("QEGLPlatformContext: Failed to get framebuffer configuration for context");
+ }
+
+ // Fetch client API type.
+ value = 0;
+ eglQueryContext(m_eglDisplay, context, EGL_CONTEXT_CLIENT_TYPE, &value);
+ if (value == EGL_OPENGL_API || value == EGL_OPENGL_ES_API) {
+ m_api = value;
+ eglBindAPI(m_api);
+ } else {
+ qWarning("QEGLPlatformContext: Failed to get client API type");
+ m_api = EGL_OPENGL_ES_API;
+ }
+
+ m_eglContext = context;
+ m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : 0;
+ updateFormatFromGL();
+}
+
+void QEGLPlatformContext::updateFormatFromGL()
+{
#ifndef QT_NO_OPENGL
// Make the context current to ensure the GL version query works. This needs a surface too.
const EGLint pbufferAttributes[] = {
@@ -296,10 +346,10 @@ bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface)
QEGLPlatformContext::~QEGLPlatformContext()
{
- if (m_eglContext != EGL_NO_CONTEXT) {
+ if (m_ownsContext && m_eglContext != EGL_NO_CONTEXT)
eglDestroyContext(m_eglDisplay, m_eglContext);
- m_eglContext = EGL_NO_CONTEXT;
- }
+
+ m_eglContext = EGL_NO_CONTEXT;
}
void QEGLPlatformContext::doneCurrent()
diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h
index 714633c3bc..82f062c4a4 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h
+++ b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h
@@ -44,6 +44,7 @@
#include <qpa/qplatformwindow.h>
#include <qpa/qplatformopenglcontext.h>
+#include <QtCore/QVariant>
#include <EGL/egl.h>
QT_BEGIN_NAMESPACE
@@ -51,9 +52,8 @@ QT_BEGIN_NAMESPACE
class QEGLPlatformContext : public QPlatformOpenGLContext
{
public:
- QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display);
QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
- EGLConfig config);
+ EGLConfig *config = 0, const QVariant &nativeHandle = QVariant());
~QEGLPlatformContext();
bool makeCurrent(QPlatformSurface *surface);
@@ -74,6 +74,8 @@ protected:
private:
void init(const QSurfaceFormat &format, QPlatformOpenGLContext *share);
+ void adopt(const QVariant &nativeHandle, QPlatformOpenGLContext *share);
+ void updateFormatFromGL();
EGLContext m_eglContext;
EGLContext m_shareContext;
@@ -84,6 +86,7 @@ private:
int m_swapInterval;
bool m_swapIntervalEnvChecked;
int m_swapIntervalFromEnv;
+ bool m_ownsContext;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/eglconvenience/qeglplatformintegration.cpp b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp
index b48f993436..1b63d16195 100644
--- a/src/platformsupport/eglconvenience/qeglplatformintegration.cpp
+++ b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp
@@ -43,6 +43,7 @@
#include <QtGui/QOpenGLContext>
#include <QtGui/QOffscreenSurface>
#include <QtGui/QGuiApplication>
+#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatforminputcontextfactory_p.h>
@@ -57,6 +58,8 @@
#include <QtPlatformSupport/private/qevdevtouch_p.h>
#endif
+#include <QtPlatformHeaders/qeglfsfunctions.h>
+
#include "qeglplatformintegration_p.h"
#include "qeglplatformcontext_p.h"
#include "qeglplatformwindow_p.h"
@@ -93,7 +96,8 @@ QEGLPlatformIntegration::QEGLPlatformIntegration()
m_display(EGL_NO_DISPLAY),
m_inputContext(0),
m_fontDb(new QGenericUnixFontDatabase),
- m_services(new QGenericUnixServices)
+ m_services(new QGenericUnixServices),
+ m_kbdMgr(0)
{
}
@@ -158,9 +162,14 @@ QPlatformOpenGLContext *QEGLPlatformIntegration::createPlatformOpenGLContext(QOp
// If there is a "root" window into which raster and QOpenGLWidget content is
// composited, all other contexts must share with its context.
QOpenGLContext *compositingContext = screen ? screen->compositingContext() : 0;
- return createContext(context->format(),
- compositingContext ? compositingContext->handle() : context->shareHandle(),
- display());
+ QPlatformOpenGLContext *share = compositingContext ? compositingContext->handle() : context->shareHandle();
+ QVariant nativeHandle = context->nativeHandle();
+ QPlatformOpenGLContext *platformContext = createContext(context->format(),
+ share,
+ display(),
+ &nativeHandle);
+ context->setNativeHandle(nativeHandle);
+ return platformContext;
}
QPlatformOffscreenSurface *QEGLPlatformIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
@@ -189,7 +198,10 @@ QPlatformNativeInterface *QEGLPlatformIntegration::nativeInterface() const
enum ResourceType {
EglDisplay,
EglWindow,
- EglContext
+ EglContext,
+ EglConfig,
+ NativeDisplay,
+ Display
};
static int resourceType(const QByteArray &key)
@@ -197,7 +209,10 @@ static int resourceType(const QByteArray &key)
static const QByteArray names[] = { // match ResourceType
QByteArrayLiteral("egldisplay"),
QByteArrayLiteral("eglwindow"),
- QByteArrayLiteral("eglcontext")
+ QByteArrayLiteral("eglcontext"),
+ QByteArrayLiteral("eglconfig"),
+ QByteArrayLiteral("nativedisplay"),
+ QByteArrayLiteral("display")
};
const QByteArray *end = names + sizeof(names) / sizeof(names[0]);
const QByteArray *result = std::find(names, end, key);
@@ -214,6 +229,26 @@ void *QEGLPlatformIntegration::nativeResourceForIntegration(const QByteArray &re
case EglDisplay:
result = m_screen->display();
break;
+ case NativeDisplay:
+ result = reinterpret_cast<void*>(nativeDisplay());
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+void *QEGLPlatformIntegration::nativeResourceForScreen(const QByteArray &resource, QScreen *)
+{
+ void *result = 0;
+
+ switch (resourceType(resource)) {
+ case Display:
+ // Play nice when using the x11 hooks: Be compatible with xcb that allows querying
+ // the X Display pointer, which is nothing but our native display.
+ result = reinterpret_cast<void*>(nativeDisplay());
+ break;
default:
break;
}
@@ -252,6 +287,10 @@ void *QEGLPlatformIntegration::nativeResourceForContext(const QByteArray &resour
if (context->handle())
result = static_cast<QEGLPlatformContext *>(context->handle())->eglContext();
break;
+ case EglConfig:
+ if (context->handle())
+ result = static_cast<QEGLPlatformContext *>(context->handle())->eglConfig();
+ break;
default:
break;
}
@@ -279,10 +318,35 @@ QPlatformNativeInterface::NativeResourceForContextFunction QEGLPlatformIntegrati
return 0;
}
+QFunctionPointer QEGLPlatformIntegration::platformFunction(const QByteArray &function) const
+{
+#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
+ if (function == QEglFSFunctions::loadKeymapTypeIdentifier())
+ return QFunctionPointer(loadKeymapStatic);
+#else
+ Q_UNUSED(function)
+#endif
+
+ return 0;
+}
+
+void QEGLPlatformIntegration::loadKeymapStatic(const QString &filename)
+{
+#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
+ QEGLPlatformIntegration *self = static_cast<QEGLPlatformIntegration *>(QGuiApplicationPrivate::platformIntegration());
+ if (self->m_kbdMgr)
+ self->m_kbdMgr->loadKeymap(filename);
+ else
+ qWarning("QEGLPlatformIntegration: Cannot load keymap, no keyboard handler found");
+#else
+ Q_UNUSED(filename);
+#endif
+}
+
void QEGLPlatformIntegration::createInputHandlers()
{
#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
- new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString() /* spec */, this);
+ m_kbdMgr = new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString() /* spec */, this);
QEvdevMouseManager *mouseMgr = new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString() /* spec */, this);
Q_FOREACH (QScreen *screen, QGuiApplication::screens()) {
QEGLPlatformCursor *cursor = static_cast<QEGLPlatformCursor *>(screen->handle()->cursor());
diff --git a/src/platformsupport/eglconvenience/qeglplatformintegration_p.h b/src/platformsupport/eglconvenience/qeglplatformintegration_p.h
index f665455383..36f79e2997 100644
--- a/src/platformsupport/eglconvenience/qeglplatformintegration_p.h
+++ b/src/platformsupport/eglconvenience/qeglplatformintegration_p.h
@@ -44,6 +44,7 @@
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformnativeinterface.h>
+#include <QtCore/QVariant>
#include <EGL/egl.h>
QT_BEGIN_NAMESPACE
@@ -52,6 +53,7 @@ class QEGLPlatformScreen;
class QEGLPlatformWindow;
class QEGLPlatformContext;
class QFbVtHandler;
+class QEvdevKeyboardManager;
class QEGLPlatformIntegration : public QPlatformIntegration, public QPlatformNativeInterface
{
@@ -79,16 +81,20 @@ public:
QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE;
// QPlatformNativeInterface
void *nativeResourceForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE;
+ void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen) Q_DECL_OVERRIDE;
void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) Q_DECL_OVERRIDE;
void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) Q_DECL_OVERRIDE;
NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource) Q_DECL_OVERRIDE;
+ QFunctionPointer platformFunction(const QByteArray &function) const Q_DECL_OVERRIDE;
+
protected:
virtual QEGLPlatformScreen *createScreen() const = 0;
virtual QEGLPlatformWindow *createWindow(QWindow *window) const = 0;
virtual QEGLPlatformContext *createContext(const QSurfaceFormat &format,
QPlatformOpenGLContext *shareContext,
- EGLDisplay display) const = 0;
+ EGLDisplay display,
+ QVariant *nativeHandle) const = 0;
virtual QPlatformOffscreenSurface *createOffscreenSurface(EGLDisplay display,
const QSurfaceFormat &format,
QOffscreenSurface *surface) const = 0;
@@ -98,12 +104,15 @@ protected:
void createInputHandlers();
private:
+ static void loadKeymapStatic(const QString &filename);
+
QEGLPlatformScreen *m_screen;
EGLDisplay m_display;
QPlatformInputContext *m_inputContext;
QScopedPointer<QPlatformFontDatabase> m_fontDb;
QScopedPointer<QPlatformServices> m_services;
QScopedPointer<QFbVtHandler> m_vtHandler;
+ QEvdevKeyboardManager *m_kbdMgr;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/eglconvenience/qeglplatformwindow.cpp b/src/platformsupport/eglconvenience/qeglplatformwindow.cpp
index e9b79512ba..a83dd80391 100644
--- a/src/platformsupport/eglconvenience/qeglplatformwindow.cpp
+++ b/src/platformsupport/eglconvenience/qeglplatformwindow.cpp
@@ -127,4 +127,12 @@ WId QEGLPlatformWindow::winId() const
return m_winId;
}
+void QEGLPlatformWindow::setOpacity(qreal)
+{
+ if (!isRaster())
+ qWarning("eglfs: Cannot set opacity for non-raster windows");
+
+ // Nothing to do here. The opacity is stored in the QWindow.
+}
+
QT_END_NAMESPACE
diff --git a/src/platformsupport/eglconvenience/qeglplatformwindow_p.h b/src/platformsupport/eglconvenience/qeglplatformwindow_p.h
index 17a1d07a79..8c77d31fef 100644
--- a/src/platformsupport/eglconvenience/qeglplatformwindow_p.h
+++ b/src/platformsupport/eglconvenience/qeglplatformwindow_p.h
@@ -64,6 +64,7 @@ public:
bool isRaster() const;
WId winId() const Q_DECL_OVERRIDE;
+ void setOpacity(qreal opacity) Q_DECL_OVERRIDE;
virtual EGLNativeWindowType eglWindow() const = 0;
diff --git a/src/platformsupport/fbconvenience/qfbscreen.cpp b/src/platformsupport/fbconvenience/qfbscreen.cpp
index 37d16ddeb6..a962a5eb59 100644
--- a/src/platformsupport/fbconvenience/qfbscreen.cpp
+++ b/src/platformsupport/fbconvenience/qfbscreen.cpp
@@ -196,13 +196,13 @@ void QFbScreen::generateRects()
remainingScreen -= localGeometry;
QRegion windowRegion(localGeometry);
windowRegion -= remainingScreen;
- foreach (QRect rect, windowRegion.rects()) {
+ foreach (const QRect &rect, windowRegion.rects()) {
mCachedRects += QPair<QRect, int>(rect, i);
}
}
#endif
}
- foreach (QRect rect, remainingScreen.rects())
+ foreach (const QRect &rect, remainingScreen.rects())
mCachedRects += QPair<QRect, int>(rect, -1);
mIsUpToDate = true;
return;
@@ -242,7 +242,7 @@ QRegion QFbScreen::doRedraw()
rectRegion -= intersect;
// we only expect one rectangle, but defensive coding...
- foreach (QRect rect, intersect.rects()) {
+ foreach (const QRect &rect, intersect.rects()) {
bool firstLayer = true;
if (layer == -1) {
mCompositePainter->fillRect(rect, Qt::black);
diff --git a/src/platformsupport/fbconvenience/qfbscreen_p.h b/src/platformsupport/fbconvenience/qfbscreen_p.h
index dd940c4a1d..924b49afda 100644
--- a/src/platformsupport/fbconvenience/qfbscreen_p.h
+++ b/src/platformsupport/fbconvenience/qfbscreen_p.h
@@ -108,7 +108,7 @@ private:
void generateRects();
QPainter *mCompositePainter;
- QList<QPair<QRect, int> > mCachedRects;
+ QVector<QPair<QRect, int> > mCachedRects;
QList <QFbBackingStore*> mBackingStores;
friend class QFbWindow;
diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
index b8da9726d5..0d1f9455e1 100644
--- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
+++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
@@ -51,7 +51,6 @@
#include <qpa/qplatformservices.h>
#include <QtGui/private/qfontengine_ft_p.h>
-#include <QtGui/private/qfontengine_qpa_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/qguiapplication.h>
diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig.cpp
index fec489ba60..20cdab6de1 100644
--- a/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig.cpp
+++ b/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig.cpp
@@ -46,7 +46,7 @@
QT_BEGIN_NAMESPACE
QFontEngineMultiFontConfig::QFontEngineMultiFontConfig(QFontEngine *fe, int script)
- : QFontEngineMultiQPA(fe, script)
+ : QFontEngineMultiBasicImpl(fe, script)
{
}
diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig_p.h b/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig_p.h
index 2d93d236e5..9fb273f692 100644
--- a/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig_p.h
+++ b/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig_p.h
@@ -42,12 +42,12 @@
#ifndef QFONTENGINEMULTIFONTCONFIG_H
#define QFONTENGINEMULTIFONTCONFIG_H
-#include <QtGui/private/qfontengine_qpa_p.h>
+#include <QtGui/private/qfontengine_p.h>
#include <fontconfig/fontconfig.h>
QT_BEGIN_NAMESPACE
-class QFontEngineMultiFontConfig : public QFontEngineMultiQPA
+class QFontEngineMultiFontConfig : public QFontEngineMultiBasicImpl
{
public:
explicit QFontEngineMultiFontConfig(QFontEngine *fe, int script);
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
index 9248785696..c0643444e2 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -348,7 +348,7 @@ QFontEngine *QCoreTextFontDatabase::fontEngine(const QByteArray &fontData, qreal
QFontEngine *fontEngine = NULL;
if (cgFont == NULL) {
- qWarning("QRawFont::platformLoadFromData: CGFontCreateWithDataProvider failed");
+ qWarning("QCoreTextFontDatabase::fontEngine: CGFontCreateWithDataProvider failed");
} else {
QFontDef def;
def.pixelSize = pixelSize;
diff --git a/src/platformsupport/glxconvenience/qglxconvenience.cpp b/src/platformsupport/glxconvenience/qglxconvenience.cpp
index 4630b12a57..851ad37a6a 100644
--- a/src/platformsupport/glxconvenience/qglxconvenience.cpp
+++ b/src/platformsupport/glxconvenience/qglxconvenience.cpp
@@ -250,7 +250,7 @@ XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *f
return visualInfo;
}
-void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config, GLXContext)
+void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config)
{
int redSize = 0;
int greenSize = 0;
@@ -262,8 +262,6 @@ void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display,
int sampleCount = 0;
int stereo = 0;
- XVisualInfo *vi = glXGetVisualFromFBConfig(display,config);
- XFree(vi);
glXGetFBConfigAttrib(display, config, GLX_RED_SIZE, &redSize);
glXGetFBConfigAttrib(display, config, GLX_GREEN_SIZE, &greenSize);
glXGetFBConfigAttrib(display, config, GLX_BLUE_SIZE, &blueSize);
@@ -287,6 +285,41 @@ void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display,
format->setStereo(stereo);
}
+void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display, XVisualInfo *visualInfo)
+{
+ int redSize = 0;
+ int greenSize = 0;
+ int blueSize = 0;
+ int alphaSize = 0;
+ int depthSize = 0;
+ int stencilSize = 0;
+ int sampleBuffers = 0;
+ int sampleCount = 0;
+ int stereo = 0;
+
+ glXGetConfig(display, visualInfo, GLX_RED_SIZE, &redSize);
+ glXGetConfig(display, visualInfo, GLX_GREEN_SIZE, &greenSize);
+ glXGetConfig(display, visualInfo, GLX_BLUE_SIZE, &blueSize);
+ glXGetConfig(display, visualInfo, GLX_ALPHA_SIZE, &alphaSize);
+ glXGetConfig(display, visualInfo, GLX_DEPTH_SIZE, &depthSize);
+ glXGetConfig(display, visualInfo, GLX_STENCIL_SIZE, &stencilSize);
+ glXGetConfig(display, visualInfo, GLX_SAMPLES_ARB, &sampleBuffers);
+ glXGetConfig(display, visualInfo, GLX_STEREO, &stereo);
+
+ format->setRedBufferSize(redSize);
+ format->setGreenBufferSize(greenSize);
+ format->setBlueBufferSize(blueSize);
+ format->setAlphaBufferSize(alphaSize);
+ format->setDepthBufferSize(depthSize);
+ format->setStencilBufferSize(stencilSize);
+ if (sampleBuffers) {
+ glXGetConfig(display, visualInfo, GLX_SAMPLES_ARB, &sampleCount);
+ format->setSamples(sampleCount);
+ }
+
+ format->setStereo(stereo);
+}
+
QSurfaceFormat qglx_reduceSurfaceFormat(const QSurfaceFormat &format, bool *reduced)
{
QSurfaceFormat retFormat = format;
diff --git a/src/platformsupport/glxconvenience/qglxconvenience_p.h b/src/platformsupport/glxconvenience/qglxconvenience_p.h
index 66548a3479..04fa8595ef 100644
--- a/src/platformsupport/glxconvenience/qglxconvenience_p.h
+++ b/src/platformsupport/glxconvenience/qglxconvenience_p.h
@@ -50,7 +50,8 @@
XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format);
GLXFBConfig qglx_findConfig(Display *display, int screen, const QSurfaceFormat &format, int drawableBit = GLX_WINDOW_BIT);
-void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config, GLXContext context = 0);
+void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config);
+void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display, XVisualInfo *visualInfo);
QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit = GLX_WINDOW_BIT);
QSurfaceFormat qglx_reduceSurfaceFormat(const QSurfaceFormat &format, bool *reduced);
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp
index 0841544208..72de73db7e 100644
--- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp
+++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp
@@ -93,13 +93,15 @@ QEvdevKeyboardHandler::~QEvdevKeyboardHandler()
qt_safe_close(m_fd);
}
-QEvdevKeyboardHandler *QEvdevKeyboardHandler::create(const QString &device, const QString &specification)
+QEvdevKeyboardHandler *QEvdevKeyboardHandler::create(const QString &device,
+ const QString &specification,
+ const QString &defaultKeymapFile)
{
#ifdef QT_QPA_KEYMAP_DEBUG
qWarning() << "Try to create keyboard handler for" << device << specification;
#endif
- QString keymapFile;
+ QString keymapFile = defaultKeymapFile;
int repeatDelay = 400;
int repeatRate = 80;
bool disableZap = false;
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h
index 1065b05d51..164b1c3863 100644
--- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h
+++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h
@@ -145,7 +145,9 @@ public:
SwitchConsoleMask = 0x0000007f
};
- static QEvdevKeyboardHandler *create(const QString &device, const QString &specification);
+ static QEvdevKeyboardHandler *create(const QString &device,
+ const QString &specification,
+ const QString &defaultKeymapFile = QString());
static Qt::KeyboardModifiers toQtModifiers(quint8 mod)
{
@@ -161,13 +163,14 @@ public:
return qtmod;
}
+ bool loadKeymap(const QString &file);
+ void unloadKeymap();
+
private slots:
void readKeycode();
KeycodeAction processKeycode(quint16 keycode, bool pressed, bool autorepeat);
private:
- void unloadKeymap();
- bool loadKeymap(const QString &file);
void processKeyEvent(int nativecode, int unicode, int qtcode,
Qt::KeyboardModifiers modifiers, bool isPress, bool autoRepeat);
void switchLed(int, bool);
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp
index 4932087c5f..4ceaf98055 100644
--- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp
+++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp
@@ -113,7 +113,7 @@ void QEvdevKeyboardManager::addKeyboard(const QString &deviceNode)
#endif
QEvdevKeyboardHandler *keyboard;
- keyboard = QEvdevKeyboardHandler::create(deviceNode, m_spec);
+ keyboard = QEvdevKeyboardHandler::create(deviceNode, m_spec, m_defaultKeymapFile);
if (keyboard)
m_keyboards.insert(deviceNode, keyboard);
else
@@ -132,4 +132,28 @@ void QEvdevKeyboardManager::removeKeyboard(const QString &deviceNode)
}
}
+void QEvdevKeyboardManager::loadKeymap(const QString &file)
+{
+ m_defaultKeymapFile = file;
+
+ if (file.isEmpty()) {
+ // Restore the default, which is either the built-in keymap or
+ // the one given in the plugin spec.
+ QString keymapFromSpec;
+ foreach (const QString &arg, m_spec.split(QLatin1Char(':'))) {
+ if (arg.startsWith(QLatin1String("keymap=")))
+ keymapFromSpec = arg.mid(7);
+ }
+ foreach (QEvdevKeyboardHandler *handler, m_keyboards) {
+ if (keymapFromSpec.isEmpty())
+ handler->unloadKeymap();
+ else
+ handler->loadKeymap(keymapFromSpec);
+ }
+ } else {
+ foreach (QEvdevKeyboardHandler *handler, m_keyboards)
+ handler->loadKeymap(file);
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h
index 37c60c035c..e7a07f17a4 100644
--- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h
+++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h
@@ -59,6 +59,8 @@ public:
QEvdevKeyboardManager(const QString &key, const QString &specification, QObject *parent = 0);
~QEvdevKeyboardManager();
+ void loadKeymap(const QString &file);
+
private slots:
void addKeyboard(const QString &deviceNode = QString());
void removeKeyboard(const QString &deviceNode);
@@ -67,6 +69,7 @@ private:
QString m_spec;
QHash<QString,QEvdevKeyboardHandler*> m_keyboards;
QDeviceDiscovery *m_deviceDiscovery;
+ QString m_defaultKeymapFile;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
index 92f807095f..611a7f9d6d 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
+++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
@@ -60,6 +60,8 @@
//#define QT_QPA_MOUSE_HANDLER_DEBUG
+#define TEST_BIT(array, bit) (array[bit/8] & (1<<(bit%8)))
+
QT_BEGIN_NAMESPACE
QEvdevMouseHandler *QEvdevMouseHandler::create(const QString &device, const QString &specification)
@@ -71,6 +73,7 @@ QEvdevMouseHandler *QEvdevMouseHandler::create(const QString &device, const QStr
bool compression = true;
int jitterLimit = 0;
int grab = 0;
+ bool abs = false;
QStringList args = specification.split(QLatin1Char(':'));
foreach (const QString &arg, args) {
@@ -80,27 +83,37 @@ QEvdevMouseHandler *QEvdevMouseHandler::create(const QString &device, const QStr
jitterLimit = arg.mid(9).toInt();
else if (arg.startsWith(QLatin1String("grab=")))
grab = arg.mid(5).toInt();
+ else if (arg == QLatin1String("abs"))
+ abs = true;
}
int fd;
fd = qt_safe_open(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
if (fd >= 0) {
::ioctl(fd, EVIOCGRAB, grab);
- return new QEvdevMouseHandler(device, fd, compression, jitterLimit);
+ return new QEvdevMouseHandler(device, fd, abs, compression, jitterLimit);
} else {
qWarning("Cannot open mouse input device '%s': %s", qPrintable(device), strerror(errno));
return 0;
}
}
-QEvdevMouseHandler::QEvdevMouseHandler(const QString &device, int fd, bool compression, int jitterLimit)
+QEvdevMouseHandler::QEvdevMouseHandler(const QString &device, int fd, bool abs, bool compression, int jitterLimit)
: m_device(device), m_fd(fd), m_notify(0), m_x(0), m_y(0), m_prevx(0), m_prevy(0),
- m_compression(compression), m_buttons(0), m_prevInvalid(true)
+ m_abs(abs), m_compression(compression), m_buttons(0), m_prevInvalid(true)
{
setObjectName(QLatin1String("Evdev Mouse Handler"));
m_jitterLimitSquared = jitterLimit * jitterLimit;
+ // Some touch screens present as mice with absolute coordinates.
+ // These can not be differentiated from touchpads, so supplying abs to QT_QPA_EVDEV_MOUSE_PARAMETERS
+ // will force qevdevmousehandler to treat the coordinates as absolute, scaled to the hardware maximums.
+ // Turning this on will not affect mice as these do not report in absolute coordinates
+ // but will make touchpads act like touch screens
+ if (m_abs)
+ m_abs = getHardwareMaximum();
+
// socket notifier for events on the mouse device
QSocketNotifier *notifier;
notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
@@ -113,16 +126,66 @@ QEvdevMouseHandler::~QEvdevMouseHandler()
qt_safe_close(m_fd);
}
+// Ask touch screen hardware for information on coordinate maximums
+// If any ioctls fail, revert to non abs mode
+bool QEvdevMouseHandler::getHardwareMaximum()
+{
+ unsigned char absFeatures[(ABS_MAX / 8) + 1];
+ memset(absFeatures, '\0', sizeof (absFeatures));
+
+ // test if ABS_X, ABS_Y are available
+ if (ioctl(m_fd, EVIOCGBIT(EV_ABS, sizeof (absFeatures)), absFeatures) == -1)
+ return false;
+
+ if ((!TEST_BIT(absFeatures, ABS_X)) || (!TEST_BIT(absFeatures, ABS_Y)))
+ return false;
+
+ // ask hardware for minimum and maximum values
+ struct input_absinfo absInfo;
+ if (ioctl(m_fd, EVIOCGABS(ABS_X), &absInfo) == -1)
+ return false;
+
+ m_hardwareWidth = absInfo.maximum - absInfo.minimum;
+
+ if (ioctl(m_fd, EVIOCGABS(ABS_Y), &absInfo) == -1)
+ return false;
+
+ m_hardwareHeight = absInfo.maximum - absInfo.minimum;
+
+ QRect g = QGuiApplication::primaryScreen()->virtualGeometry();
+ m_hardwareScalerX = static_cast<qreal>(m_hardwareWidth) / (g.right() - g.left());
+ m_hardwareScalerY = static_cast<qreal>(m_hardwareHeight) / (g.bottom() - g.top());
+
+#ifdef QT_QPA_MOUSE_HANDLER_DEBUG
+ qDebug() << "Absolute pointing device";
+ qDebug() << "hardware max x" << m_hardwareWidth;
+ qDebug() << "hardware max y" << m_hardwareHeight;
+ qDebug() << "hardware scalers x" << m_hardwareScalerX << "y" << m_hardwareScalerY;
+#endif
+
+ return true;
+}
+
void QEvdevMouseHandler::sendMouseEvent()
{
- int x = m_x - m_prevx;
- int y = m_y - m_prevy;
+ int x;
+ int y;
+
+ if (!m_abs) {
+ x = m_x - m_prevx;
+ y = m_y - m_prevy;
+ }
+ else {
+ x = m_x / m_hardwareScalerX;
+ y = m_y / m_hardwareScalerY;
+ }
+
if (m_prevInvalid) {
x = y = 0;
m_prevInvalid = false;
}
- emit handleMouseEvent(x, y, m_buttons);
+ emit handleMouseEvent(x, y, m_abs, m_buttons);
m_prevx = m_x;
m_prevy = m_y;
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h b/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h
index d419a1913e..027d2862b0 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h
+++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h
@@ -57,26 +57,32 @@ public:
~QEvdevMouseHandler();
signals:
- void handleMouseEvent(int x, int y, Qt::MouseButtons buttons);
+ void handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons);
void handleWheelEvent(int delta, Qt::Orientation orientation);
private slots:
void readMouseData();
private:
- QEvdevMouseHandler(const QString &device, int fd, bool compression, int jitterLimit);
+ QEvdevMouseHandler(const QString &device, int fd, bool abs, bool compression, int jitterLimit);
void sendMouseEvent();
+ bool getHardwareMaximum();
QString m_device;
int m_fd;
QSocketNotifier *m_notify;
int m_x, m_y;
int m_prevx, m_prevy;
+ bool m_abs;
bool m_compression;
Qt::MouseButtons m_buttons;
int m_jitterLimitSquared;
bool m_prevInvalid;
+ int m_hardwareWidth;
+ int m_hardwareHeight;
+ qreal m_hardwareScalerY;
+ qreal m_hardwareScalerX;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp
index 6c430091c1..87f3a4c9a0 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp
+++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp
@@ -111,11 +111,16 @@ QEvdevMouseManager::~QEvdevMouseManager()
m_mice.clear();
}
-void QEvdevMouseManager::handleMouseEvent(int x, int y, Qt::MouseButtons buttons)
+void QEvdevMouseManager::handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons)
{
// update current absolute coordinates
- m_x += x;
- m_y += y;
+ if (!abs) {
+ m_x += x;
+ m_y += y;
+ } else {
+ m_x = x;
+ m_y = y;
+ }
// clamp to screen geometry
QRect g = QGuiApplication::primaryScreen()->virtualGeometry();
@@ -130,7 +135,9 @@ void QEvdevMouseManager::handleMouseEvent(int x, int y, Qt::MouseButtons buttons
m_y = g.bottom() - m_yoffset;
QPoint pos(m_x + m_xoffset, m_y + m_yoffset);
- QWindowSystemInterface::handleMouseEvent(0, pos, pos, buttons);
+ // Cannot track the keyboard modifiers ourselves here. Instead, report the
+ // modifiers from the last key event that has been seen by QGuiApplication.
+ QWindowSystemInterface::handleMouseEvent(0, pos, pos, buttons, QGuiApplication::keyboardModifiers());
#ifdef QT_QPA_MOUSEMANAGER_DEBUG
qDebug("mouse event %d %d %d", pos.x(), pos.y(), int(buttons));
@@ -140,7 +147,7 @@ void QEvdevMouseManager::handleMouseEvent(int x, int y, Qt::MouseButtons buttons
void QEvdevMouseManager::handleWheelEvent(int delta, Qt::Orientation orientation)
{
QPoint pos(m_x + m_xoffset, m_y + m_yoffset);
- QWindowSystemInterface::handleWheelEvent(0, pos, pos, delta, orientation);
+ QWindowSystemInterface::handleWheelEvent(0, pos, pos, delta, orientation, QGuiApplication::keyboardModifiers());
#ifdef QT_QPA_MOUSEMANAGER_DEBUG
qDebug("mouse wheel event %dx%d %d %d", pos.x(), pos.y(), delta, int(orientation));
@@ -156,7 +163,7 @@ void QEvdevMouseManager::addMouse(const QString &deviceNode)
QEvdevMouseHandler *handler;
handler = QEvdevMouseHandler::create(deviceNode, m_spec);
if (handler) {
- connect(handler, SIGNAL(handleMouseEvent(int,int,Qt::MouseButtons)), this, SLOT(handleMouseEvent(int,int,Qt::MouseButtons)));
+ 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)));
m_mice.insert(deviceNode, handler);
} else {
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h b/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h
index d52a16ea75..5280b5efbd 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h
+++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h
@@ -62,7 +62,7 @@ public:
QDeviceDiscovery *deviceDiscovery() { return m_deviceDiscovery; }
public slots:
- void handleMouseEvent(int x, int y, Qt::MouseButtons buttons);
+ void handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons);
void handleWheelEvent(int delta, Qt::Orientation orientation);
private slots:
diff --git a/src/platformsupport/input/evdevtouch/qevdevtouch.cpp b/src/platformsupport/input/evdevtouch/qevdevtouch.cpp
index 563edf4fd7..6ed4abaeee 100644
--- a/src/platformsupport/input/evdevtouch/qevdevtouch.cpp
+++ b/src/platformsupport/input/evdevtouch/qevdevtouch.cpp
@@ -184,6 +184,8 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification,
QString dev;
int rotationAngle = 0;
+ bool invertx = false;
+ bool inverty = false;
for (int i = 0; i < args.count(); ++i) {
if (args.at(i).startsWith(QLatin1String("/dev/")) && dev.isEmpty()) {
dev = args.at(i);
@@ -201,6 +203,10 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification,
break;
}
}
+ } else if (args.at(i) == QLatin1String("invertx")) {
+ invertx = true;
+ } else if (args.at(i) == QLatin1String("inverty")) {
+ inverty = true;
}
}
@@ -326,6 +332,12 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification,
if (rotationAngle)
d->m_rotate = QTransform::fromTranslate(0.5, 0.5).rotate(rotationAngle).translate(-0.5, -0.5);
+ if (invertx)
+ d->m_rotate *= QTransform::fromTranslate(0.5, 0.5).scale(-1.0, 1.0).translate(-0.5, -0.5);
+
+ if (inverty)
+ d->m_rotate *= QTransform::fromTranslate(0.5, 0.5).scale(1.0, -1.0).translate(-0.5, -0.5);
+
d->registerDevice();
}
diff --git a/src/platformsupport/linuxaccessibility/application.cpp b/src/platformsupport/linuxaccessibility/application.cpp
index ae52ab3b57..5a8d0e73f0 100644
--- a/src/platformsupport/linuxaccessibility/application.cpp
+++ b/src/platformsupport/linuxaccessibility/application.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -47,6 +47,7 @@
#include <qdebug.h>
#include "deviceeventcontroller_adaptor.h"
+#include "atspi/atspi-constants.h"
//#define KEYBOARD_DEBUG
@@ -62,7 +63,7 @@ QT_BEGIN_NAMESPACE
*/
QSpiApplicationAdaptor::QSpiApplicationAdaptor(const QDBusConnection &connection, QObject *parent)
- : QObject(parent), dbusConnection(connection)
+ : QObject(parent), dbusConnection(connection), inCapsLock(false)
{
}
@@ -107,13 +108,14 @@ bool QSpiApplicationAdaptor::eventFilter(QObject *target, QEvent *event)
de.id = keyEvent->nativeVirtualKey();
de.hardwareCode = keyEvent->nativeScanCode();
- de.modifiers = keyEvent->nativeModifiers();
de.timestamp = QDateTime::currentMSecsSinceEpoch();
if (keyEvent->key() == Qt::Key_Tab)
de.text = QStringLiteral("Tab");
else if (keyEvent->key() == Qt::Key_Backtab)
de.text = QStringLiteral("Backtab");
+ else if (keyEvent->key() == Qt::Key_Control)
+ de.text = QStringLiteral("Control_L");
else if (keyEvent->key() == Qt::Key_Left)
de.text = (keyEvent->modifiers() & Qt::KeypadModifier) ? QStringLiteral("KP_Left") : QStringLiteral("Left");
else if (keyEvent->key() == Qt::Key_Right)
@@ -142,9 +144,13 @@ bool QSpiApplicationAdaptor::eventFilter(QObject *target, QEvent *event)
de.text = QStringLiteral("Escape");
else if (keyEvent->key() == Qt::Key_Space)
de.text = QStringLiteral("space");
- else if (keyEvent->key() == Qt::Key_CapsLock)
+ else if (keyEvent->key() == Qt::Key_CapsLock) {
de.text = QStringLiteral("Caps_Lock");
- else if (keyEvent->key() == Qt::Key_NumLock)
+ if (event->type() == QEvent::KeyPress)
+ inCapsLock = true;
+ else
+ inCapsLock = false;
+ } else if (keyEvent->key() == Qt::Key_NumLock)
de.text = QStringLiteral("Num_Lock");
else if (keyEvent->key() == Qt::Key_Insert)
de.text = QStringLiteral("Insert");
@@ -155,18 +161,28 @@ bool QSpiApplicationAdaptor::eventFilter(QObject *target, QEvent *event)
// Long term the spec will hopefully change to just use keycodes.
de.isText = !de.text.isEmpty();
+ de.modifiers = 0;
+ if (!inCapsLock && keyEvent->modifiers() & Qt::ShiftModifier)
+ de.modifiers |= 1 << ATSPI_MODIFIER_SHIFT;
+ if (inCapsLock && (keyEvent->key() != Qt::Key_CapsLock))
+ de.modifiers |= 1 << ATSPI_MODIFIER_SHIFTLOCK;
+ if ((keyEvent->modifiers() & Qt::ControlModifier) && (keyEvent->key() != Qt::Key_Control))
+ de.modifiers |= 1 << ATSPI_MODIFIER_CONTROL;
+ if ((keyEvent->modifiers() & Qt::AltModifier) && (keyEvent->key() != Qt::Key_Alt))
+ de.modifiers |= 1 << ATSPI_MODIFIER_ALT;
+
#ifdef KEYBOARD_DEBUG
- qDebug() << QStringLiteral("Key event text: ") << event->type() << de.isText << QStringLiteral(" ") << de.text
- << QStringLiteral(" hardware code: ") << de.hardwareCode
- << QStringLiteral(" native sc: ") << keyEvent->nativeScanCode()
- << QStringLiteral(" native mod: ") << keyEvent->nativeModifiers()
- << QStringLiteral("native virt: ") << keyEvent->nativeVirtualKey();
+ qDebug() << QStringLiteral("Key event text:") << event->type() << de.text
+ << QStringLiteral("native virtual key:") << de.id
+ << QStringLiteral("hardware code/scancode:") << de.hardwareCode
+ << QStringLiteral("modifiers:") << de.modifiers
+ << QStringLiteral("text:") << de.text;
#endif
QDBusMessage m = QDBusMessage::createMethodCall(QStringLiteral("org.a11y.atspi.Registry"),
QStringLiteral("/org/a11y/atspi/registry/deviceeventcontroller"),
QStringLiteral("org.a11y.atspi.DeviceEventController"), QStringLiteral("NotifyListenersSync"));
- m.setArguments(QVariantList() <<QVariant::fromValue(de));
+ m.setArguments(QVariantList() << QVariant::fromValue(de));
// FIXME: this is critical, the timeout should probably be pretty low to allow normal processing
int timeout = 100;
@@ -175,9 +191,6 @@ bool QSpiApplicationAdaptor::eventFilter(QObject *target, QEvent *event)
if (sent) {
//queue the event and send it after callback
keyEvents.enqueue(QPair<QPointer<QObject>, QKeyEvent*> (QPointer<QObject>(target), copyKeyEvent(keyEvent)));
-#ifdef KEYBOARD_DEBUG
- qDebug() << QStringLiteral("Sent key: ") << de.text;
-#endif
return true;
}
}
diff --git a/src/platformsupport/linuxaccessibility/application_p.h b/src/platformsupport/linuxaccessibility/application_p.h
index e8684ab2b5..72c27c0d88 100644
--- a/src/platformsupport/linuxaccessibility/application_p.h
+++ b/src/platformsupport/linuxaccessibility/application_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -78,6 +78,7 @@ private:
QQueue<QPair<QPointer<QObject>, QKeyEvent*> > keyEvents;
QDBusConnection dbusConnection;
+ bool inCapsLock;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
index 84f82cdeda..48cd01413f 100644
--- a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
+++ b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -910,6 +910,11 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
notifyAboutDestruction(event->accessibleInterface());
break;
}
+ case QAccessible::ObjectReorder: {
+ if (sendObject || sendObject_children_changed)
+ childrenChanged(event->accessibleInterface());
+ break;
+ }
case QAccessible::NameChanged: {
if (sendObject || sendObject_property_change || sendObject_property_change_accessible_name) {
QString path = pathForInterface(event->accessibleInterface());
@@ -1078,16 +1083,14 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
QAccessibleInterface * iface = event->accessibleInterface();
if (!iface || !(iface->role() == QAccessible::Window && (sendWindow || sendWindow_activate)))
return;
+ int isActive = iface->state().active;
QString windowTitle = iface->text(QAccessible::Name);
QDBusVariant data;
data.setVariant(windowTitle);
QVariantList args = packDBusSignalArguments(QString(), 0, 0, QVariant::fromValue(data));
-
- QString status = iface->state().active ? QLatin1String("Activate") : QLatin1String("Deactivate");
+ QString status = isActive ? QLatin1String("Activate") : QLatin1String("Deactivate");
QString path = pathForInterface(iface);
sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_WINDOW), status, args);
-
- int isActive = iface->state().active;
notifyStateChange(iface, QLatin1String("active"), isActive);
} else if (stateChange.disabled) {
QAccessibleInterface *iface = event->accessibleInterface();
@@ -1150,7 +1153,6 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
case QAccessible::TextAttributeChanged:
case QAccessible::TextColumnChanged:
case QAccessible::VisibleDataChanged:
- case QAccessible::ObjectReorder:
case QAccessible::SelectionAdd:
case QAccessible::SelectionWithin:
case QAccessible::LocationChanged:
@@ -1186,6 +1188,17 @@ void AtSpiAdaptor::sendFocusChanged(QAccessibleInterface *interface) const
}
}
+void AtSpiAdaptor::childrenChanged(QAccessibleInterface *interface) const
+{
+ QString parentPath = pathForInterface(interface);
+ int childCount = interface->childCount();
+ for (int i = 0; i < interface->childCount(); ++i) {
+ QString childPath = pathForInterface(interface->child(i));
+ QVariantList args = packDBusSignalArguments(QLatin1String("add"), childCount, 0, childPath);
+ sendDBusSignal(parentPath, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT), QLatin1String("ChildrenChanged"), args);
+ }
+}
+
void AtSpiAdaptor::notifyAboutCreation(QAccessibleInterface *interface) const
{
// // say hello to d-bus
@@ -1641,13 +1654,13 @@ bool AtSpiAdaptor::componentInterface(QAccessibleInterface *interface, const QSt
size << rect.width() << rect.height();
connection.send(message.createReply(size));
} else if (function == QLatin1String("GrabFocus")) {
-// FIXME: implement focus grabbing
-// if (interface->object() && interface->object()->isWidgetType()) {
-// QWidget* w = static_cast<QWidget*>(interface->object());
-// w->setFocus(Qt::OtherFocusReason);
-// sendReply(connection, message, true);
-// }
- sendReply(connection, message, false);
+ QAccessibleActionInterface *actionIface = interface->actionInterface();
+ if (actionIface && actionIface->actionNames().contains(QAccessibleActionInterface::setFocusAction())) {
+ actionIface->doAction(QAccessibleActionInterface::setFocusAction());
+ sendReply(connection, message, true);
+ } else {
+ sendReply(connection, message, false);
+ }
} else if (function == QLatin1String("SetExtents")) {
// int x = message.arguments().at(0).toInt();
// int y = message.arguments().at(1).toInt();
@@ -1952,17 +1965,17 @@ QVariantList AtSpiAdaptor::getAttributeValue(QAccessibleInterface *interface, in
return list;
}
-QRect AtSpiAdaptor::getCharacterExtents(QAccessibleInterface *interface, int offset, uint coordType) const
+QList<QVariant> AtSpiAdaptor::getCharacterExtents(QAccessibleInterface *interface, int offset, uint coordType) const
{
QRect rect = interface->textInterface()->characterRect(offset);
if (coordType == ATSPI_COORD_TYPE_WINDOW)
rect = translateRectToWindowCoordinates(interface, rect);
- return rect;
+ return QList<QVariant>() << rect.x() << rect.y() << rect.width() << rect.height();
}
-QRect AtSpiAdaptor::getRangeExtents(QAccessibleInterface *interface,
+QList<QVariant> AtSpiAdaptor::getRangeExtents(QAccessibleInterface *interface,
int startOffset, int endOffset, uint coordType) const
{
if (endOffset == -1)
@@ -1970,7 +1983,7 @@ QRect AtSpiAdaptor::getRangeExtents(QAccessibleInterface *interface,
QAccessibleTextInterface *textInterface = interface->textInterface();
if (endOffset <= startOffset || !textInterface)
- return QRect();
+ return QList<QVariant>() << -1 << -1 << 0 << 0;
QRect rect = textInterface->characterRect(startOffset);
for (int i=startOffset + 1; i <= endOffset; i++)
@@ -1980,7 +1993,7 @@ QRect AtSpiAdaptor::getRangeExtents(QAccessibleInterface *interface,
if (coordType == ATSPI_COORD_TYPE_WINDOW)
rect = translateRectToWindowCoordinates(interface, rect);
- return rect;
+ return QList<QVariant>() << rect.x() << rect.y() << rect.width() << rect.height();
}
QRect AtSpiAdaptor::translateRectToWindowCoordinates(QAccessibleInterface *interface, const QRect &rect)
diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor_p.h b/src/platformsupport/linuxaccessibility/atspiadaptor_p.h
index 8e905e4cca..e1e2f2b149 100644
--- a/src/platformsupport/linuxaccessibility/atspiadaptor_p.h
+++ b/src/platformsupport/linuxaccessibility/atspiadaptor_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -91,6 +91,7 @@ private:
void sendFocusChanged(QAccessibleInterface *interface) const;
void notifyAboutCreation(QAccessibleInterface *interface) const;
void notifyAboutDestruction(QAccessibleInterface *interface) const;
+ void childrenChanged(QAccessibleInterface *interface) const;
// handlers for the different accessible interfaces
bool applicationInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection);
@@ -125,8 +126,8 @@ private:
// text helper functions
QVariantList getAttributes(QAccessibleInterface *, int offset, bool includeDefaults) const;
QVariantList getAttributeValue(QAccessibleInterface *, int offset, const QString &attributeName) const;
- QRect getCharacterExtents(QAccessibleInterface *, int offset, uint coordType) const;
- QRect getRangeExtents(QAccessibleInterface *, int startOffset, int endOffset, uint coordType) const;
+ QList<QVariant> getCharacterExtents(QAccessibleInterface *, int offset, uint coordType) const;
+ QList<QVariant> getRangeExtents(QAccessibleInterface *, int startOffset, int endOffset, uint coordType) const;
QAccessible::TextBoundaryType qAccessibleBoundaryType(int atspiTextBoundaryType) const;
static bool inheritsQAction(QObject *object);
diff --git a/src/platformsupport/linuxaccessibility/bridge.cpp b/src/platformsupport/linuxaccessibility/bridge.cpp
index 350c67f1ed..3a1e3e0ce0 100644
--- a/src/platformsupport/linuxaccessibility/bridge.cpp
+++ b/src/platformsupport/linuxaccessibility/bridge.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -244,6 +244,12 @@ static RoleMapping map[] = {
//: Role of an accessible object
{ QAccessible::LayeredPane, ATSPI_ROLE_LAYERED_PANE, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "layered pane") },
//: Role of an accessible object
+ { QAccessible::WebDocument, ATSPI_ROLE_DOCUMENT_WEB, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "web document") },
+ //: Role of an accessible object
+ { QAccessible::Paragraph, ATSPI_ROLE_PARAGRAPH, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "paragraph") },
+ //: Role of an accessible object
+ { QAccessible::Section, ATSPI_ROLE_SECTION, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "section") },
+ //: Role of an accessible object
{ QAccessible::UserRole, ATSPI_ROLE_UNKNOWN, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "unknown") }
};
diff --git a/src/platformsupport/linuxaccessibility/bridge_p.h b/src/platformsupport/linuxaccessibility/bridge_p.h
index 0e1624c522..56018ef14c 100644
--- a/src/platformsupport/linuxaccessibility/bridge_p.h
+++ b/src/platformsupport/linuxaccessibility/bridge_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
diff --git a/src/platformsupport/linuxaccessibility/cache.cpp b/src/platformsupport/linuxaccessibility/cache.cpp
index f9d519b9cd..a850c6dec4 100644
--- a/src/platformsupport/linuxaccessibility/cache.cpp
+++ b/src/platformsupport/linuxaccessibility/cache.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
diff --git a/src/platformsupport/linuxaccessibility/cache_p.h b/src/platformsupport/linuxaccessibility/cache_p.h
index a8128d9320..dd7ef24e5e 100644
--- a/src/platformsupport/linuxaccessibility/cache_p.h
+++ b/src/platformsupport/linuxaccessibility/cache_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
diff --git a/src/platformsupport/linuxaccessibility/constant_mappings.cpp b/src/platformsupport/linuxaccessibility/constant_mappings.cpp
index 9de667158b..0bafaa036c 100644
--- a/src/platformsupport/linuxaccessibility/constant_mappings.cpp
+++ b/src/platformsupport/linuxaccessibility/constant_mappings.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
diff --git a/src/platformsupport/linuxaccessibility/constant_mappings_p.h b/src/platformsupport/linuxaccessibility/constant_mappings_p.h
index a0287a910b..50b7864836 100644
--- a/src/platformsupport/linuxaccessibility/constant_mappings_p.h
+++ b/src/platformsupport/linuxaccessibility/constant_mappings_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
diff --git a/src/platformsupport/linuxaccessibility/dbusconnection.cpp b/src/platformsupport/linuxaccessibility/dbusconnection.cpp
index 18915f8e08..b5485c034e 100644
--- a/src/platformsupport/linuxaccessibility/dbusconnection.cpp
+++ b/src/platformsupport/linuxaccessibility/dbusconnection.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -84,8 +84,14 @@ void DBusConnection::serviceRegistered()
QDBusConnection c = QDBusConnection::sessionBus();
OrgA11yStatusInterface *a11yStatus = new OrgA11yStatusInterface(A11Y_SERVICE, A11Y_PATH, c, this);
+ //The variable was introduced because on some embedded platforms there are custom accessibility
+ //clients which don't set Status.ScreenReaderEnabled to true. The variable is also useful for
+ //debugging.
+ static const bool a11yAlwaysOn = !qEnvironmentVariableIsSet("QT_LINUX_ACCESSIBILITY_ALWAYS_ON");
+
// a11yStatus->isEnabled() returns always true (since Gnome 3.6)
- bool enabled = a11yStatus->screenReaderEnabled();
+ bool enabled = a11yAlwaysOn || a11yStatus->screenReaderEnabled();
+
if (enabled != m_enabled) {
m_enabled = enabled;
if (m_a11yConnection.isConnected()) {
diff --git a/src/platformsupport/linuxaccessibility/dbusconnection_p.h b/src/platformsupport/linuxaccessibility/dbusconnection_p.h
index 70f6fb80ac..b4d1bea8af 100644
--- a/src/platformsupport/linuxaccessibility/dbusconnection_p.h
+++ b/src/platformsupport/linuxaccessibility/dbusconnection_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
diff --git a/src/platformsupport/linuxaccessibility/struct_marshallers.cpp b/src/platformsupport/linuxaccessibility/struct_marshallers.cpp
index a5b663bfec..8c6f4959de 100644
--- a/src/platformsupport/linuxaccessibility/struct_marshallers.cpp
+++ b/src/platformsupport/linuxaccessibility/struct_marshallers.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
diff --git a/src/platformsupport/linuxaccessibility/struct_marshallers_p.h b/src/platformsupport/linuxaccessibility/struct_marshallers_p.h
index 0b775d5521..fb1e6756eb 100644
--- a/src/platformsupport/linuxaccessibility/struct_marshallers_p.h
+++ b/src/platformsupport/linuxaccessibility/struct_marshallers_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
diff --git a/src/platformsupport/platformsupport.pro b/src/platformsupport/platformsupport.pro
index 5b4d2b1fb3..32ce2e3887 100644
--- a/src/platformsupport/platformsupport.pro
+++ b/src/platformsupport/platformsupport.pro
@@ -18,6 +18,7 @@ include(input/input.pri)
include(devicediscovery/devicediscovery.pri)
include(services/services.pri)
include(themes/themes.pri)
+include(accessibility/accessibility.pri)
include(linuxaccessibility/linuxaccessibility.pri)
include(clipboard/clipboard.pri)
diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
index 4a1d67f4b5..bf73d30871 100644
--- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
+++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
@@ -51,6 +51,7 @@
#include <QtCore/QFileInfo>
#include <QtCore/QFile>
#include <QtCore/QDebug>
+#include <QtCore/QHash>
#include <QtCore/QSettings>
#include <QtCore/QVariant>
#include <QtCore/QStringList>
@@ -171,26 +172,26 @@ QVariant QGenericUnixTheme::themeHint(ThemeHint hint) const
class QKdeThemePrivate : public QPlatformThemePrivate
{
public:
- QKdeThemePrivate(const QString &kdeHome, int kdeVersion)
- : kdeHome(kdeHome)
+ QKdeThemePrivate(const QStringList &kdeDirs, int kdeVersion)
+ : kdeDirs(kdeDirs)
, kdeVersion(kdeVersion)
, toolButtonStyle(Qt::ToolButtonTextBesideIcon)
, toolBarIconSize(0)
, singleClick(true)
{ }
- QString globalSettingsFile() const
+ static QString kdeGlobals(const QString &kdeDir)
{
- return kdeHome + QStringLiteral("/share/config/kdeglobals");
+ return kdeDir + QStringLiteral("/share/config/kdeglobals");
}
void refresh();
- static void readKdeSystemPalette(const QSettings &kdeSettings, QPalette *pal);
- static QFont *readKdeFontSetting(const QSettings &settings, const QString &key);
- static QStringList kdeIconThemeSearchPaths(const QString &kdeHome);
+ static QVariant readKdeSetting(const QString &key, const QStringList &kdeDirs, QHash<QString, QSettings*> &kdeSettings);
+ static void readKdeSystemPalette(const QStringList &kdeDirs, QHash<QString, QSettings*> &kdeSettings, QPalette *pal);
+ static QFont *kdeFont(const QVariant &fontValue);
+ static QStringList kdeIconThemeSearchPaths(const QStringList &kdeDirs);
-
- const QString kdeHome;
+ const QStringList kdeDirs;
const int kdeVersion;
ResourceHelper resources;
@@ -212,36 +213,33 @@ void QKdeThemePrivate::refresh()
styleNames << QStringLiteral("Oxygen") << QStringLiteral("fusion") << QStringLiteral("windows");
iconFallbackThemeName = iconThemeName = QStringLiteral("oxygen");
- // Read settings file.
- const QString settingsFile = globalSettingsFile();
- if (!QFileInfo(settingsFile).isReadable())
- return;
-
- const QSettings kdeSettings(settingsFile, QSettings::IniFormat);
+ QHash<QString, QSettings*> kdeSettings;
QPalette systemPalette = QPalette();
- readKdeSystemPalette(kdeSettings, &systemPalette);
+ readKdeSystemPalette(kdeDirs, kdeSettings, &systemPalette);
resources.palettes[QPlatformTheme::SystemPalette] = new QPalette(systemPalette);
//## TODO tooltip color
- const QVariant styleValue = kdeSettings.value(QStringLiteral("widgetStyle"));
+ const QVariant styleValue = readKdeSetting(QStringLiteral("widgetStyle"), kdeDirs, kdeSettings);
if (styleValue.isValid()) {
const QString style = styleValue.toString();
if (style != styleNames.front())
styleNames.push_front(style);
}
- singleClick = kdeSettings.value(QStringLiteral("KDE/SingleClick"), true).toBool();
+ const QVariant singleClickValue = readKdeSetting(QStringLiteral("KDE/SingleClick"), kdeDirs, kdeSettings);
+ if (singleClickValue.isValid())
+ singleClick = singleClickValue.toBool();
- const QVariant themeValue = kdeSettings.value(QStringLiteral("Icons/Theme"));
+ const QVariant themeValue = readKdeSetting(QStringLiteral("Icons/Theme"), kdeDirs, kdeSettings);
if (themeValue.isValid())
iconThemeName = themeValue.toString();
- const QVariant toolBarIconSizeValue = kdeSettings.value(QStringLiteral("ToolbarIcons/Size"));
+ const QVariant toolBarIconSizeValue = readKdeSetting(QStringLiteral("ToolbarIcons/Size"), kdeDirs, kdeSettings);
if (toolBarIconSizeValue.isValid())
toolBarIconSize = toolBarIconSizeValue.toInt();
- const QVariant toolbarStyleValue = kdeSettings.value(QStringLiteral("ToolButtonStyle"));
+ const QVariant toolbarStyleValue = readKdeSetting(QStringLiteral("Toolbar style/ToolButtonStyle"), kdeDirs, kdeSettings);
if (toolbarStyleValue.isValid()) {
const QString toolBarStyle = toolbarStyleValue.toString();
if (toolBarStyle == QStringLiteral("TextBesideIcon"))
@@ -253,26 +251,46 @@ void QKdeThemePrivate::refresh()
}
// Read system font, ignore 'smallestReadableFont'
- if (QFont *systemFont = readKdeFontSetting(kdeSettings, QStringLiteral("font")))
+ if (QFont *systemFont = kdeFont(readKdeSetting(QStringLiteral("font"), kdeDirs, kdeSettings)))
resources.fonts[QPlatformTheme::SystemFont] = systemFont;
else
resources.fonts[QPlatformTheme::SystemFont] = new QFont(QLatin1String(defaultSystemFontNameC), defaultSystemFontSize);
- if (QFont *fixedFont = readKdeFontSetting(kdeSettings, QStringLiteral("fixed"))) {
+ if (QFont *fixedFont = kdeFont(readKdeSetting(QStringLiteral("fixed"), kdeDirs, kdeSettings))) {
resources.fonts[QPlatformTheme::FixedFont] = fixedFont;
} else {
fixedFont = new QFont(QLatin1String(defaultSystemFontNameC), defaultSystemFontSize);
fixedFont->setStyleHint(QFont::TypeWriter);
resources.fonts[QPlatformTheme::FixedFont] = fixedFont;
}
+
+ qDeleteAll(kdeSettings);
+}
+
+QVariant QKdeThemePrivate::readKdeSetting(const QString &key, const QStringList &kdeDirs, QHash<QString, QSettings*> &kdeSettings)
+{
+ foreach (const QString &kdeDir, kdeDirs) {
+ QSettings *settings = kdeSettings.value(kdeDir);
+ if (!settings) {
+ const QString kdeGlobalsPath = kdeGlobals(kdeDir);
+ if (QFileInfo(kdeGlobalsPath).isReadable()) {
+ settings = new QSettings(kdeGlobalsPath, QSettings::IniFormat);
+ kdeSettings.insert(kdeDir, settings);
+ }
+ }
+ if (settings) {
+ const QVariant value = settings->value(key);
+ if (value.isValid())
+ return value;
+ }
+ }
+ return QVariant();
}
// Reads the color from the KDE configuration, and store it in the
// palette with the given color role if found.
-static inline bool kdeColor(QPalette *pal, QPalette::ColorRole role,
- const QSettings &kdeSettings, const QString &key)
+static inline bool kdeColor(QPalette *pal, QPalette::ColorRole role, const QVariant &value)
{
- const QVariant value = kdeSettings.value(key);
if (!value.isValid())
return false;
const QStringList values = value.toStringList();
@@ -282,9 +300,9 @@ static inline bool kdeColor(QPalette *pal, QPalette::ColorRole role,
return true;
}
-void QKdeThemePrivate::readKdeSystemPalette(const QSettings &kdeSettings, QPalette *pal)
+void QKdeThemePrivate::readKdeSystemPalette(const QStringList &kdeDirs, QHash<QString, QSettings*> &kdeSettings, QPalette *pal)
{
- if (!kdeSettings.contains(QStringLiteral("Colors:Button/BackgroundNormal"))) {
+ if (!kdeColor(pal, QPalette::Button, readKdeSetting(QStringLiteral("Colors:Button/BackgroundNormal"), kdeDirs, kdeSettings))) {
// kcolorscheme.cpp: SetDefaultColors
const QColor defaultWindowBackground(214, 210, 208);
const QColor defaultButtonBackground(223, 220, 217);
@@ -292,19 +310,18 @@ void QKdeThemePrivate::readKdeSystemPalette(const QSettings &kdeSettings, QPalet
return;
}
- kdeColor(pal, QPalette::Button, kdeSettings, QStringLiteral("Colors:Button/BackgroundNormal"));
- kdeColor(pal, QPalette::Window, kdeSettings, QStringLiteral("Colors:Window/BackgroundNormal"));
- kdeColor(pal, QPalette::Text, kdeSettings, QStringLiteral("Colors:View/ForegroundNormal"));
- kdeColor(pal, QPalette::WindowText, kdeSettings, QStringLiteral("Colors:Window/ForegroundNormal"));
- kdeColor(pal, QPalette::Base, kdeSettings, QStringLiteral("Colors:View/BackgroundNormal"));
- kdeColor(pal, QPalette::Highlight, kdeSettings, QStringLiteral("Colors:Selection/BackgroundNormal"));
- kdeColor(pal, QPalette::HighlightedText, kdeSettings, QStringLiteral("Colors:Selection/ForegroundNormal"));
- kdeColor(pal, QPalette::AlternateBase, kdeSettings, QStringLiteral("Colors:View/BackgroundAlternate"));
- kdeColor(pal, QPalette::ButtonText, kdeSettings, QStringLiteral("Colors:Button/ForegroundNormal"));
- kdeColor(pal, QPalette::Link, kdeSettings, QStringLiteral("Colors:View/ForegroundLink"));
- kdeColor(pal, QPalette::LinkVisited, kdeSettings, QStringLiteral("Colors:View/ForegroundVisited"));
- kdeColor(pal, QPalette::ToolTipBase, kdeSettings, QStringLiteral("Colors:Tooltip/BackgroundNormal"));
- kdeColor(pal, QPalette::ToolTipText, kdeSettings, QStringLiteral("Colors:Tooltip/ForegroundNormal"));
+ kdeColor(pal, QPalette::Window, readKdeSetting(QStringLiteral("Colors:Window/BackgroundNormal"), kdeDirs, kdeSettings));
+ kdeColor(pal, QPalette::Text, readKdeSetting(QStringLiteral("Colors:View/ForegroundNormal"), kdeDirs, kdeSettings));
+ kdeColor(pal, QPalette::WindowText, readKdeSetting(QStringLiteral("Colors:Window/ForegroundNormal"), kdeDirs, kdeSettings));
+ kdeColor(pal, QPalette::Base, readKdeSetting(QStringLiteral("Colors:View/BackgroundNormal"), kdeDirs, kdeSettings));
+ kdeColor(pal, QPalette::Highlight, readKdeSetting(QStringLiteral("Colors:Selection/BackgroundNormal"), kdeDirs, kdeSettings));
+ kdeColor(pal, QPalette::HighlightedText, readKdeSetting(QStringLiteral("Colors:Selection/ForegroundNormal"), kdeDirs, kdeSettings));
+ kdeColor(pal, QPalette::AlternateBase, readKdeSetting(QStringLiteral("Colors:View/BackgroundAlternate"), kdeDirs, kdeSettings));
+ kdeColor(pal, QPalette::ButtonText, readKdeSetting(QStringLiteral("Colors:Button/ForegroundNormal"), kdeDirs, kdeSettings));
+ kdeColor(pal, QPalette::Link, readKdeSetting(QStringLiteral("Colors:View/ForegroundLink"), kdeDirs, kdeSettings));
+ kdeColor(pal, QPalette::LinkVisited, readKdeSetting(QStringLiteral("Colors:View/ForegroundVisited"), kdeDirs, kdeSettings));
+ kdeColor(pal, QPalette::ToolTipBase, readKdeSetting(QStringLiteral("Colors:Tooltip/BackgroundNormal"), kdeDirs, kdeSettings));
+ kdeColor(pal, QPalette::ToolTipText, readKdeSetting(QStringLiteral("Colors:Tooltip/ForegroundNormal"), kdeDirs, kdeSettings));
// The above code sets _all_ color roles to "normal" colors. In KDE, the disabled
// color roles are calculated by applying various effects described in kdeglobals.
@@ -347,15 +364,14 @@ void QKdeThemePrivate::readKdeSystemPalette(const QSettings &kdeSettings, QPalet
const char *QKdeTheme::name = "kde";
-QKdeTheme::QKdeTheme(const QString &kdeHome, int kdeVersion)
- : QPlatformTheme(new QKdeThemePrivate(kdeHome,kdeVersion))
+QKdeTheme::QKdeTheme(const QStringList& kdeDirs, int kdeVersion)
+ : QPlatformTheme(new QKdeThemePrivate(kdeDirs,kdeVersion))
{
d_func()->refresh();
}
-QFont *QKdeThemePrivate::readKdeFontSetting(const QSettings &settings, const QString &key)
+QFont *QKdeThemePrivate::kdeFont(const QVariant &fontValue)
{
- const QVariant fontValue = settings.value(key);
if (fontValue.isValid()) {
// Read font value: Might be a QStringList as KDE stores fonts without quotes.
// Also retrieve the family for the constructor since we cannot use the
@@ -382,16 +398,11 @@ QFont *QKdeThemePrivate::readKdeFontSetting(const QSettings &settings, const QSt
}
-QStringList QKdeThemePrivate::kdeIconThemeSearchPaths(const QString &kdeHome)
+QStringList QKdeThemePrivate::kdeIconThemeSearchPaths(const QStringList &kdeDirs)
{
- QStringList candidates = QStringList(kdeHome);
- const QString kdeDirs = QFile::decodeName(qgetenv("KDEDIRS"));
- if (!kdeDirs.isEmpty())
- candidates.append(kdeDirs.split(QLatin1Char(':')));
-
QStringList paths = QGenericUnixTheme::xdgIconThemePaths();
const QString iconPath = QStringLiteral("/share/icons");
- foreach (const QString &candidate, candidates) {
+ foreach (const QString &candidate, kdeDirs) {
const QFileInfo fi(candidate + iconPath);
if (fi.isDir())
paths.append(fi.absoluteFilePath());
@@ -418,7 +429,7 @@ QVariant QKdeTheme::themeHint(QPlatformTheme::ThemeHint hint) const
case QPlatformTheme::SystemIconFallbackThemeName:
return QVariant(d->iconFallbackThemeName);
case QPlatformTheme::IconThemeSearchPaths:
- return QVariant(d->kdeIconThemeSearchPaths(d->kdeHome));
+ return QVariant(d->kdeIconThemeSearchPaths(d->kdeDirs));
case QPlatformTheme::StyleNames:
return QVariant(d->styleNames);
case QPlatformTheme::KeyboardScheme:
@@ -445,26 +456,52 @@ const QFont *QKdeTheme::font(Font type) const
QPlatformTheme *QKdeTheme::createKdeTheme()
{
- // Check for version >= 4 and determine home folder from environment,
- // defaulting to ~/.kde<version>, ~/.kde
const QByteArray kdeVersionBA = qgetenv("KDE_SESSION_VERSION");
const int kdeVersion = kdeVersionBA.toInt();
if (kdeVersion < 4)
return 0;
- const QString kdeHomePathVar = QString::fromLocal8Bit(qgetenv("KDEHOME"));
+
+ // Determine KDE prefixes in the following priority order:
+ // - KDEHOME and KDEDIRS environment variables
+ // - ~/.kde(<version>)
+ // - read prefixes from /etc/kde<version>rc
+ // - fallback to /etc/kde<version>
+
+ QStringList kdeDirs;
+ const QString kdeHomePathVar = QFile::decodeName(qgetenv("KDEHOME"));
if (!kdeHomePathVar.isEmpty())
- return new QKdeTheme(kdeHomePathVar, kdeVersion);
+ kdeDirs += kdeHomePathVar;
+
+ const QString kdeDirsVar = QFile::decodeName(qgetenv("KDEDIRS"));
+ if (!kdeDirsVar.isEmpty())
+ kdeDirs += kdeDirsVar.split(QLatin1Char(':'), QString::SkipEmptyParts);
+
+ const QString kdeVersionHomePath = QDir::homePath() + QStringLiteral("/.kde") + QLatin1String(kdeVersionBA);
+ if (QFileInfo(kdeVersionHomePath).isDir())
+ kdeDirs += kdeVersionHomePath;
- const QString kdeVersionHomePath = QDir::homePath() + QStringLiteral("/.kde") + QLatin1String(kdeVersionBA);
- if (QFileInfo(kdeVersionHomePath).isDir())
- return new QKdeTheme(kdeVersionHomePath, kdeVersion);
+ const QString kdeHomePath = QDir::homePath() + QStringLiteral("/.kde");
+ if (QFileInfo(kdeHomePath).isDir())
+ kdeDirs += kdeHomePath;
- const QString kdeHomePath = QDir::homePath() + QStringLiteral("/.kde");
- if (QFileInfo(kdeHomePath).isDir())
- return new QKdeTheme(kdeHomePath, kdeVersion);
+ const QString kdeRcPath = QStringLiteral("/etc/kde") + QLatin1String(kdeVersionBA) + QStringLiteral("rc");
+ if (QFileInfo(kdeRcPath).isReadable()) {
+ QSettings kdeSettings(kdeRcPath, QSettings::IniFormat);
+ kdeSettings.beginGroup(QStringLiteral("Directories-default"));
+ kdeDirs += kdeSettings.value(QStringLiteral("prefixes")).toStringList();
+ }
+
+ const QString kdeVersionPrefix = QStringLiteral("/etc/kde") + QLatin1String(kdeVersionBA);
+ if (QFileInfo(kdeVersionPrefix).isDir())
+ kdeDirs += kdeVersionPrefix;
+
+ kdeDirs.removeDuplicates();
+ if (kdeDirs.isEmpty()) {
+ qWarning("%s: Unable to determine KDE dirs", Q_FUNC_INFO);
+ return 0;
+ }
- qWarning("%s: Unable to determine KDEHOME", Q_FUNC_INFO);
- return 0;
+ return new QKdeTheme(kdeDirs, kdeVersion);
}
#endif // QT_NO_SETTINGS
diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h b/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h
index 36fcdd8dce..d01e6d485c 100644
--- a/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h
+++ b/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h
@@ -87,7 +87,7 @@ class QKdeTheme : public QPlatformTheme
{
Q_DECLARE_PRIVATE(QKdeTheme)
public:
- QKdeTheme(const QString &kdeHome, int kdeVersion);
+ QKdeTheme(const QStringList& kdeDirs, int kdeVersion);
static QPlatformTheme *createKdeTheme();
virtual QVariant themeHint(ThemeHint hint) const;
diff --git a/src/plugins/accessible/accessible.pro b/src/plugins/accessible/accessible.pro
deleted file mode 100644
index 26c7d3066d..0000000000
--- a/src/plugins/accessible/accessible.pro
+++ /dev/null
@@ -1,5 +0,0 @@
-TEMPLATE = subdirs
-
-contains(QT_CONFIG, accessibility) {
- SUBDIRS += widgets
-}
diff --git a/src/plugins/accessible/widgets/widgets.json b/src/plugins/accessible/widgets/widgets.json
deleted file mode 100644
index 9ebcc89d35..0000000000
--- a/src/plugins/accessible/widgets/widgets.json
+++ /dev/null
@@ -1,54 +0,0 @@
-{
- "Keys": [
- "QLineEdit",
- "QComboBox",
- "QAbstractSpinBox",
- "QSpinBox",
- "QDoubleSpinBox",
- "QScrollBar",
- "QSlider",
- "QAbstractSlider",
- "QToolButton",
- "QCheckBox",
- "QRadioButton",
- "QPushButton",
- "QAbstractButton",
- "QDialog",
- "QMessageBox",
- "QMainWindow",
- "QLabel",
- "QLCDNumber",
- "QGroupBox",
- "QStatusBar",
- "QProgressBar",
- "QPlainTextEdit",
- "QMenuBar",
- "QMenu",
- "QTabBar",
- "QToolBar",
- "QSizeGrip",
- "QListView",
- "QTreeView",
- "QTableView",
- "QWidget",
- "QSplitter",
- "QSplitterHandle",
- "QTextEdit",
- "QTipLabel",
- "QFrame",
- "QStackedWidget",
- "QToolBox",
- "QMdiArea",
- "QMdiSubWindow",
- "QDialogButtonBox",
- "QDial",
- "QRubberBand",
- "QTextBrowser",
- "QAbstractScrollArea",
- "QScrollArea",
- "QCalendarWidget",
- "QDockWidget",
- "QDesktopScreenWidget",
- "QWindowContainer"
- ]
-}
diff --git a/src/plugins/bearer/android/android.pro b/src/plugins/bearer/android/android.pro
new file mode 100644
index 0000000000..6a51abf5d7
--- /dev/null
+++ b/src/plugins/bearer/android/android.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+
+SUBDIRS += src \
+ jar
diff --git a/src/plugins/bearer/android/jar/bundledjar.pro b/src/plugins/bearer/android/jar/bundledjar.pro
new file mode 100644
index 0000000000..6037f813f2
--- /dev/null
+++ b/src/plugins/bearer/android/jar/bundledjar.pro
@@ -0,0 +1,3 @@
+TARGET = QtAndroidBearer-bundled
+CONFIG += bundled_jar_file
+include(jar.pri)
diff --git a/src/plugins/bearer/android/jar/distributedjar.pro b/src/plugins/bearer/android/jar/distributedjar.pro
new file mode 100644
index 0000000000..c769a113d5
--- /dev/null
+++ b/src/plugins/bearer/android/jar/distributedjar.pro
@@ -0,0 +1,2 @@
+TARGET = QtAndroidBearer
+include(jar.pri)
diff --git a/src/plugins/bearer/android/jar/jar.pri b/src/plugins/bearer/android/jar/jar.pri
new file mode 100644
index 0000000000..6d9aac3bb3
--- /dev/null
+++ b/src/plugins/bearer/android/jar/jar.pri
@@ -0,0 +1,13 @@
+load(qt_build_paths)
+CONFIG += java
+DESTDIR = $$MODULE_BASE_OUTDIR/jar
+
+JAVACLASSPATH += $$PWD/src
+
+JAVASOURCES += $$PWD/src/org/qtproject/qt5/android/bearer/QtNetworkReceiver.java
+
+# install
+target.path = $$[QT_INSTALL_PREFIX]/jar
+INSTALLS += target
+
+OTHER_FILES += $$JAVASOURCES
diff --git a/src/plugins/bearer/android/jar/jar.pro b/src/plugins/bearer/android/jar/jar.pro
new file mode 100644
index 0000000000..923e757d9b
--- /dev/null
+++ b/src/plugins/bearer/android/jar/jar.pro
@@ -0,0 +1,2 @@
+TEMPLATE=subdirs
+SUBDIRS += distributedjar.pro bundledjar.pro
diff --git a/src/plugins/bearer/android/jar/src/org/qtproject/qt5/android/bearer/QtNetworkReceiver.java b/src/plugins/bearer/android/jar/src/org/qtproject/qt5/android/bearer/QtNetworkReceiver.java
new file mode 100644
index 0000000000..df0a37edc0
--- /dev/null
+++ b/src/plugins/bearer/android/jar/src/org/qtproject/qt5/android/bearer/QtNetworkReceiver.java
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+package org.qtproject.qt5.android.bearer;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.util.Log;
+import android.app.Activity;
+import android.net.ConnectivityManager;
+
+public class QtNetworkReceiver
+{
+ private static final String LOG_TAG = "QtNetworkReceiver";
+ private static native void activeNetworkInfoChanged();
+ private static BroadcastReceiverPrivate m_broadcastReceiver = null;
+ private static final Object m_lock = new Object();
+
+ private static class BroadcastReceiverPrivate extends BroadcastReceiver
+ {
+ @Override
+ public void onReceive(Context context, Intent intent)
+ {
+ activeNetworkInfoChanged();
+ }
+ }
+
+ private QtNetworkReceiver() {}
+
+ public static void registerReceiver(final Activity activity)
+ {
+ synchronized (m_lock) {
+ if (m_broadcastReceiver == null) {
+ m_broadcastReceiver = new BroadcastReceiverPrivate();
+ IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
+ activity.registerReceiver(m_broadcastReceiver, intentFilter);
+ }
+ }
+ }
+
+ public static void unregisterReceiver(final Activity activity)
+ {
+ synchronized (m_lock) {
+ if (m_broadcastReceiver == null)
+ return;
+
+ activity.unregisterReceiver(m_broadcastReceiver);
+ }
+ }
+
+ public static ConnectivityManager getConnectivityManager(final Activity activity)
+ {
+ return (ConnectivityManager)activity.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+ }
+}
diff --git a/src/plugins/bearer/android/src/android.json b/src/plugins/bearer/android/src/android.json
new file mode 100644
index 0000000000..6843bd3301
--- /dev/null
+++ b/src/plugins/bearer/android/src/android.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "android" ]
+}
diff --git a/src/plugins/bearer/android/src/main.cpp b/src/plugins/bearer/android/src/main.cpp
new file mode 100644
index 0000000000..9880b94b0c
--- /dev/null
+++ b/src/plugins/bearer/android/src/main.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidbearerengine.h"
+#include <QtNetwork/private/qbearerplugin_p.h>
+
+#ifndef QT_NO_BEARERMANAGEMENT
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidBearerEnginePlugin : public QBearerEnginePlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QBearerEngineFactoryInterface" FILE "android.json")
+
+public:
+ QBearerEngine *create(const QString &key) const Q_DECL_OVERRIDE
+ {
+ return (key == QStringLiteral("android")) ? new QAndroidBearerEngine() : 0;
+ }
+};
+
+QT_END_NAMESPACE
+
+#include "main.moc"
+
+#endif // QT_NO_BEARERMANAGEMENT
diff --git a/src/plugins/bearer/android/src/qandroidbearerengine.cpp b/src/plugins/bearer/android/src/qandroidbearerengine.cpp
new file mode 100644
index 0000000000..38cd9c2de3
--- /dev/null
+++ b/src/plugins/bearer/android/src/qandroidbearerengine.cpp
@@ -0,0 +1,405 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidbearerengine.h"
+#include "../../qnetworksession_impl.h"
+#include "wrappers/androidconnectivitymanager.h"
+
+#ifndef QT_NO_BEARERMANAGEMENT
+
+QT_BEGIN_NAMESPACE
+
+static QString networkConfType(const AndroidNetworkInfo &networkInfo)
+{
+ switch (networkInfo.getType()) {
+ case AndroidNetworkInfo::Mobile:
+ return QStringLiteral("Mobile");
+ case AndroidNetworkInfo::Wifi:
+ return QStringLiteral("WiFi");
+ case AndroidNetworkInfo::Wimax:
+ return QStringLiteral("WiMax");
+ case AndroidNetworkInfo::Ethernet:
+ return QStringLiteral("Ethernet");
+ case AndroidNetworkInfo::Bluetooth:
+ return QStringLiteral("Bluetooth");
+ default:
+ break;
+ }
+
+ return QString();
+}
+
+static inline bool isMobile(QNetworkConfiguration::BearerType type)
+{
+ if (type == QNetworkConfiguration::BearerWLAN
+ || type == QNetworkConfiguration::BearerWiMAX
+ || type == QNetworkConfiguration::BearerBluetooth
+ || type == QNetworkConfiguration::BearerEthernet
+ || type == QNetworkConfiguration::BearerUnknown) {
+ return false;
+ }
+
+ return true;
+}
+
+static QNetworkConfiguration::BearerType getBearerType(const AndroidNetworkInfo &networkInfo)
+{
+ switch (networkInfo.getType()) {
+ case AndroidNetworkInfo::Mobile:
+ {
+ switch (networkInfo.getSubtype()) {
+ case AndroidNetworkInfo::Gprs:
+ case AndroidNetworkInfo::Edge:
+ case AndroidNetworkInfo::Iden: // 2G
+ return QNetworkConfiguration::Bearer2G;
+ case AndroidNetworkInfo::Umts: // BearerWCDMA (3 .5 .75 G)
+ case AndroidNetworkInfo::Hsdpa: // 3G (?) UMTS
+ case AndroidNetworkInfo::Hsupa: // 3G (?) UMTS
+ return QNetworkConfiguration::BearerWCDMA;
+ case AndroidNetworkInfo::Cdma: // CDMA ISA95[AB]
+ case AndroidNetworkInfo::Cdma1xRTT: // BearerCDMA2000 (3G)
+ case AndroidNetworkInfo::Ehrpd: // CDMA Bridge thing?!?
+ return QNetworkConfiguration::BearerCDMA2000;
+ case AndroidNetworkInfo::Evdo0: // BearerEVDO
+ case AndroidNetworkInfo::EvdoA: // BearerEVDO
+ case AndroidNetworkInfo::EvdoB: // BearerEVDO
+ return QNetworkConfiguration::BearerEVDO;
+ case AndroidNetworkInfo::Hspa:
+ case AndroidNetworkInfo::Hspap: // HSPA+
+ return QNetworkConfiguration::BearerHSPA;
+ case AndroidNetworkInfo::Lte: // BearerLTE (4G)
+ return QNetworkConfiguration::BearerLTE;
+ default:
+ break;
+ }
+ }
+ case AndroidNetworkInfo::Wifi:
+ return QNetworkConfiguration::BearerWLAN;
+ case AndroidNetworkInfo::Wimax:
+ return QNetworkConfiguration::BearerWiMAX;
+ case AndroidNetworkInfo::Bluetooth:
+ case AndroidNetworkInfo::MobileDun:
+ return QNetworkConfiguration::BearerBluetooth;
+ case AndroidNetworkInfo::Ethernet:
+ return QNetworkConfiguration::BearerEthernet;
+ case AndroidNetworkInfo::MobileMms:
+ case AndroidNetworkInfo::MobileSupl:
+ case AndroidNetworkInfo::MobileHipri:
+ case AndroidNetworkInfo::Dummy:
+ case AndroidNetworkInfo::UnknownType:
+ break;
+ }
+
+ return QNetworkConfiguration::BearerUnknown;
+}
+
+QAndroidBearerEngine::QAndroidBearerEngine(QObject *parent)
+ : QBearerEngineImpl(parent),
+ m_connectivityManager(0)
+{
+}
+
+QAndroidBearerEngine::~QAndroidBearerEngine()
+{
+}
+
+QString QAndroidBearerEngine::getInterfaceFromId(const QString &id)
+{
+ const QMutexLocker locker(&mutex);
+ return m_configurationInterface.value(id);
+}
+
+bool QAndroidBearerEngine::hasIdentifier(const QString &id)
+{
+ const QMutexLocker locker(&mutex);
+ return m_configurationInterface.contains(id);
+}
+
+void QAndroidBearerEngine::connectToId(const QString &id)
+{
+ Q_EMIT connectionError(id, OperationNotSupported);
+}
+
+void QAndroidBearerEngine::disconnectFromId(const QString &id)
+{
+ Q_EMIT connectionError(id, OperationNotSupported);
+}
+
+QNetworkSession::State QAndroidBearerEngine::sessionStateForId(const QString &id)
+{
+ const QMutexLocker locker(&mutex);
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+
+ if ((!ptr || !ptr->isValid) || m_connectivityManager == 0)
+ return QNetworkSession::Invalid;
+
+ const QMutexLocker configLocker(&ptr->mutex);
+ // Don't re-order...
+ if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
+ return (m_connectivityManager->isActiveNetworkMetered()
+ || m_connectivityManager->getActiveNetworkInfo().isRoaming())
+ ? QNetworkSession::Roaming
+ : QNetworkSession::Connected;
+ } else if ((ptr->state & QNetworkConfiguration::Discovered) == QNetworkConfiguration::Discovered) {
+ return QNetworkSession::Disconnected;
+ } else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) {
+ return QNetworkSession::NotAvailable;
+ } else if ((ptr->state & QNetworkConfiguration::Undefined) == QNetworkConfiguration::Undefined) {
+ return QNetworkSession::NotAvailable;
+ }
+
+ return QNetworkSession::Invalid;
+}
+
+QNetworkConfigurationManager::Capabilities QAndroidBearerEngine::capabilities() const
+{
+
+ return AndroidTrafficStats::isTrafficStatsSupported()
+ ? QNetworkConfigurationManager::ForcedRoaming
+ | QNetworkConfigurationManager::DataStatistics
+ : QNetworkConfigurationManager::ForcedRoaming;
+
+}
+
+QNetworkSessionPrivate *QAndroidBearerEngine::createSessionBackend()
+{
+ return new QNetworkSessionPrivateImpl();
+}
+
+QNetworkConfigurationPrivatePointer QAndroidBearerEngine::defaultConfiguration()
+{
+ return QNetworkConfigurationPrivatePointer();
+}
+
+bool QAndroidBearerEngine::requiresPolling() const
+{
+ return false;
+}
+
+quint64 QAndroidBearerEngine::bytesWritten(const QString &id)
+{
+ QMutexLocker lock(&mutex);
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+ if (!ptr || !ptr->isValid)
+ return 0;
+
+ return isMobile(ptr->bearerType)
+ ? AndroidTrafficStats::getMobileTxBytes()
+ : AndroidTrafficStats::getTotalTxBytes() - AndroidTrafficStats::getMobileTxBytes();
+}
+
+quint64 QAndroidBearerEngine::bytesReceived(const QString &id)
+{
+ QMutexLocker lock(&mutex);
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+ if (!ptr || !ptr->isValid)
+ return 0;
+
+ return isMobile(ptr->bearerType)
+ ? AndroidTrafficStats::getMobileRxBytes()
+ : AndroidTrafficStats::getTotalRxBytes() - AndroidTrafficStats::getMobileRxBytes();
+}
+
+quint64 QAndroidBearerEngine::startTime(const QString &id)
+{
+ Q_UNUSED(id);
+ return Q_UINT64_C(0);
+}
+
+void QAndroidBearerEngine::initialize()
+{
+ if (m_connectivityManager != 0)
+ return;
+
+ m_connectivityManager = AndroidConnectivityManager::getInstance();
+ if (m_connectivityManager == 0)
+ return;
+
+ updateConfigurations();
+
+ connect(m_connectivityManager, &AndroidConnectivityManager::activeNetworkChanged,
+ this, &QAndroidBearerEngine::updateConfigurations);
+
+}
+
+void QAndroidBearerEngine::requestUpdate()
+{
+ updateConfigurations();
+}
+
+void QAndroidBearerEngine::updateConfigurations()
+{
+#ifndef QT_NO_NETWORKINTERFACE
+ if (m_connectivityManager == 0)
+ return;
+
+ {
+ QMutexLocker locker(&mutex);
+ QStringList oldKeys = accessPointConfigurations.keys();
+
+ // Create a configuration for each of the main types (WiFi, Mobile, Bluetooth, WiMax, Ethernet)
+ foreach (const AndroidNetworkInfo &netInfo, m_connectivityManager->getAllNetworkInfo()) {
+
+ if (!netInfo.isValid())
+ continue;
+
+ const QString name = networkConfType(netInfo);
+ if (name.isEmpty())
+ continue;
+
+ QNetworkConfiguration::BearerType bearerType = getBearerType(netInfo);
+
+ QNetworkConfiguration::StateFlag state;
+ QString interfaceName;
+ if (netInfo.isAvailable()) {
+ if (netInfo.isConnected()) {
+ state = QNetworkConfiguration::Active;
+ // Attempt to map an interface to this configuration
+ const QList<QNetworkInterface> &interfaces = QNetworkInterface::allInterfaces();
+ foreach (const QNetworkInterface &interface, interfaces) {
+ // ignore loopback interface
+ if (!interface.isValid())
+ continue;
+
+ if (interface.flags() & QNetworkInterface::IsLoopBack)
+ continue;
+ // There is no way to get the interface from the NetworkInfo, so
+ // look for an active interface...
+ if (interface.flags() & QNetworkInterface::IsRunning
+ && !interface.addressEntries().isEmpty()) {
+ interfaceName = interface.humanReadableName();
+ if (interfaceName.isEmpty())
+ interfaceName = interface.name();
+ }
+ }
+ } else if (netInfo.isConnectedOrConnecting()) {
+ state = QNetworkConfiguration::Undefined;
+ } else {
+ state = QNetworkConfiguration::Discovered;
+ }
+ } else {
+ state = QNetworkConfiguration::Defined;
+ }
+
+ const uint identifier = qHash(QLatin1String("android:") + name);
+ const QString id = QString::number(identifier);
+
+ oldKeys.removeAll(id);
+ if (accessPointConfigurations.contains(id)) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+ bool changed = false;
+ {
+ const QMutexLocker confLocker(&ptr->mutex);
+
+ if (!ptr->isValid) {
+ ptr->isValid = true;
+ changed = true;
+ }
+
+ // Don't reset the bearer type to 'Unknown'
+ if (ptr->bearerType != QNetworkConfiguration::BearerUnknown
+ && ptr->bearerType != bearerType) {
+ ptr->bearerType = bearerType;
+ changed = true;
+ }
+
+ if (ptr->name != name) {
+ ptr->name = name;
+ changed = true;
+ }
+
+ if (ptr->id != id) {
+ ptr->id = id;
+ changed = true;
+ }
+
+ if (ptr->state != state) {
+ ptr->state = state;
+ changed = true;
+ }
+
+ QString &oldIfName = m_configurationInterface[id];
+ if (oldIfName != interfaceName) {
+ oldIfName = interfaceName;
+ changed = true;
+ }
+ } // Unlock configuration
+
+ if (changed) {
+ locker.unlock();
+ Q_EMIT configurationChanged(ptr);
+ locker.relock();
+ }
+ } else {
+ QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate);
+ ptr->name = name;
+ ptr->isValid = true;
+ ptr->id = id;
+ ptr->state = state;
+ ptr->type = QNetworkConfiguration::InternetAccessPoint;
+ ptr->bearerType = bearerType;
+ accessPointConfigurations.insert(id, ptr);
+ m_configurationInterface.insert(id, interfaceName);
+
+ locker.unlock();
+ Q_EMIT configurationAdded(ptr);
+ locker.relock();
+ }
+ }
+
+ while (!oldKeys.isEmpty()) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(oldKeys.takeFirst());
+ m_configurationInterface.remove(ptr->id);
+ locker.unlock();
+ Q_EMIT configurationRemoved(ptr);
+ locker.relock();
+ }
+
+ } // Unlock engine
+
+#endif // QT_NO_NETWORKINTERFACE
+
+ Q_EMIT updateCompleted();
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_BEARERMANAGEMENT
diff --git a/src/plugins/bearer/android/src/qandroidbearerengine.h b/src/plugins/bearer/android/src/qandroidbearerengine.h
new file mode 100644
index 0000000000..93e576e040
--- /dev/null
+++ b/src/plugins/bearer/android/src/qandroidbearerengine.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDBEARERENGINE_H
+#define QANDROIDBEARERENGINE_H
+
+#include "../../qbearerengine_impl.h"
+
+#include <QAbstractEventDispatcher>
+#include <QAbstractNativeEventFilter>
+#include <QtCore/private/qjni_p.h>
+
+#ifndef QT_NO_BEARERMANAGEMENT
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkConfigurationPrivate;
+class QNetworkSessionPrivate;
+class AndroidConnectivityManager;
+
+class QAndroidBearerEngine : public QBearerEngineImpl
+{
+ Q_OBJECT
+
+public:
+ explicit QAndroidBearerEngine(QObject *parent = 0);
+ ~QAndroidBearerEngine() Q_DECL_OVERRIDE;
+
+ QString getInterfaceFromId(const QString &id) Q_DECL_OVERRIDE;
+ bool hasIdentifier(const QString &id) Q_DECL_OVERRIDE;
+ void connectToId(const QString &id) Q_DECL_OVERRIDE;
+ void disconnectFromId(const QString &id) Q_DECL_OVERRIDE;
+ QNetworkSession::State sessionStateForId(const QString &id) Q_DECL_OVERRIDE;
+ QNetworkConfigurationManager::Capabilities capabilities() const Q_DECL_OVERRIDE;
+ QNetworkSessionPrivate *createSessionBackend() Q_DECL_OVERRIDE;
+ QNetworkConfigurationPrivatePointer defaultConfiguration() Q_DECL_OVERRIDE;
+ bool requiresPolling() const Q_DECL_OVERRIDE;
+ quint64 bytesWritten(const QString &id) Q_DECL_OVERRIDE;
+ quint64 bytesReceived(const QString &id) Q_DECL_OVERRIDE;
+ quint64 startTime(const QString &id) Q_DECL_OVERRIDE;
+
+ Q_INVOKABLE void initialize();
+ Q_INVOKABLE void requestUpdate();
+
+private Q_SLOTS:
+ void updateConfigurations();
+
+private:
+ QJNIObjectPrivate m_networkReceiver;
+ AndroidConnectivityManager *m_connectivityManager;
+ QMap<QString, QString> m_configurationInterface;
+};
+
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_BEARERMANAGEMENT
+
+#endif // QANDROIDBEARERENGINE_H
diff --git a/src/plugins/bearer/android/src/src.pro b/src/plugins/bearer/android/src/src.pro
new file mode 100644
index 0000000000..1050601896
--- /dev/null
+++ b/src/plugins/bearer/android/src/src.pro
@@ -0,0 +1,17 @@
+include(wrappers/wrappers.pri)
+
+TARGET = qandroidbearer
+
+PLUGIN_TYPE = bearer
+PLUGIN_CLASS_NAME = QAndroidBearerEnginePlugin
+load(qt_plugin)
+
+QT = core-private network-private
+
+HEADERS += qandroidbearerengine.h \
+ ../../qnetworksession_impl.h \
+ ../../qbearerengine_impl.h
+
+SOURCES += main.cpp \
+ qandroidbearerengine.cpp \
+ ../../qnetworksession_impl.cpp
diff --git a/src/plugins/bearer/android/src/wrappers/androidconnectivitymanager.cpp b/src/plugins/bearer/android/src/wrappers/androidconnectivitymanager.cpp
new file mode 100644
index 0000000000..df2c3db0d6
--- /dev/null
+++ b/src/plugins/bearer/android/src/wrappers/androidconnectivitymanager.cpp
@@ -0,0 +1,394 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "androidconnectivitymanager.h"
+#include <QtCore/private/qjni_p.h>
+#include <QtCore/private/qjnihelpers_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static inline bool exceptionCheckAndClear(JNIEnv *env)
+{
+ if (!env->ExceptionCheck())
+ return false;
+
+#ifdef QT_DEBUG
+ env->ExceptionDescribe();
+#endif // QT_DEBUG
+ env->ExceptionClear();
+
+ return true;
+}
+
+struct AndroidConnectivityManagerInstance
+{
+ AndroidConnectivityManagerInstance()
+ : connManager(new AndroidConnectivityManager)
+ { }
+ ~AndroidConnectivityManagerInstance()
+ {
+ delete connManager;
+ }
+
+ AndroidConnectivityManager* connManager;
+};
+
+Q_GLOBAL_STATIC(AndroidConnectivityManagerInstance, androidConnManagerInstance)
+
+static const char networkReceiverClass[] = "org/qtproject/qt5/android/bearer/QtNetworkReceiver";
+static const char trafficStatsClass[] = "android/net/TrafficStats";
+
+/**
+ * Returns the number of bytes transmitted over the mobile network since last device boot.
+ */
+qint64 AndroidTrafficStats::getMobileTxBytes()
+{
+ return QJNIObjectPrivate::callStaticMethod<jlong>(trafficStatsClass,
+ "getMobileTxBytes",
+ "()J");
+}
+
+/**
+ * Returns the number of bytes received over the mobile network since last device boot.
+ */
+qint64 AndroidTrafficStats::getMobileRxBytes()
+{
+ return QJNIObjectPrivate::callStaticMethod<jlong>(trafficStatsClass,
+ "getMobileRxBytes",
+ "()J");
+}
+
+/**
+ * Returns the total transmitted bytes since last device boot.
+ */
+qint64 AndroidTrafficStats::getTotalTxBytes()
+{
+ return QJNIObjectPrivate::callStaticMethod<jlong>(trafficStatsClass,
+ "getTotalTxBytes",
+ "()J");
+}
+
+/**
+ * Returns the total received bytes since last device boot.
+ */
+qint64 AndroidTrafficStats::getTotalRxBytes()
+{
+ return QJNIObjectPrivate::callStaticMethod<jlong>(trafficStatsClass,
+ "getTotalRxBytes",
+ "()J");
+}
+
+bool AndroidTrafficStats::isTrafficStatsSupported()
+{
+ // Before API level 18 DataStatistics might not be supported, so make sure that we get something
+ // else then -1 from from getXXBytes().
+ return (AndroidTrafficStats::getMobileRxBytes() != -1
+ && AndroidTrafficStats::getTotalRxBytes() != -1);
+}
+
+static AndroidNetworkInfo::NetworkState stateForName(const QString stateName)
+{
+ if (stateName == QLatin1String("CONNECTED"))
+ return AndroidNetworkInfo::Connected;
+ else if (stateName == QLatin1String("CONNECTING"))
+ return AndroidNetworkInfo::Connecting;
+ else if (stateName == QLatin1String("DISCONNECTED"))
+ return AndroidNetworkInfo::Disconnected;
+ else if (stateName == QLatin1String("DISCONNECTING"))
+ return AndroidNetworkInfo::Disconnecting;
+ else if (stateName == QLatin1String("SUSPENDED"))
+ return AndroidNetworkInfo::Suspended;
+
+ return AndroidNetworkInfo::UnknownState;
+}
+
+AndroidNetworkInfo::NetworkState AndroidNetworkInfo::getDetailedState() const
+{
+ QJNIObjectPrivate enumObject = m_networkInfo.callObjectMethod("getDetailedState",
+ "()Landroid/net/NetworkInfo$DetailedState;");
+ if (!enumObject.isValid())
+ return UnknownState;
+
+ QJNIObjectPrivate enumName = enumObject.callObjectMethod<jstring>("name");
+ if (!enumName.isValid())
+ return UnknownState;
+
+ return stateForName(enumName.toString());
+}
+
+QString AndroidNetworkInfo::getExtraInfo() const
+{
+ QJNIObjectPrivate extraInfo = m_networkInfo.callObjectMethod<jstring>("getExtraInfo");
+ if (!extraInfo.isValid())
+ return QString();
+
+ return extraInfo.toString();
+}
+
+QString AndroidNetworkInfo::getReason() const
+{
+ QJNIObjectPrivate reason = m_networkInfo.callObjectMethod<jstring>("getReason");
+ if (!reason.isValid())
+ return QString();
+
+ return reason.toString();
+}
+
+AndroidNetworkInfo::NetworkState AndroidNetworkInfo::getState() const
+{
+ QJNIObjectPrivate enumObject = m_networkInfo.callObjectMethod("getState",
+ "()Landroid/net/NetworkInfo$State;");
+ if (!enumObject.isValid())
+ return UnknownState;
+
+ QJNIObjectPrivate enumName = enumObject.callObjectMethod<jstring>("name");
+ if (!enumName.isValid())
+ return UnknownState;
+
+ return stateForName(enumName.toString());
+}
+
+AndroidNetworkInfo::NetworkSubType AndroidNetworkInfo::getSubtype() const
+{
+ return AndroidNetworkInfo::NetworkSubType(m_networkInfo.callMethod<jint>("getSubtype"));
+}
+
+QString AndroidNetworkInfo::getSubtypeName() const
+{
+ QJNIObjectPrivate subtypeName = m_networkInfo.callObjectMethod<jstring>("getSubtypeName");
+ if (!subtypeName.isValid())
+ return QString();
+
+ return subtypeName.toString();
+}
+
+AndroidNetworkInfo::NetworkType AndroidNetworkInfo::getType() const
+{
+ return AndroidNetworkInfo::NetworkType(m_networkInfo.callMethod<jint>("getType"));
+}
+
+QString AndroidNetworkInfo::getTypeName() const
+{
+ QJNIObjectPrivate typeName = m_networkInfo.callObjectMethod<jstring>("getTypeName");
+ if (!typeName.isValid())
+ return QString();
+
+ return typeName.toString();
+}
+
+bool AndroidNetworkInfo::isAvailable() const
+{
+ return m_networkInfo.callMethod<jboolean>("isAvailable");
+}
+
+bool AndroidNetworkInfo::isConnected() const
+{
+ return m_networkInfo.callMethod<jboolean>("isConnected");
+}
+
+bool AndroidNetworkInfo::isConnectedOrConnecting() const
+{
+ return m_networkInfo.callMethod<jboolean>("isConnectedOrConnecting");
+}
+
+bool AndroidNetworkInfo::isFailover() const
+{
+ return m_networkInfo.callMethod<jboolean>("isFailover");
+}
+
+bool AndroidNetworkInfo::isRoaming() const
+{
+ return m_networkInfo.callMethod<jboolean>("isRoaming");
+}
+
+bool AndroidNetworkInfo::isValid() const
+{
+ return m_networkInfo.isValid();
+}
+
+AndroidConnectivityManager::AndroidConnectivityManager()
+{
+ QJNIEnvironmentPrivate env;
+ if (!registerNatives(env))
+ return;
+
+ m_connectivityManager = QJNIObjectPrivate::callStaticObjectMethod(networkReceiverClass,
+ "getConnectivityManager",
+ "(Landroid/app/Activity;)Landroid/net/ConnectivityManager;",
+ QtAndroidPrivate::activity());
+ if (!m_connectivityManager.isValid())
+ return;
+
+ QJNIObjectPrivate::callStaticMethod<void>(networkReceiverClass,
+ "registerReceiver",
+ "(Landroid/app/Activity;)V",
+ QtAndroidPrivate::activity());
+}
+
+AndroidConnectivityManager *AndroidConnectivityManager::getInstance()
+{
+ return androidConnManagerInstance->connManager->isValid()
+ ? androidConnManagerInstance->connManager
+ : 0;
+}
+
+AndroidConnectivityManager::~AndroidConnectivityManager()
+{
+ QJNIObjectPrivate::callStaticMethod<void>(networkReceiverClass,
+ "unregisterReceiver",
+ "(Landroid/app/Activity;)V",
+ QtAndroidPrivate::activity());
+}
+
+AndroidNetworkInfo AndroidConnectivityManager::getActiveNetworkInfo() const
+{
+ QJNIObjectPrivate networkInfo = m_connectivityManager.callObjectMethod("getActiveNetworkInfo",
+ "()Landroid/net/NetworkInfo;");
+ return networkInfo;
+}
+
+QList<AndroidNetworkInfo> AndroidConnectivityManager::getAllNetworkInfo() const
+{
+ QJNIEnvironmentPrivate env;
+ QJNIObjectPrivate objArray = m_connectivityManager.callObjectMethod("getAllNetworkInfo",
+ "()[Landroid/net/NetworkInfo;");
+ QList<AndroidNetworkInfo> list;
+ if (!objArray.isValid())
+ return list;
+
+ const jsize length = env->GetArrayLength(static_cast<jarray>(objArray.object()));
+ if (exceptionCheckAndClear(env))
+ return list;
+
+ for (int i = 0; i != length; ++i) {
+ jobject lref = env->GetObjectArrayElement(static_cast<jobjectArray>(objArray.object()), i);
+ if (exceptionCheckAndClear(env))
+ break;
+
+ list << AndroidNetworkInfo(lref);
+ env->DeleteLocalRef(lref);
+ }
+
+ return list;
+}
+
+bool AndroidConnectivityManager::getBackgroundDataSetting() const
+{
+ return m_connectivityManager.callMethod<jboolean>("getBackgroundDataSetting");
+}
+
+AndroidNetworkInfo AndroidConnectivityManager::getNetworkInfo(int networkType) const
+{
+ QJNIObjectPrivate networkInfo = m_connectivityManager.callObjectMethod("getNetworkInfo",
+ "(I)Landroid/net/NetworkInfo;",
+ networkType);
+ return networkInfo;
+}
+
+int AndroidConnectivityManager::getNetworkPreference() const
+{
+ return m_connectivityManager.callMethod<jint>("getNetworkPreference");
+}
+
+bool AndroidConnectivityManager::isActiveNetworkMetered() const
+{
+ // This function was added in JB
+ if (QtAndroidPrivate::androidSdkVersion() < 16)
+ return false;
+
+ return m_connectivityManager.callMethod<jboolean>("isActiveNetworkMetered");
+}
+
+bool AndroidConnectivityManager::isNetworkTypeValid(int networkType)
+{
+ return QJNIObjectPrivate::callStaticMethod<jboolean>("android/net/ConnectivityManager",
+ "isNetworkTypeValid",
+ "(I)Z",
+ networkType);
+}
+
+bool AndroidConnectivityManager::requestRouteToHost(int networkType, int hostAddress)
+{
+ return m_connectivityManager.callMethod<jboolean>("requestRouteToHost", "(II)Z", networkType, hostAddress);
+}
+
+void AndroidConnectivityManager::setNetworkPreference(int preference)
+{
+ m_connectivityManager.callMethod<void>("setNetworkPreference", "(I)V", preference);
+}
+
+int AndroidConnectivityManager::startUsingNetworkFeature(int networkType, const QString &feature)
+{
+ QJNIObjectPrivate jfeature = QJNIObjectPrivate::fromString(feature);
+ return m_connectivityManager.callMethod<jint>("startUsingNetworkFeature",
+ "(ILjava/lang/String;)I",
+ networkType,
+ jfeature.object());
+}
+
+int AndroidConnectivityManager::stopUsingNetworkFeature(int networkType, const QString &feature)
+{
+ QJNIObjectPrivate jfeature = QJNIObjectPrivate::fromString(feature);
+ return m_connectivityManager.callMethod<jint>("stopUsingNetworkFeature",
+ "(ILjava/lang/String;)I",
+ networkType,
+ jfeature.object());
+}
+
+static void activeNetworkInfoChanged()
+{
+ Q_EMIT androidConnManagerInstance->connManager->activeNetworkChanged();
+}
+
+bool AndroidConnectivityManager::registerNatives(JNIEnv *env)
+{
+ QJNIObjectPrivate networkReceiver(networkReceiverClass);
+ if (!networkReceiver.isValid())
+ return false;
+
+ jclass clazz = env->GetObjectClass(networkReceiver.object());
+ static JNINativeMethod method = {"activeNetworkInfoChanged", "()V", reinterpret_cast<void *>(activeNetworkInfoChanged)};
+ const bool ret = (env->RegisterNatives(clazz, &method, 1) == JNI_OK);
+ env->DeleteLocalRef(clazz);
+ return ret;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/android/src/wrappers/androidconnectivitymanager.h b/src/plugins/bearer/android/src/wrappers/androidconnectivitymanager.h
new file mode 100644
index 0000000000..de7e5151fa
--- /dev/null
+++ b/src/plugins/bearer/android/src/wrappers/androidconnectivitymanager.h
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ANDROIDCONNECTIVITYMANAGER_H
+#define ANDROIDCONNECTIVITYMANAGER_H
+
+#include <QObject>
+#include <QtCore/private/qjni_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class AndroidTrafficStats
+{
+public:
+ static qint64 getMobileTxBytes();
+ static qint64 getMobileRxBytes();
+ static qint64 getTotalTxBytes();
+ static qint64 getTotalRxBytes();
+ static bool isTrafficStatsSupported();
+};
+
+class AndroidNetworkInfo
+{
+public:
+ // Needs to be in sync with the values from the android api.
+ enum NetworkState {
+ UnknownState,
+ Authenticating,
+ Blocked,
+ CaptivePortalCheck,
+ Connected,
+ Connecting,
+ Disconnected,
+ Disconnecting,
+ Failed,
+ Idle,
+ ObtainingIpAddr,
+ Scanning,
+ Suspended,
+ VerifyingPoorLink
+ };
+
+ enum NetworkType {
+ Mobile,
+ Wifi,
+ MobileMms,
+ MobileSupl,
+ MobileDun,
+ MobileHipri,
+ Wimax,
+ Bluetooth,
+ Dummy,
+ Ethernet,
+ UnknownType
+ };
+
+ enum NetworkSubType {
+ UnknownSubType,
+ Gprs,
+ Edge,
+ Umts,
+ Cdma,
+ Evdo0,
+ EvdoA,
+ Cdma1xRTT,
+ Hsdpa,
+ Hsupa,
+ Hspa,
+ Iden,
+ EvdoB,
+ Lte,
+ Ehrpd,
+ Hspap
+ };
+
+ inline AndroidNetworkInfo(const QJNIObjectPrivate &obj) : m_networkInfo(obj)
+ { }
+
+ NetworkState getDetailedState() const;
+ QString getExtraInfo() const;
+ QString getReason() const;
+ NetworkState getState() const;
+ NetworkSubType getSubtype() const;
+ QString getSubtypeName() const;
+ NetworkType getType() const;
+ QString getTypeName() const;
+ bool isAvailable() const;
+ bool isConnected() const;
+ bool isConnectedOrConnecting() const;
+ bool isFailover() const;
+ bool isRoaming() const;
+ bool isValid() const;
+
+private:
+ QJNIObjectPrivate m_networkInfo;
+};
+
+class AndroidConnectivityManager : public QObject
+{
+ Q_OBJECT
+public:
+ static AndroidConnectivityManager *getInstance();
+ ~AndroidConnectivityManager();
+
+ AndroidNetworkInfo getActiveNetworkInfo() const;
+ QList<AndroidNetworkInfo> getAllNetworkInfo() const;
+ bool getBackgroundDataSetting() const;
+ AndroidNetworkInfo getNetworkInfo(int networkType) const;
+ int getNetworkPreference() const;
+ bool isActiveNetworkMetered() const;
+ static bool isNetworkTypeValid(int networkType);
+ bool requestRouteToHost(int networkType, int hostAddress);
+ void setNetworkPreference(int preference);
+ int startUsingNetworkFeature(int networkType, const QString &feature);
+ int stopUsingNetworkFeature(int networkType, const QString &feature);
+ inline bool isValid() const
+ {
+ return m_connectivityManager.isValid();
+ }
+
+ Q_SIGNAL void activeNetworkChanged();
+
+private:
+ friend struct AndroidConnectivityManagerInstance;
+ AndroidConnectivityManager();
+ bool registerNatives(JNIEnv *env);
+ QJNIObjectPrivate m_connectivityManager;
+};
+
+QT_END_NAMESPACE
+
+#endif // ANDROIDCONNECTIVITYMANAGER_H
diff --git a/src/plugins/bearer/android/src/wrappers/wrappers.pri b/src/plugins/bearer/android/src/wrappers/wrappers.pri
new file mode 100644
index 0000000000..209b76e533
--- /dev/null
+++ b/src/plugins/bearer/android/src/wrappers/wrappers.pri
@@ -0,0 +1,6 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/androidconnectivitymanager.h
+SOURCES += \
+ $$PWD/androidconnectivitymanager.cpp
diff --git a/src/plugins/bearer/bearer.pro b/src/plugins/bearer/bearer.pro
index 42f039b19b..e52df24857 100644
--- a/src/plugins/bearer/bearer.pro
+++ b/src/plugins/bearer/bearer.pro
@@ -11,5 +11,6 @@ blackberry:SUBDIRS += blackberry
win32:!wince*:SUBDIRS += nativewifi
mac:contains(QT_CONFIG, corewlan):SUBDIRS += corewlan
mac:SUBDIRS += generic
+android:!android-no-sdk:SUBDIRS += android
isEmpty(SUBDIRS):SUBDIRS = generic
diff --git a/src/plugins/bearer/connman/qconnmanengine.cpp b/src/plugins/bearer/connman/qconnmanengine.cpp
index 797c30c7c6..adefb7504e 100644
--- a/src/plugins/bearer/connman/qconnmanengine.cpp
+++ b/src/plugins/bearer/connman/qconnmanengine.cpp
@@ -186,10 +186,23 @@ void QConnmanEngine::connectToId(const QString &id)
QConnmanServiceInterface *serv = connmanServiceInterfaces.value(id);
- if (!serv->isValid()) {
+ if (!serv || !serv->isValid()) {
emit connectionError(id, QBearerEngineImpl::InterfaceLookupError);
} else {
- serv->connect();
+ if (serv->type() == QLatin1String("cellular")) {
+ if (serv->roaming()) {
+ if (!isRoamingAllowed(serv->path())) {
+ emit connectionError(id, QBearerEngineImpl::OperationNotSupported);
+ return;
+ }
+ if (isAlwaysAskRoaming()) {
+ emit connectionError(id, QBearerEngineImpl::OperationNotSupported);
+ return;
+ }
+ }
+ }
+ if (serv->autoConnect())
+ serv->connect();
}
}
@@ -198,7 +211,7 @@ void QConnmanEngine::disconnectFromId(const QString &id)
QMutexLocker locker(&mutex);
QConnmanServiceInterface *serv = connmanServiceInterfaces.value(id);
- if (!serv->isValid()) {
+ if (!serv || !serv->isValid()) {
emit connectionError(id, DisconnectionError);
} else {
serv->disconnect();
@@ -250,6 +263,8 @@ QNetworkSession::State QConnmanEngine::sessionStateForId(const QString &id)
QString service = id;
QConnmanServiceInterface *serv = connmanServiceInterfaces.value(service);
+ if (!serv)
+ return QNetworkSession::Invalid;
QString servState = serv->state();
@@ -355,6 +370,8 @@ void QConnmanEngine::serviceStateChanged(const QString &state)
void QConnmanEngine::configurationChange(QConnmanServiceInterface *serv)
{
+ if (!serv)
+ return;
QMutexLocker locker(&mutex);
QString id = serv->path();
@@ -396,8 +413,10 @@ QNetworkConfiguration::StateFlags QConnmanEngine::getStateForService(const QStri
{
QMutexLocker locker(&mutex);
QConnmanServiceInterface *serv = connmanServiceInterfaces.value(service);
- QString state = serv->state();
+ if (!serv)
+ return QNetworkConfiguration::Undefined;
+ QString state = serv->state();
QNetworkConfiguration::StateFlags flag = QNetworkConfiguration::Defined;
if (serv->type() == QLatin1String("cellular")) {
@@ -494,7 +513,7 @@ void QConnmanEngine::addServiceConfiguration(const QString &servicePath)
{
QMutexLocker locker(&mutex);
if (!connmanServiceInterfaces.contains(servicePath)) {
- QConnmanServiceInterface *serv = new QConnmanServiceInterface(servicePath);
+ QConnmanServiceInterface *serv = new QConnmanServiceInterface(servicePath, this);
connmanServiceInterfaces.insert(serv->path(),serv);
}
diff --git a/src/plugins/imageformats/ico/ico.json b/src/plugins/imageformats/ico/ico.json
index bd46e07e54..14093ee471 100644
--- a/src/plugins/imageformats/ico/ico.json
+++ b/src/plugins/imageformats/ico/ico.json
@@ -1,4 +1,4 @@
{
- "Keys": [ "ico" ],
+ "Keys": [ "ico", "cur" ],
"MimeTypes": [ "image/vnd.microsoft.icon" ]
}
diff --git a/src/plugins/imageformats/ico/main.cpp b/src/plugins/imageformats/ico/main.cpp
index 05e6e1885c..2ff2f36fdc 100644
--- a/src/plugins/imageformats/ico/main.cpp
+++ b/src/plugins/imageformats/ico/main.cpp
@@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE
QImageIOPlugin::Capabilities QICOPlugin::capabilities(QIODevice *device, const QByteArray &format) const
{
- if (format == "ico")
+ if (format == "ico" || format == "cur")
return Capabilities(CanRead | CanWrite);
if (!format.isEmpty())
return 0;
diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp
index 505d6cc42b..f013692809 100644
--- a/src/plugins/imageformats/ico/qicohandler.cpp
+++ b/src/plugins/imageformats/ico/qicohandler.cpp
@@ -75,7 +75,7 @@ typedef struct
typedef struct
{
quint16 idReserved; // Reserved
- quint16 idType; // resource type (1 for icons)
+ quint16 idType; // resource type (1 for icons, 2 for cursors)
quint16 idCount; // how many images?
ICONDIRENTRY idEntries[1]; // the entries for each image
} ICONDIR, *LPICONDIR;
@@ -275,10 +275,10 @@ bool ICOReader::canRead(QIODevice *iodev)
readBytes += ICONDIRENTRY_SIZE;
// ICO format does not have a magic identifier, so we read 6 different values, which will hopefully be enough to identify the file.
if ( ikonDir.idReserved == 0
- && ikonDir.idType == 1
+ && (ikonDir.idType == 1 || ikonDir.idType == 2)
&& ikonDir.idEntries[0].bReserved == 0
- && ikonDir.idEntries[0].wPlanes <= 1
- && ikonDir.idEntries[0].wBitCount <= 32 // Bits per pixel
+ && (ikonDir.idEntries[0].wPlanes <= 1 || ikonDir.idType == 2)
+ && (ikonDir.idEntries[0].wBitCount <= 32 || ikonDir.idType == 2) // Bits per pixel
&& ikonDir.idEntries[0].dwBytesInRes >= 40 // Must be over 40, since sizeof (infoheader) == 40
) {
isProbablyICO = true;
@@ -339,7 +339,7 @@ bool ICOReader::readHeader()
if (iod && !headerRead) {
startpos = iod->pos();
if (readIconDir(iod, &iconDir)) {
- if (iconDir.idReserved == 0 || iconDir.idType == 1)
+ if (iconDir.idReserved == 0 && (iconDir.idType == 1 || iconDir.idType == 2))
headerRead = true;
}
}
diff --git a/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.InputContext.xml b/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.InputContext.xml
index dbc79c178b..9c67a38c57 100644
--- a/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.InputContext.xml
+++ b/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.InputContext.xml
@@ -35,6 +35,11 @@
<method name="GetEngine">
<arg name="desc" direction="out" type="v"/>
</method>
+ <method name="SetSurroundingText">
+ <arg name="text" direction="in" type="v"/>
+ <arg name="cursor_pos" direction="in" type="u"/>
+ <arg name="anchor_pos" direction="in" type="u"/>
+ </method>
<method name="Destroy"/>
<signal name="CommitText">
<arg name="text" type="v"/>
@@ -75,6 +80,11 @@
<signal name="UpdateProperty">
<arg name="prop" type="v"/>
</signal>
+ <signal name="RequireSurroundingText"/>
+ <signal name="DeleteSurroundingText">
+ <arg name="offset" type="i"/>
+ <arg name="n_chars" type="u"/>
+ </signal>
</interface>
</node>
diff --git a/src/plugins/platforminputcontexts/ibus/main.cpp b/src/plugins/platforminputcontexts/ibus/main.cpp
index d7c34ee9b3..e33c328b9e 100644
--- a/src/plugins/platforminputcontexts/ibus/main.cpp
+++ b/src/plugins/platforminputcontexts/ibus/main.cpp
@@ -41,7 +41,9 @@
#include <qpa/qplatforminputcontextplugin_p.h>
#include <QtCore/QStringList>
+#include <QDBusMetaType>
#include "qibusplatforminputcontext.h"
+#include "qibustypes.h"
QT_BEGIN_NAMESPACE
@@ -58,8 +60,13 @@ QIBusPlatformInputContext *QIbusPlatformInputContextPlugin::create(const QString
{
Q_UNUSED(paramList);
- if (system.compare(system, QStringLiteral("ibus"), Qt::CaseInsensitive) == 0)
+ if (system.compare(system, QStringLiteral("ibus"), Qt::CaseInsensitive) == 0) {
+ qDBusRegisterMetaType<QIBusSerializable>();
+ qDBusRegisterMetaType<QIBusAttribute>();
+ qDBusRegisterMetaType<QIBusAttributeList>();
+ qDBusRegisterMetaType<QIBusText>();
return new QIBusPlatformInputContext;
+ }
return 0;
}
diff --git a/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.cpp b/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.cpp
index 8df88b339b..454a1e6fda 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.cpp
+++ b/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.cpp
@@ -1,5 +1,5 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
+ * This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p qibusinputcontextproxy -c QIBusInputContextProxy interfaces/org.freedesktop.IBus.InputContext.xml
*
* qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
diff --git a/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.h b/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.h
index b1e33a3ecd..b75a5e0a93 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.h
+++ b/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.h
@@ -1,5 +1,5 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
+ * This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p qibusinputcontextproxy -c QIBusInputContextProxy interfaces/org.freedesktop.IBus.InputContext.xml
*
* qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
@@ -8,8 +8,8 @@
* Do not edit! All changes made to it will be lost.
*/
-#ifndef QIBUSINPUTCONTEXTPROXY_H_1308831153
-#define QIBUSINPUTCONTEXTPROXY_H_1308831153
+#ifndef QIBUSINPUTCONTEXTPROXY_H_1394889529
+#define QIBUSINPUTCONTEXTPROXY_H_1394889529
#include <QtCore/QObject>
#include <QtCore/QByteArray>
@@ -119,10 +119,18 @@ public Q_SLOTS: // METHODS
return asyncCallWithArgumentList(QLatin1String("SetEngine"), argumentList);
}
+ inline QDBusPendingReply<> SetSurroundingText(const QDBusVariant &text, uint cursor_pos, uint anchor_pos)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(text) << QVariant::fromValue(cursor_pos) << QVariant::fromValue(anchor_pos);
+ return asyncCallWithArgumentList(QLatin1String("SetSurroundingText"), argumentList);
+ }
+
Q_SIGNALS: // SIGNALS
void CommitText(const QDBusVariant &text);
void CursorDownLookupTable();
void CursorUpLookupTable();
+ void DeleteSurroundingText(int offset, uint n_chars);
void Disabled();
void Enabled();
void ForwardKeyEvent(uint keyval, uint keycode, uint state);
@@ -132,6 +140,7 @@ Q_SIGNALS: // SIGNALS
void PageDownLookupTable();
void PageUpLookupTable();
void RegisterProperties(const QDBusVariant &props);
+ void RequireSurroundingText();
void ShowAuxiliaryText();
void ShowLookupTable();
void ShowPreeditText();
diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
index 53e9b171d5..be90bbecb0 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
+++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
@@ -43,6 +43,7 @@
#include <QtDebug>
#include <QTextCharFormat>
#include <QGuiApplication>
+#include <QDBusVariant>
#include <qwindow.h>
#include <qevent.h>
@@ -78,6 +79,7 @@ public:
bool valid;
QString predit;
+ bool needsSurroundingText;
};
@@ -87,6 +89,8 @@ QIBusPlatformInputContext::QIBusPlatformInputContext ()
if (d->context) {
connect(d->context, SIGNAL(CommitText(QDBusVariant)), SLOT(commitText(QDBusVariant)));
connect(d->context, SIGNAL(UpdatePreeditText(QDBusVariant,uint,bool)), this, SLOT(updatePreeditText(QDBusVariant,uint,bool)));
+ connect(d->context, SIGNAL(DeleteSurroundingText(int,uint)), this, SLOT(deleteSurroundingText(int,uint)));
+ connect(d->context, SIGNAL(RequireSurroundingText()), this, SLOT(surroundingTextRequired()));
}
QInputMethod *p = qApp->inputMethod();
connect(p, SIGNAL(cursorRectangleChanged()), this, SLOT(cursorRectChanged()));
@@ -146,6 +150,33 @@ void QIBusPlatformInputContext::commit()
void QIBusPlatformInputContext::update(Qt::InputMethodQueries q)
{
+ QObject *input = qApp->focusObject();
+
+ if (d->needsSurroundingText && input
+ && (q.testFlag(Qt::ImSurroundingText)
+ || q.testFlag(Qt::ImCursorPosition)
+ || q.testFlag(Qt::ImAnchorPosition))) {
+ QInputMethodQueryEvent srrndTextQuery(Qt::ImSurroundingText);
+ QInputMethodQueryEvent cursorPosQuery(Qt::ImCursorPosition);
+ QInputMethodQueryEvent anchorPosQuery(Qt::ImAnchorPosition);
+
+ QCoreApplication::sendEvent(input, &srrndTextQuery);
+ QCoreApplication::sendEvent(input, &cursorPosQuery);
+ QCoreApplication::sendEvent(input, &anchorPosQuery);
+
+ QString surroundingText = srrndTextQuery.value(Qt::ImSurroundingText).toString();
+ uint cursorPosition = cursorPosQuery.value(Qt::ImCursorPosition).toUInt();
+ uint anchorPosition = anchorPosQuery.value(Qt::ImAnchorPosition).toUInt();
+
+ QIBusText text;
+ text.text = surroundingText;
+
+ QVariant variant;
+ variant.setValue(text);
+ QDBusVariant dbusText(variant);
+
+ d->context->SetSurroundingText(dbusText, cursorPosition, anchorPosition);
+ }
QPlatformInputContext::update(q);
}
@@ -191,7 +222,7 @@ void QIBusPlatformInputContext::commitText(const QDBusVariant &text)
QIBusText t;
if (debug)
qDebug() << arg.currentSignature();
- t.fromDBusArgument(arg);
+ arg >> t;
if (debug)
qDebug() << "commit text:" << t.text;
@@ -211,7 +242,7 @@ void QIBusPlatformInputContext::updatePreeditText(const QDBusVariant &text, uint
const QDBusArgument arg = text.variant().value<QDBusArgument>();
QIBusText t;
- t.fromDBusArgument(arg);
+ arg >> t;
if (debug)
qDebug() << "preedit text:" << t.text;
@@ -225,6 +256,27 @@ void QIBusPlatformInputContext::updatePreeditText(const QDBusVariant &text, uint
d->predit = t.text;
}
+void QIBusPlatformInputContext::surroundingTextRequired()
+{
+ if (debug)
+ qDebug() << "surroundingTextRequired";
+ d->needsSurroundingText = true;
+ update(Qt::ImSurroundingText);
+}
+
+void QIBusPlatformInputContext::deleteSurroundingText(int offset, uint n_chars)
+{
+ QObject *input = qApp->focusObject();
+ if (!input)
+ return;
+
+ if (debug)
+ qDebug() << "deleteSurroundingText" << offset << n_chars;
+
+ QInputMethodEvent event;
+ event.setCommitString("", offset, n_chars);
+ QCoreApplication::sendEvent(input, &event);
+}
bool
QIBusPlatformInputContext::x11FilterEvent(uint keyval, uint keycode, uint state, bool press)
@@ -250,7 +302,8 @@ QIBusPlatformInputContextPrivate::QIBusPlatformInputContextPrivate()
: connection(createConnection()),
bus(0),
context(0),
- valid(false)
+ valid(false),
+ needsSurroundingText(false)
{
if (!connection || !connection->isConnected())
return;
@@ -284,7 +337,7 @@ QIBusPlatformInputContextPrivate::QIBusPlatformInputContextPrivate()
IBUS_CAP_PROPERTY = 1 << 4,
IBUS_CAP_SURROUNDING_TEXT = 1 << 5
};
- context->SetCapabilities(IBUS_CAP_PREEDIT_TEXT|IBUS_CAP_FOCUS);
+ context->SetCapabilities(IBUS_CAP_PREEDIT_TEXT|IBUS_CAP_FOCUS|IBUS_CAP_SURROUNDING_TEXT);
if (debug)
qDebug(">>>> valid!");
diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
index 400ef3914a..a9e9ac18f9 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
+++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
@@ -69,6 +69,8 @@ public Q_SLOTS:
void commitText(const QDBusVariant &text);
void updatePreeditText(const QDBusVariant &text, uint cursor_pos, bool visible);
void cursorRectChanged();
+ void deleteSurroundingText(int offset, uint n_chars);
+ void surroundingTextRequired();
private:
QIBusPlatformInputContextPrivate *d;
diff --git a/src/plugins/platforminputcontexts/ibus/qibustypes.cpp b/src/plugins/platforminputcontexts/ibus/qibustypes.cpp
index 6ab0b1ae3e..5fa0c9ef67 100644
--- a/src/plugins/platforminputcontexts/ibus/qibustypes.cpp
+++ b/src/plugins/platforminputcontexts/ibus/qibustypes.cpp
@@ -42,6 +42,7 @@
#include "qibustypes.h"
#include <qtextformat.h>
#include <QtDBus>
+#include <QHash>
QT_BEGIN_NAMESPACE
@@ -53,23 +54,45 @@ QIBusSerializable::~QIBusSerializable()
{
}
-void QIBusSerializable::fromDBusArgument(const QDBusArgument &arg)
+const QDBusArgument &operator>>(const QDBusArgument &argument, QIBusSerializable &object)
{
- arg >> name;
- arg.beginMap();
- while (!arg.atEnd()) {
- arg.beginMapEntry();
+ argument >> object.name;
+
+ argument.beginMap();
+ while (!argument.atEnd()) {
+ argument.beginMapEntry();
QString key;
QDBusVariant value;
- arg >> key;
- arg >> value;
- arg.endMapEntry();
- attachments[key] = value.variant().value<QDBusArgument>();
+ argument >> key;
+ argument >> value;
+ argument.endMapEntry();
+ object.attachments[key] = value.variant().value<QDBusArgument>();
}
- arg.endMap();
+ argument.endMap();
+ return argument;
}
+QDBusArgument &operator<<(QDBusArgument &argument, const QIBusSerializable &object)
+{
+ argument << object.name;
+
+ argument.beginMap(qMetaTypeId<QString>(), qMetaTypeId<QDBusVariant>());
+
+ QHashIterator<QString, QDBusArgument> i(object.attachments);
+ while (i.hasNext()) {
+ i.next();
+ argument.beginMapEntry();
+ argument << i.key();
+
+ QDBusVariant variant(i.value().asVariant());
+
+ argument << variant;
+ argument.endMapEntry();
+ }
+ argument.endMap();
+ return argument;
+}
QIBusAttribute::QIBusAttribute()
: type(Invalid),
@@ -77,28 +100,46 @@ QIBusAttribute::QIBusAttribute()
start(0),
end(0)
{
+ name = "IBusAttribute";
}
QIBusAttribute::~QIBusAttribute()
{
+}
+
+QDBusArgument &operator<<(QDBusArgument &argument, const QIBusAttribute &attribute)
+{
+ argument.beginStructure();
+
+ argument << static_cast<const QIBusSerializable &>(attribute);
+
+ quint32 t = (quint32) attribute.type;
+ argument << t;
+ argument << attribute.value;
+ argument << attribute.start;
+ argument << attribute.end;
+ argument.endStructure();
+
+ return argument;
}
-void QIBusAttribute::fromDBusArgument(const QDBusArgument &arg)
+const QDBusArgument &operator>>(const QDBusArgument &argument, QIBusAttribute &attribute)
{
-// qDebug() << "QIBusAttribute::fromDBusArgument()" << arg.currentSignature();
- arg.beginStructure();
+ argument.beginStructure();
- QIBusSerializable::fromDBusArgument(arg);
+ argument >> static_cast<QIBusSerializable &>(attribute);
quint32 t;
- arg >> t;
- type = (Type)t;
- arg >> value;
- arg >> start;
- arg >> end;
+ argument >> t;
+ attribute.type = (QIBusAttribute::Type) t;
+ argument >> attribute.value;
+ argument >> attribute.start;
+ argument >> attribute.end;
- arg.endStructure();
+ argument.endStructure();
+
+ return argument;
}
QTextFormat QIBusAttribute::format() const
@@ -141,36 +182,53 @@ QTextFormat QIBusAttribute::format() const
return fmt;
}
-
QIBusAttributeList::QIBusAttributeList()
{
-
+ name = "IBusAttrList";
}
QIBusAttributeList::~QIBusAttributeList()
{
+}
+
+QDBusArgument &operator<<(QDBusArgument &argument, const QIBusAttributeList &attrList)
+{
+ argument.beginStructure();
+ argument << static_cast<const QIBusSerializable &>(attrList);
+
+ argument.beginArray(qMetaTypeId<QDBusVariant>());
+ for (int i = 0; i < attrList.attributes.size(); ++i) {
+ QVariant variant;
+ variant.setValue(attrList.attributes.at(i));
+ argument << QDBusVariant (variant);
+ }
+ argument.endArray();
+
+ argument.endStructure();
+ return argument;
}
-void QIBusAttributeList::fromDBusArgument(const QDBusArgument &arg)
+const QDBusArgument &operator>>(const QDBusArgument &arg, QIBusAttributeList &attrList)
{
// qDebug() << "QIBusAttributeList::fromDBusArgument()" << arg.currentSignature();
arg.beginStructure();
- QIBusSerializable::fromDBusArgument(arg);
+ arg >> static_cast<QIBusSerializable &>(attrList);
arg.beginArray();
- while(!arg.atEnd()) {
+ while (!arg.atEnd()) {
QDBusVariant var;
arg >> var;
QIBusAttribute attr;
- attr.fromDBusArgument(var.variant().value<QDBusArgument>());
- attributes.append(attr);
+ var.variant().value<QDBusArgument>() >> attr;
+ attrList.attributes.append(attr);
}
arg.endArray();
arg.endStructure();
+ return arg;
}
QList<QInputMethodEvent::Attribute> QIBusAttributeList::imAttributes() const
@@ -183,30 +241,40 @@ QList<QInputMethodEvent::Attribute> QIBusAttributeList::imAttributes() const
return imAttrs;
}
-
QIBusText::QIBusText()
{
-
+ name = "IBusText";
}
QIBusText::~QIBusText()
{
+}
+
+QDBusArgument &operator<<(QDBusArgument &argument, const QIBusText &text)
+{
+ argument.beginStructure();
+
+ argument << static_cast<const QIBusSerializable &>(text);
+ argument << text.text << text.attributes;
+ argument.endStructure();
+ return argument;
}
-void QIBusText::fromDBusArgument(const QDBusArgument &arg)
+const QDBusArgument &operator>>(const QDBusArgument &argument, QIBusText &text)
{
// qDebug() << "QIBusText::fromDBusArgument()" << arg.currentSignature();
- arg.beginStructure();
+ argument.beginStructure();
- QIBusSerializable::fromDBusArgument(arg);
+ argument >> static_cast<QIBusSerializable &>(text);
- arg >> text;
+ argument >> text.text;
QDBusVariant variant;
- arg >> variant;
- attributes.fromDBusArgument(variant.variant().value<QDBusArgument>());
+ argument >> variant;
+ variant.variant().value<QDBusArgument>() >> text.attributes;
- arg.endStructure();
+ argument.endStructure();
+ return argument;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforminputcontexts/ibus/qibustypes.h b/src/plugins/platforminputcontexts/ibus/qibustypes.h
index 8e6f853a52..0275c5eed2 100644
--- a/src/plugins/platforminputcontexts/ibus/qibustypes.h
+++ b/src/plugins/platforminputcontexts/ibus/qibustypes.h
@@ -43,19 +43,16 @@
#include <qvector.h>
#include <qevent.h>
+#include <QDBusArgument>
QT_BEGIN_NAMESPACE
-class QDBusArgument;
-
class QIBusSerializable
{
public:
QIBusSerializable();
virtual ~QIBusSerializable();
- virtual void fromDBusArgument(const QDBusArgument &arg);
-
QString name;
QHash<QString, QDBusArgument> attachments;
};
@@ -81,7 +78,6 @@ public:
QIBusAttribute();
~QIBusAttribute();
- void fromDBusArgument(const QDBusArgument &arg);
QTextFormat format() const;
Type type;
@@ -96,8 +92,6 @@ public:
QIBusAttributeList();
~QIBusAttributeList();
- void fromDBusArgument(const QDBusArgument &arg);
-
QList<QInputMethodEvent::Attribute> imAttributes() const;
QVector<QIBusAttribute> attributes;
@@ -109,12 +103,27 @@ public:
QIBusText();
~QIBusText();
- void fromDBusArgument(const QDBusArgument &arg);
-
QString text;
QIBusAttributeList attributes;
};
+QDBusArgument &operator<<(QDBusArgument &argument, const QIBusSerializable &object);
+const QDBusArgument &operator>>(const QDBusArgument &argument, QIBusSerializable &object);
+
+QDBusArgument &operator<<(QDBusArgument &argument, const QIBusAttribute &attribute);
+const QDBusArgument &operator>>(const QDBusArgument &argument, QIBusAttribute &attribute);
+
+QDBusArgument &operator<<(QDBusArgument &argument, const QIBusAttributeList &attributeList);
+const QDBusArgument &operator>>(const QDBusArgument &arg, QIBusAttributeList &attrList);
+
+QDBusArgument &operator<<(QDBusArgument &argument, const QIBusText &text);
+const QDBusArgument &operator>>(const QDBusArgument &argument, QIBusText &text);
+
QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QIBusSerializable)
+Q_DECLARE_METATYPE(QIBusAttribute)
+Q_DECLARE_METATYPE(QIBusAttributeList)
+Q_DECLARE_METATYPE(QIBusText)
+
#endif
diff --git a/src/plugins/platforms/android/android.pro b/src/plugins/platforms/android/android.pro
index 243eea071a..32c37ab17a 100644
--- a/src/plugins/platforms/android/android.pro
+++ b/src/plugins/platforms/android/android.pro
@@ -21,7 +21,9 @@ CONFIG += qpa/genericunixfontdatabase
OTHER_FILES += $$PWD/android.json
-INCLUDEPATH += $$PWD
+INCLUDEPATH += \
+ $$PWD \
+ $$QT_SOURCE_TREE/src/3rdparty/android
SOURCES += $$PWD/androidplatformplugin.cpp \
$$PWD/androidjnimain.cpp \
@@ -48,7 +50,8 @@ SOURCES += $$PWD/androidplatformplugin.cpp \
$$PWD/qandroidplatformrasterwindow.cpp \
$$PWD/qandroidplatformbackingstore.cpp \
$$PWD/qandroidplatformopenglcontext.cpp \
- $$PWD/qandroidplatformforeignwindow.cpp
+ $$PWD/qandroidplatformforeignwindow.cpp \
+ $$PWD/extract.cpp
HEADERS += $$PWD/qandroidplatformintegration.h \
$$PWD/androidjnimain.h \
diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp
index 3f58597c9b..a7fec8748b 100644
--- a/src/plugins/platforms/android/androidjniaccessibility.cpp
+++ b/src/plugins/platforms/android/androidjniaccessibility.cpp
@@ -43,10 +43,12 @@
#include "androidjnimain.h"
#include "qandroidplatformintegration.h"
#include "qpa/qplatformaccessibility.h"
+#include <QtPlatformSupport/private/qaccessiblebridgeutils_p.h>
#include "qguiapplication.h"
#include "qwindow.h"
#include "qrect.h"
#include "QtGui/qaccessible.h"
+#include <QtCore/qmath.h>
#include <QtCore/private/qjnihelpers_p.h>
#include "qdebug.h"
@@ -67,6 +69,7 @@ namespace QtAndroidAccessibility
static jmethodID m_setEnabledMethodID = 0;
static jmethodID m_setFocusableMethodID = 0;
static jmethodID m_setFocusedMethodID = 0;
+ static jmethodID m_setScrollableMethodID = 0;
static jmethodID m_setTextSelectionMethodID = 0;
static jmethodID m_setVisibleToUserMethodID = 0;
@@ -169,6 +172,18 @@ namespace QtAndroidAccessibility
return false;
}
+ static jboolean scrollForward(JNIEnv */*env*/, jobject /*thiz*/, jint objectId)
+ {
+ QAccessibleInterface *iface = interfaceFromId(objectId);
+ return QAccessibleBridgeUtils::performEffectiveAction(iface, QAccessibleActionInterface::increaseAction());
+ }
+
+ static jboolean scrollBackward(JNIEnv */*env*/, jobject /*thiz*/, jint objectId)
+ {
+ QAccessibleInterface *iface = interfaceFromId(objectId);
+ return QAccessibleBridgeUtils::performEffectiveAction(iface, QAccessibleActionInterface::decreaseAction());
+ }
+
#define FIND_AND_CHECK_CLASS(CLASS_NAME) \
clazz = env->FindClass(CLASS_NAME); \
@@ -202,6 +217,11 @@ if (!clazz) { \
return false;
}
QAccessible::State state = iface->state();
+ const QStringList actions = QAccessibleBridgeUtils::effectiveActionNames(iface);
+ const bool hasClickableAction = actions.contains(QAccessibleActionInterface::pressAction())
+ || actions.contains(QAccessibleActionInterface::toggleAction());
+ const bool hasIncreaseAction = actions.contains(QAccessibleActionInterface::increaseAction());
+ const bool hasDecreaseAction = actions.contains(QAccessibleActionInterface::decreaseAction());
// try to fill in the text property, this is what the screen reader reads
QString desc = iface->text(QAccessible::Value);
@@ -219,21 +239,26 @@ if (!clazz) { \
}
env->CallVoidMethod(node, m_setEnabledMethodID, !state.disabled);
+ env->CallVoidMethod(node, m_setCheckableMethodID, (bool)state.checkable);
env->CallVoidMethod(node, m_setCheckedMethodID, (bool)state.checked);
env->CallVoidMethod(node, m_setFocusableMethodID, (bool)state.focusable);
env->CallVoidMethod(node, m_setFocusedMethodID, (bool)state.focused);
- env->CallVoidMethod(node, m_setCheckableMethodID, (bool)state.checkable);
env->CallVoidMethod(node, m_setVisibleToUserMethodID, !state.invisible);
+ env->CallVoidMethod(node, m_setScrollableMethodID, hasIncreaseAction || hasDecreaseAction);
+ env->CallVoidMethod(node, m_setClickableMethodID, hasClickableAction);
+
+ // Add ACTION_CLICK
+ if (hasClickableAction)
+ env->CallVoidMethod(node, m_addActionMethodID, (int)16); // ACTION_CLICK defined in AccessibilityNodeInfo
+
+ // Add ACTION_SCROLL_FORWARD
+ if (hasIncreaseAction)
+ env->CallVoidMethod(node, m_addActionMethodID, (int)4096); // ACTION_SCROLL_FORWARD defined in AccessibilityNodeInfo
+
+ // Add ACTION_SCROLL_BACKWARD
+ if (hasDecreaseAction)
+ env->CallVoidMethod(node, m_addActionMethodID, (int)8192); // ACTION_SCROLL_BACKWARD defined in AccessibilityNodeInfo
- if (iface->actionInterface()) {
- QStringList actions = iface->actionInterface()->actionNames();
- bool clickable = actions.contains(QAccessibleActionInterface::pressAction());
- bool toggle = actions.contains(QAccessibleActionInterface::toggleAction());
- if (clickable || toggle) {
- env->CallVoidMethod(node, m_setClickableMethodID, (bool)clickable);
- env->CallVoidMethod(node, m_addActionMethodID, (int)16); // ACTION_CLICK defined in AccessibilityNodeInfo
- }
- }
jstring jdesc = env->NewString((jchar*) desc.constData(), (jsize) desc.size());
//CALL_METHOD(node, "setText", "(Ljava/lang/CharSequence;)V", jdesc)
@@ -251,6 +276,8 @@ if (!clazz) { \
{"hitTest", "(FF)I", (void*)hitTest},
{"populateNode", "(ILandroid/view/accessibility/AccessibilityNodeInfo;)Z", (void*)populateNode},
{"clickAction", "(I)Z", (void*)clickAction},
+ {"scrollForward", "(I)Z", (void*)scrollForward},
+ {"scrollBackward", "(I)Z", (void*)scrollBackward},
};
#define GET_AND_CHECK_STATIC_METHOD(VAR, CLASS, METHOD_NAME, METHOD_SIGNATURE) \
@@ -283,6 +310,7 @@ if (!clazz) { \
GET_AND_CHECK_STATIC_METHOD(m_setEnabledMethodID, nodeInfoClass, "setEnabled", "(Z)V");
GET_AND_CHECK_STATIC_METHOD(m_setFocusableMethodID, nodeInfoClass, "setFocusable", "(Z)V");
GET_AND_CHECK_STATIC_METHOD(m_setFocusedMethodID, nodeInfoClass, "setFocused", "(Z)V");
+ GET_AND_CHECK_STATIC_METHOD(m_setScrollableMethodID, nodeInfoClass, "setScrollable", "(Z)V");
GET_AND_CHECK_STATIC_METHOD(m_setVisibleToUserMethodID, nodeInfoClass, "setVisibleToUser", "(Z)V");
if (QtAndroidPrivate::androidSdkVersion() >= 18) {
diff --git a/src/plugins/platforms/android/extract.cpp b/src/plugins/platforms/android/extract.cpp
new file mode 100644
index 0000000000..82687e61a7
--- /dev/null
+++ b/src/plugins/platforms/android/extract.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+
+#include <jni.h>
+#include <android/log.h>
+#include <extract.h>
+#include <alloca.h>
+
+#define LOG_TAG "extractSyleInfo"
+#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
+#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__)
+
+extern "C" JNIEXPORT jintArray JNICALL Java_org_qtproject_qt5_android_ExtractStyle_extractNativeChunkInfo(JNIEnv * env, jobject, Res_png_9patch* chunk)
+{
+ Res_png_9patch::deserialize(chunk);
+ //printChunkInformation(chunk);
+ jintArray result;
+ size_t size = 3+chunk->numXDivs+chunk->numYDivs+chunk->numColors;
+ result = env->NewIntArray(size);
+ if (!result)
+ return 0;
+
+ jint *data = (jint*)malloc(sizeof(jint)*size);
+ size_t pos = 0;
+ data[pos++]=chunk->numXDivs;
+ data[pos++]=chunk->numYDivs;
+ data[pos++]=chunk->numColors;
+ for (int x = 0; x <chunk->numXDivs; x ++)
+ data[pos++]=chunk->xDivs[x];
+ for (int y = 0; y <chunk->numYDivs; y ++)
+ data[pos++]=chunk->yDivs[y];
+ for (int c = 0; c <chunk->numColors; c ++)
+ data[pos++]=chunk->colors[c];
+ env->SetIntArrayRegion(result, 0, size, data);
+ free(data);
+ return result;
+}
+
+extern "C" JNIEXPORT jintArray JNICALL Java_org_qtproject_qt5_android_ExtractStyle_extractChunkInfo(JNIEnv * env, jobject obj, jbyteArray chunkObj)
+{
+ size_t chunkSize = env->GetArrayLength(chunkObj);
+ void* storage = alloca(chunkSize);
+ env->GetByteArrayRegion(chunkObj, 0, chunkSize,
+ reinterpret_cast<jbyte*>(storage));
+
+ if (!env->ExceptionCheck())
+ return Java_org_qtproject_qt5_android_ExtractStyle_extractNativeChunkInfo(env, obj, static_cast<Res_png_9patch*>(storage));
+ else
+ env->ExceptionClear();
+ return 0;
+}
+
+// The following part was shamelessly stolen from ResourceTypes.cpp from Android's sources
+/*
+ * Copyright (C) 2005 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+static void deserializeInternal(const void* inData, Res_png_9patch* outData) {
+ char* patch = (char*) inData;
+ if (inData != outData) {
+ memmove(&outData->wasDeserialized, patch, 4); // copy wasDeserialized, numXDivs, numYDivs, numColors
+ memmove(&outData->paddingLeft, patch + 12, 4); // copy wasDeserialized, numXDivs, numYDivs, numColors
+ }
+ outData->wasDeserialized = true;
+ char* data = (char*)outData;
+ data += sizeof(Res_png_9patch);
+ outData->xDivs = (int32_t*) data;
+ data += outData->numXDivs * sizeof(int32_t);
+ outData->yDivs = (int32_t*) data;
+ data += outData->numYDivs * sizeof(int32_t);
+ outData->colors = (uint32_t*) data;
+}
+
+Res_png_9patch* Res_png_9patch::deserialize(const void* inData)
+{
+ if (sizeof(void*) != sizeof(int32_t)) {
+ LOGE("Cannot deserialize on non 32-bit system\n");
+ return NULL;
+ }
+ deserializeInternal(inData, (Res_png_9patch*) inData);
+ return (Res_png_9patch*) inData;
+}
diff --git a/src/plugins/platforms/android/qandroidplatformbackingstore.h b/src/plugins/platforms/android/qandroidplatformbackingstore.h
index 4c24e129c3..c51ebe879d 100644
--- a/src/plugins/platforms/android/qandroidplatformbackingstore.h
+++ b/src/plugins/platforms/android/qandroidplatformbackingstore.h
@@ -55,7 +55,7 @@ public:
virtual QPaintDevice *paintDevice();
virtual void flush(QWindow *window, const QRegion &region, const QPoint &offset);
virtual void resize(const QSize &size, const QRegion &staticContents);
- const QImage image() { return m_image; }
+ QImage toImage() const { return m_image; }
void setBackingStore(QWindow *window);
protected:
QImage m_image;
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp
index 714a670134..af184cde02 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.cpp
+++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp
@@ -332,7 +332,7 @@ void QAndroidPlatformScreen::doRedraw()
QRect windowRect = targetRect.translated(-window->geometry().topLeft());
QAndroidPlatformBackingStore *backingStore = static_cast<QAndroidPlatformRasterWindow *>(window)->backingStore();
if (backingStore)
- compositePainter.drawImage(targetRect.topLeft(), backingStore->image(), windowRect);
+ compositePainter.drawImage(targetRect.topLeft(), backingStore->toImage(), windowRect);
}
}
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro
index 1f9c0e051d..ad6cb3a1fc 100644
--- a/src/plugins/platforms/cocoa/cocoa.pro
+++ b/src/plugins/platforms/cocoa/cocoa.pro
@@ -14,7 +14,6 @@ OBJECTIVE_SOURCES += main.mm \
qnsviewaccessibility.mm \
qcocoaautoreleasepool.mm \
qnswindowdelegate.mm \
- qcocoaglcontext.mm \
qcocoanativeinterface.mm \
qcocoaeventdispatcher.mm \
qcocoaapplicationdelegate.mm \
@@ -51,7 +50,6 @@ HEADERS += qcocoaintegration.h \
qnsview.h \
qcocoaautoreleasepool.h \
qnswindowdelegate.h \
- qcocoaglcontext.h \
qcocoanativeinterface.h \
qcocoaeventdispatcher.h \
qcocoaapplicationdelegate.h \
@@ -80,6 +78,12 @@ HEADERS += qcocoaintegration.h \
messages.h \
qcocoamimetypes.h
+contains(QT_CONFIG, opengl.*) {
+ OBJECTIVE_SOURCES += qcocoaglcontext.mm
+
+ HEADERS += qcocoaglcontext.h
+}
+
RESOURCES += qcocoaresources.qrc
LIBS += -framework Cocoa -framework Carbon -framework IOKit -lcups
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
index 72045a1bbb..8f83b0fe30 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
@@ -55,7 +55,7 @@ QCocoaAccessibility::~QCocoaAccessibility()
void QCocoaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
{
- QCocoaAccessibleElement *element = [QCocoaAccessibleElement elementWithId: event->uniqueId()];
+ QMacAccessibilityElement *element = [QMacAccessibilityElement elementWithId: event->uniqueId()];
if (!element) {
qWarning() << "QCocoaAccessibility::notifyAccessibilityUpdate: invalid element";
return;
@@ -140,7 +140,7 @@ static void populateRoleMap()
roleMap[QAccessible::Row] = NSAccessibilityRowRole;
roleMap[QAccessible::RowHeader] = NSAccessibilityRowRole;
roleMap[QAccessible::Cell] = NSAccessibilityTextFieldRole;
- roleMap[QAccessible::PushButton] = NSAccessibilityButtonRole;
+ roleMap[QAccessible::Button] = NSAccessibilityButtonRole;
roleMap[QAccessible::EditableText] = NSAccessibilityTextFieldRole;
roleMap[QAccessible::Link] = NSAccessibilityLinkRole;
roleMap[QAccessible::Indicator] = NSAccessibilityValueIndicatorRole;
@@ -149,6 +149,9 @@ static void populateRoleMap()
roleMap[QAccessible::ListItem] = NSAccessibilityStaticTextRole;
roleMap[QAccessible::Cell] = NSAccessibilityStaticTextRole;
roleMap[QAccessible::Client] = NSAccessibilityGroupRole;
+ roleMap[QAccessible::Paragraph] = NSAccessibilityGroupRole;
+ roleMap[QAccessible::Section] = NSAccessibilityGroupRole;
+ roleMap[QAccessible::WebDocument] = NSAccessibilityGroupRole;
}
/*
@@ -244,7 +247,7 @@ NSArray *unignoredChildren(QAccessibleInterface *interface)
QAccessible::Id childId = QAccessible::uniqueId(child);
//qDebug() << " kid: " << childId << child;
- QCocoaAccessibleElement *element = [QCocoaAccessibleElement elementWithId: childId];
+ QMacAccessibilityElement *element = [QMacAccessibilityElement elementWithId: childId];
if (element)
[kids addObject: element];
else
@@ -343,7 +346,7 @@ id getValueAttribute(QAccessibleInterface *interface)
}
if (QAccessibleValueInterface *valueInterface = interface->valueInterface()) {
- return QCFString::toNSString(QString::number(valueInterface->currentValue().toDouble()));
+ return QCFString::toNSString(valueInterface->currentValue().toString());
}
if (interface->state().checkable) {
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
index 9760f492ea..4a5baefbc5 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
@@ -50,18 +50,18 @@
#import <qaccessible.h>
-@class QT_MANGLE_NAMESPACE(QCocoaAccessibleElement);
+@class QT_MANGLE_NAMESPACE(QMacAccessibilityElement);
-@interface QT_MANGLE_NAMESPACE(QCocoaAccessibleElement) : NSObject {
+@interface QT_MANGLE_NAMESPACE(QMacAccessibilityElement) : NSObject {
NSString *role;
QAccessible::Id axid;
}
- (id)initWithId:(QAccessible::Id)anId;
-+ (QT_MANGLE_NAMESPACE(QCocoaAccessibleElement) *)elementWithId:(QAccessible::Id)anId;
++ (QT_MANGLE_NAMESPACE(QMacAccessibilityElement) *)elementWithId:(QAccessible::Id)anId;
@end
-QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaAccessibleElement);
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAccessibilityElement);
#endif
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
index 078dc67cad..9f803e411d 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -43,12 +43,12 @@
#include "qcocoahelpers.h"
#include "qcocoawindow.h"
#include "private/qaccessiblecache_p.h"
-
+#include <QtPlatformSupport/private/qaccessiblebridgeutils_p.h>
#include <QtGui/qaccessible.h>
#import <AppKit/NSAccessibility.h>
-@implementation QCocoaAccessibleElement
+@implementation QMacAccessibilityElement
- (id)initWithId:(QAccessible::Id)anId
{
@@ -72,7 +72,7 @@
QAccessibleCache *cache = QAccessibleCache::instance();
- QCocoaAccessibleElement *element = cache->elementForId(anId);
+ QMacAccessibilityElement *element = cache->elementForId(anId);
if (!element) {
QAccessibleInterface *iface = QAccessible::accessibleInterface(anId);
Q_ASSERT(iface);
@@ -95,8 +95,8 @@
}
- (BOOL)isEqual:(id)object {
- if ([object isKindOfClass:[QCocoaAccessibleElement class]]) {
- QCocoaAccessibleElement *other = object;
+ if ([object isKindOfClass:[QMacAccessibilityElement class]]) {
+ QMacAccessibilityElement *other = object;
return other->axid == axid;
} else {
return NO;
@@ -196,7 +196,7 @@
}
QAccessible::Id parentId = QAccessible::uniqueId(parent);
- return [QCocoaAccessibleElement elementWithId: parentId];
+ return [QMacAccessibilityElement elementWithId: parentId];
}
@@ -345,7 +345,7 @@
}
if ([attribute isEqualToString: NSAccessibilityLineForIndexParameterizedAttribute]) {
int index = [parameter intValue];
- NSNumber *ln = [QCocoaAccessibleElement lineNumberForIndex: index forText: iface->text(QAccessible::Value)];
+ NSNumber *ln = [QMacAccessibilityElement lineNumberForIndex: index forText: iface->text(QAccessible::Value)];
return ln;
}
if ([attribute isEqualToString: NSAccessibilityRangeForLineParameterizedAttribute]) {
@@ -430,15 +430,11 @@
if (!iface)
return nsActions;
- QAccessibleActionInterface *actionInterface = iface->actionInterface();
- if (actionInterface) {
- QStringList supportedActionNames = actionInterface->actionNames();
-
- foreach (const QString &qtAction, supportedActionNames) {
- NSString *nsAction = QCocoaAccessible::getTranslatedAction(qtAction);
- if (nsAction)
- [nsActions addObject : nsAction];
- }
+ const QStringList &supportedActionNames = QAccessibleBridgeUtils::effectiveActionNames(iface);
+ foreach (const QString &qtAction, supportedActionNames) {
+ NSString *nsAction = QCocoaAccessible::getTranslatedAction(qtAction);
+ if (nsAction)
+ [nsActions addObject : nsAction];
}
return nsActions;
@@ -448,27 +444,25 @@
QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
if (!iface)
return nil; // FIXME is that the right return type??
- QAccessibleActionInterface *actionInterface = iface->actionInterface();
- if (actionInterface) {
- QString qtAction = QCocoaAccessible::translateAction(action);
-
- // Return a description from the action interface if this action is not known to the OS.
- if (qtAction.isEmpty()) {
- QString description = actionInterface->localizedActionDescription(qtAction);
- return QCFString::toNSString(description);
+ QString qtAction = QCocoaAccessible::translateAction(action);
+ QString description;
+ // Return a description from the action interface if this action is not known to the OS.
+ if (qtAction.isEmpty()) {
+ if (QAccessibleActionInterface *actionInterface = iface->actionInterface()) {
+ qtAction = QString::fromNSString((NSString *)action);
+ description = actionInterface->localizedActionDescription(qtAction);
}
+ } else {
+ description = qAccessibleLocalizedActionDescription(qtAction);
}
-
- return NSAccessibilityActionDescription(action);
+ return QCFString::toNSString(description);
}
- (void)accessibilityPerformAction:(NSString *)action {
QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
if (iface) {
- QAccessibleActionInterface *actionInterface = iface->actionInterface();
- if (actionInterface) {
- actionInterface->doAction(QCocoaAccessible::translateAction(action));
- }
+ const QString qtAction = QCocoaAccessible::translateAction(action);
+ QAccessibleBridgeUtils::performEffectiveAction(iface, qtAction);
}
}
@@ -504,7 +498,7 @@
QAccessible::Id childId = QAccessible::uniqueId(childInterface);
// hit a child, forward to child accessible interface.
- QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement elementWithId:childId];
+ QMacAccessibilityElement *accessibleElement = [QMacAccessibilityElement elementWithId:childId];
if (accessibleElement)
return NSAccessibilityUnignoredAncestor(accessibleElement);
return NSAccessibilityUnignoredAncestor(self);
@@ -521,7 +515,7 @@
QAccessibleInterface *childInterface = iface->focusChild();
if (childInterface) {
QAccessible::Id childAxid = QAccessible::uniqueId(childInterface);
- QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement elementWithId:childAxid];
+ QMacAccessibilityElement *accessibleElement = [QMacAccessibilityElement elementWithId:childAxid];
return NSAccessibilityUnignoredAncestor(accessibleElement);
}
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
index 92358ecc74..efe3269d42 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
+++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
@@ -340,6 +340,7 @@ static void cleanupCocoaApplicationDelegate()
&& [reflectionDelegate respondsToSelector:@selector(applicationDidBecomeActive:)])
[reflectionDelegate applicationDidBecomeActive:notification];
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive);
/*
onApplicationChangedActivation(true);
@@ -363,6 +364,7 @@ static void cleanupCocoaApplicationDelegate()
&& [reflectionDelegate respondsToSelector:@selector(applicationDidResignActive:)])
[reflectionDelegate applicationDidResignActive:notification];
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
/*
onApplicationChangedActivation(false);
@@ -374,6 +376,26 @@ static void cleanupCocoaApplicationDelegate()
*/
}
+- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag
+{
+ Q_UNUSED(theApplication);
+ Q_UNUSED(flag);
+ if (reflectionDelegate
+ && [reflectionDelegate respondsToSelector:@selector(applicationShouldHandleReopen:hasVisibleWindows:)])
+ return [reflectionDelegate applicationShouldHandleReopen:theApplication hasVisibleWindows:flag];
+
+ /*
+ true to force delivery of the event even if the application state is already active,
+ because rapp (handle reopen) events are sent each time the dock icon is clicked regardless
+ of the active state of the application or number of visible windows. For example, a browser
+ app that has no windows opened would need the event be to delivered even if it was already
+ active in order to create a new window as per OS X conventions.
+ */
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive, true /*forcePropagate*/);
+
+ return NO;
+}
+
- (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate
{
[oldDelegate retain];
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h
index a33373c4c1..8a4e2e68df 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.h
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h
@@ -59,7 +59,9 @@ public:
QPaintDevice *paintDevice();
void flush(QWindow *widget, const QRegion &region, const QPoint &offset);
+#ifndef QT_NO_OPENGL
QImage toImage() const Q_DECL_OVERRIDE;
+#endif
void resize (const QSize &size, const QRegion &);
bool scroll(const QRegion &area, int dx, int dy);
CGImageRef getBackingStoreCGImage();
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index d76645c668..e13e295511 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -96,10 +96,12 @@ void QCocoaBackingStore::flush(QWindow *win, const QRegion &region, const QPoint
}
}
+#ifndef QT_NO_OPENGL
QImage QCocoaBackingStore::toImage() const
{
return m_qImage;
}
+#endif
void QCocoaBackingStore::resize(const QSize &size, const QRegion &)
{
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h
index 30f1cdc278..2aa22ea759 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.h
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h
@@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE
class QCocoaGLContext : public QPlatformOpenGLContext
{
public:
- QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share);
+ QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, const QVariant &nativeHandle);
~QCocoaGLContext();
QSurfaceFormat format() const;
@@ -77,6 +77,8 @@ public:
void windowWasHidden();
+ QVariant nativeHandle() const;
+
private:
void setActiveWindow(QWindow *window);
void updateSurfaceFormat();
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
index 3f61bd81ee..7b70fbb4bb 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
@@ -46,6 +46,7 @@
#include <qdebug.h>
#include <QtCore/private/qcore_mac_p.h>
#include <QtPlatformSupport/private/cglconvenience_p.h>
+#include <QtPlatformHeaders/qcocoanativecontext.h>
#import <Cocoa/Cocoa.h>
@@ -117,11 +118,33 @@ static void updateFormatFromContext(QSurfaceFormat *format)
format->setProfile(QSurfaceFormat::CompatibilityProfile);
}
-QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share)
+QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share,
+ const QVariant &nativeHandle)
: m_context(nil),
m_shareContext(nil),
m_format(format)
{
+ if (!nativeHandle.isNull()) {
+ if (!nativeHandle.canConvert<QCocoaNativeContext>()) {
+ qWarning("QCocoaGLContext: Requires a QCocoaNativeContext");
+ return;
+ }
+ QCocoaNativeContext handle = nativeHandle.value<QCocoaNativeContext>();
+ NSOpenGLContext *context = handle.context();
+ if (!context) {
+ qWarning("QCocoaGLContext: No NSOpenGLContext given");
+ return;
+ }
+ m_context = context;
+ [m_context retain];
+ m_shareContext = share ? static_cast<QCocoaGLContext *>(share)->nsOpenGLContext() : nil;
+ // OpenGL surfaces can be ordered either above(default) or below the NSWindow.
+ const GLint order = qt_mac_resolveOption(1, "QT_MAC_OPENGL_SURFACE_ORDER");
+ [m_context setValues:&order forParameter:NSOpenGLCPSurfaceOrder];
+ updateSurfaceFormat();
+ return;
+ }
+
// we only support OpenGL contexts under Cocoa
if (m_format.renderableType() == QSurfaceFormat::DefaultRenderableType)
m_format.setRenderableType(QSurfaceFormat::OpenGL);
@@ -168,6 +191,11 @@ QCocoaGLContext::~QCocoaGLContext()
[m_context release];
}
+QVariant QCocoaGLContext::nativeHandle() const
+{
+ return QVariant::fromValue<QCocoaNativeContext>(QCocoaNativeContext(m_context));
+}
+
// Match up with createNSOpenGLPixelFormat!
QSurfaceFormat QCocoaGLContext::format() const
{
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h
index 3b72184d83..d692a179fd 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.h
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.h
@@ -80,6 +80,7 @@ NSRect qt_mac_toNSRect(const QRect &rect);
QRect qt_mac_toQRect(const NSRect &rect);
QColor qt_mac_toQColor(const NSColor *color);
+QColor qt_mac_toQColor(CGColorRef color);
// Creates a mutable shape, it's the caller's responsibility to release.
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index 9850f83dea..526204a414 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -225,6 +225,24 @@ QColor qt_mac_toQColor(const NSColor *color)
return qtColor;
}
+QColor qt_mac_toQColor(CGColorRef color)
+{
+ QColor qtColor;
+ CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(color));
+ const CGFloat *components = CGColorGetComponents(color);
+ if (model == kCGColorSpaceModelRGB) {
+ qtColor.setRgbF(components[0], components[1], components[2], components[3]);
+ } else if (model == kCGColorSpaceModelCMYK) {
+ qtColor.setCmykF(components[0], components[1], components[2], components[3]);
+ } else if (model == kCGColorSpaceModelMonochrome) {
+ qtColor.setRgbF(components[0], components[0], components[0], components[1]);
+ } else {
+ // Colorspace we can't deal with.
+ qWarning("Qt: qt_mac_toQColor: cannot convert from colorspace model: %d", model);
+ Q_ASSERT(false);
+ }
+ return qtColor;
+}
// Use this method to keep all the information in the TextSegment. As long as it is ordered
// we are in OK shape, and we can influence that ourselves.
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index 07b73c1a7a..5ca2ccc571 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -113,7 +113,9 @@ public:
bool hasCapability(QPlatformIntegration::Capability cap) const;
QPlatformWindow *createPlatformWindow(QWindow *window) const;
+#ifndef QT_NO_OPENGL
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;
+#endif
QPlatformBackingStore *createPlatformBackingStore(QWindow *widget) const;
QAbstractEventDispatcher *createEventDispatcher() const;
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index fca7fa042c..4be49ed68f 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -420,30 +420,37 @@ bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) cons
{
switch (cap) {
case ThreadedPixmaps:
+#ifndef QT_NO_OPENGL
case OpenGL:
case ThreadedOpenGL:
case BufferQueueingOpenGL:
+#endif
case WindowMasks:
case MultipleWindows:
case ForeignWindows:
case RasterGLSurface:
+ case ApplicationState:
return true;
default:
return QPlatformIntegration::hasCapability(cap);
}
}
-
-
QPlatformWindow *QCocoaIntegration::createPlatformWindow(QWindow *window) const
{
return new QCocoaWindow(window);
}
+#ifndef QT_NO_OPENGL
QPlatformOpenGLContext *QCocoaIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
- return new QCocoaGLContext(context->format(), context->shareHandle());
+ QCocoaGLContext *glContext = new QCocoaGLContext(context->format(),
+ context->shareHandle(),
+ context->nativeHandle());
+ context->setNativeHandle(glContext->nativeHandle());
+ return glContext;
}
+#endif
QPlatformBackingStore *QCocoaIntegration::createPlatformBackingStore(QWindow *window) const
{
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h
index 54e45a1d99..da60afd4e7 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h
@@ -61,15 +61,19 @@ class QCocoaNativeInterface : public QPlatformNativeInterface
public:
QCocoaNativeInterface();
+#ifndef QT_NO_OPENGL
void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context);
+#endif
void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window);
NativeResourceForIntegrationFunction nativeResourceFunctionForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE;
Q_INVOKABLE void beep();
+#ifndef QT_NO_OPENGL
static void *cglContextForContext(QOpenGLContext *context);
static void *nsOpenGLContextForContext(QOpenGLContext* context);
+#endif
public Q_SLOTS:
void onAppFocusWindowChanged(QWindow *window);
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
index e09c31231d..7b314665de 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
@@ -40,7 +40,6 @@
****************************************************************************/
#include "qcocoanativeinterface.h"
-#include "qcocoaglcontext.h"
#include "qcocoawindow.h"
#include "qcocoamenu.h"
#include "qcocoamenubar.h"
@@ -53,8 +52,11 @@
#include <qpixmap.h>
#include <qpa/qplatformwindow.h>
#include "qsurfaceformat.h"
+#ifndef QT_NO_OPENGL
#include <qpa/qplatformopenglcontext.h>
#include "qopenglcontext.h"
+#include "qcocoaglcontext.h"
+#endif
#include "qguiapplication.h"
#include <qdebug.h>
@@ -72,6 +74,7 @@ QCocoaNativeInterface::QCocoaNativeInterface()
{
}
+#ifndef QT_NO_OPENGL
void *QCocoaNativeInterface::nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context)
{
if (!context)
@@ -83,16 +86,19 @@ void *QCocoaNativeInterface::nativeResourceForContext(const QByteArray &resource
return 0;
}
+#endif
void *QCocoaNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window)
{
if (!window->handle())
return 0;
- if (resourceString == "nsopenglcontext") {
- return static_cast<QCocoaWindow *>(window->handle())->currentContext()->nsOpenGLContext();
- } else if (resourceString == "nsview") {
+ if (resourceString == "nsview") {
return static_cast<QCocoaWindow *>(window->handle())->m_contentView;
+#ifndef QT_NO_OPENGL
+ } else if (resourceString == "nsopenglcontext") {
+ return static_cast<QCocoaWindow *>(window->handle())->currentContext()->nsOpenGLContext();
+#endif
} else if (resourceString == "nswindow") {
return static_cast<QCocoaWindow *>(window->handle())->m_nsWindow;
}
@@ -198,6 +204,7 @@ void QCocoaNativeInterface::onAppFocusWindowChanged(QWindow *window)
QCocoaMenuBar::updateMenuBarImmediately();
}
+#ifndef QT_NO_OPENGL
void *QCocoaNativeInterface::cglContextForContext(QOpenGLContext* context)
{
NSOpenGLContext *nsOpenGLContext = static_cast<NSOpenGLContext*>(nsOpenGLContextForContext(context));
@@ -216,6 +223,7 @@ void *QCocoaNativeInterface::nsOpenGLContextForContext(QOpenGLContext* context)
}
return 0;
}
+#endif
void QCocoaNativeInterface::addToMimeList(void *macPasteboardMime)
{
diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
index f18be8b69c..26aa871998 100644
--- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
@@ -41,6 +41,8 @@
#include "qcocoasystemsettings.h"
+#include "qcocoahelpers.h"
+
#include <QtCore/private/qcore_mac_p.h>
#include <QtGui/qfont.h>
@@ -48,30 +50,11 @@
QT_BEGIN_NAMESPACE
-QColor qt_mac_colorFromCGColor(CGColorRef cgcolor)
-{
- QColor pc;
- CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(cgcolor));
- const CGFloat *components = CGColorGetComponents(cgcolor);
- if (model == kCGColorSpaceModelRGB) {
- pc.setRgbF(components[0], components[1], components[2], components[3]);
- } else if (model == kCGColorSpaceModelCMYK) {
- pc.setCmykF(components[0], components[1], components[2], components[3]);
- } else if (model == kCGColorSpaceModelMonochrome) {
- pc.setRgbF(components[0], components[0], components[0], components[1]);
- } else {
- // Colorspace we can't deal with.
- qWarning("Qt: qcolorFromCGColor: cannot convert from colorspace model: %d", model);
- Q_ASSERT(false);
- }
- return pc;
-}
-
QColor qt_mac_colorForTheme(ThemeBrush brush)
{
QCFType<CGColorRef> cgClr = 0;
HIThemeBrushCreateCGColor(brush, &cgClr);
- return qt_mac_colorFromCGColor(cgClr);
+ return qt_mac_toQColor(cgClr);
}
QColor qt_mac_colorForThemeTextColor(ThemeTextColor themeColor)
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index 7a21f7a8d3..8f885ab5f3 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -47,7 +47,9 @@
#include <qpa/qplatformwindow.h>
#include <QRect>
+#ifndef QT_NO_OPENGL
#include "qcocoaglcontext.h"
+#endif
#include "qnsview.h"
#include "qt_mac_p.h"
@@ -201,8 +203,10 @@ public:
void setWindowShadow(Qt::WindowFlags flags);
void setWindowZoomButton(Qt::WindowFlags flags);
+#ifndef QT_NO_OPENGL
void setCurrentContext(QCocoaGLContext *context);
QCocoaGLContext *currentContext() const;
+#endif
bool setWindowModified(bool modified) Q_DECL_OVERRIDE;
@@ -272,7 +276,9 @@ public: // for QNSView
bool m_inConstructor;
bool m_inSetVisible;
+#ifndef QT_NO_OPENGL
QCocoaGLContext *m_glContext;
+#endif
QCocoaMenuBar *m_menubar;
NSCursor *m_windowCursor;
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 4d0458a4aa..29b983cd89 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -43,7 +43,9 @@
#include "qnswindowdelegate.h"
#include "qcocoaautoreleasepool.h"
#include "qcocoaeventdispatcher.h"
+#ifndef QT_NO_OPENGL
#include "qcocoaglcontext.h"
+#endif
#include "qcocoahelpers.h"
#include "qcocoanativeinterface.h"
#include "qnsview.h"
@@ -373,7 +375,9 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
, m_windowUnderMouse(false)
, m_inConstructor(true)
, m_inSetVisible(false)
+#ifndef QT_NO_OPENGL
, m_glContext(0)
+#endif
, m_menubar(0)
, m_windowCursor(0)
, m_hasModalSession(false)
@@ -712,8 +716,10 @@ void QCocoaWindow::setVisible(bool visible)
[m_contentView setHidden:NO];
} else {
// qDebug() << "close" << this;
+#ifndef QT_NO_OPENGL
if (m_glContext)
m_glContext->windowWasHidden();
+#endif
QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast<QCocoaEventDispatcher *>(QGuiApplication::instance()->eventDispatcher());
QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = 0;
if (cocoaEventDispatcher)
@@ -1224,6 +1230,7 @@ bool QCocoaWindow::windowIsPopupType(Qt::WindowType type) const
return ((type & Qt::Popup) == Qt::Popup);
}
+#ifndef QT_NO_OPENGL
void QCocoaWindow::setCurrentContext(QCocoaGLContext *context)
{
m_glContext = context;
@@ -1233,6 +1240,7 @@ QCocoaGLContext *QCocoaWindow::currentContext() const
{
return m_glContext;
}
+#endif
void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow)
{
diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h
index 5387f2a825..a75e366a73 100644
--- a/src/plugins/platforms/cocoa/qnsview.h
+++ b/src/plugins/platforms/cocoa/qnsview.h
@@ -72,15 +72,19 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QNSViewMouseMoveHelper);
bool m_sendUpAsRightButton;
Qt::KeyboardModifiers currentWheelModifiers;
bool m_subscribesForGlobalFrameNotifications;
+#ifndef QT_NO_OPENGL
QCocoaGLContext *m_glContext;
bool m_shouldSetGLContextinDrawRect;
+#endif
NSString *m_inputSource;
QNSViewMouseMoveHelper *m_mouseMoveHelper;
}
- (id)init;
- (id)initWithQWindow:(QWindow *)window platformWindow:(QCocoaWindow *) platformWindow;
+#ifndef QT_NO_OPENGL
- (void)setQCocoaGLContext:(QCocoaGLContext *)context;
+#endif
- (void)flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset;
- (void)setMaskRegion:(const QRegion *)region;
- (void)invalidateWindowShadowIfNeeded;
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index a18ee7ff71..cc8fe51e0f 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -57,7 +57,9 @@
#include <QtCore/QDebug>
#include <private/qguiapplication_p.h>
#include "qcocoabackingstore.h"
+#ifndef QT_NO_OPENGL
#include "qcocoaglcontext.h"
+#endif
#include "qcocoaintegration.h"
#ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR
@@ -143,8 +145,10 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
m_frameStrutButtons = Qt::NoButton;
m_sendKeyEvent = false;
m_subscribesForGlobalFrameNotifications = false;
+#ifndef QT_NO_OPENGL
m_glContext = 0;
m_shouldSetGLContextinDrawRect = false;
+#endif
currentCustomDragTypes = 0;
m_sendUpAsRightButton = false;
m_inputSource = 0;
@@ -210,6 +214,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
return self;
}
+#ifndef QT_NO_OPENGL
- (void) setQCocoaGLContext:(QCocoaGLContext *)context
{
m_glContext = context;
@@ -231,6 +236,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
object:self];
}
}
+#endif
- (void) globalFrameChanged:(NSNotification*)notification
{
@@ -516,10 +522,12 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
- (void) drawRect:(NSRect)dirtyRect
{
+#ifndef QT_NO_OPENGL
if (m_glContext && m_shouldSetGLContextinDrawRect) {
[m_glContext->nsOpenGLContext() setView:self];
m_shouldSetGLContextinDrawRect = false;
}
+#endif
if (m_platformWindow->m_drawContentBorderGradient)
NSDrawWindowBackground(dirtyRect);
diff --git a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
index d18a01b11c..a02b074771 100644
--- a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
@@ -59,7 +59,7 @@
return nil;
QAccessible::Id childId = QAccessible::uniqueId(m_window->accessibleRoot());
- return [QCocoaAccessibleElement elementWithId: childId];
+ return [QMacAccessibilityElement elementWithId: childId];
}
// The QNSView is a container that the user does not interact directly with:
diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm
index ef67d1166f..f4cd071ab7 100644
--- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm
+++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm
@@ -193,7 +193,6 @@ CGImageRef qt_mac_create_imagemask(const QPixmap &pixmap, const QRectF &sr)
//conversion
inline static float qt_mac_convert_color_to_cg(int c) { return ((float)c * 1000 / 255) / 1000; }
-inline static int qt_mac_convert_color_from_cg(float c) { return qRound(c * 255); }
CGAffineTransform qt_mac_convert_transform_to_cg(const QTransform &t) {
return CGAffineTransformMake(t.m11(), t.m12(), t.m21(), t.m22(), t.dx(), t.dy());
}
@@ -974,11 +973,6 @@ void QCoreGraphicsPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, co
d->restoreGraphicsState();
}
-static void drawImageReleaseData (void *info, const void *, size_t)
-{
- delete static_cast<QImage *>(info);
-}
-
void QCoreGraphicsPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRectF &sr,
Qt::ImageConversionFlags flags)
{
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
index 1936ef0622..702ef7af92 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
@@ -60,22 +60,22 @@ public:
QWindowsDirect2DPlatformPixmap(PixelType pixelType, QWindowsDirect2DBitmap *bitmap);
~QWindowsDirect2DPlatformPixmap();
- virtual void resize(int width, int height);
+ void resize(int width, int height) Q_DECL_OVERRIDE;
virtual void fromImage(const QImage &image,
Qt::ImageConversionFlags flags);
- virtual int metric(QPaintDevice::PaintDeviceMetric metric) const;
- virtual void fill(const QColor &color);
+ int metric(QPaintDevice::PaintDeviceMetric metric) const Q_DECL_OVERRIDE;
+ void fill(const QColor &color) Q_DECL_OVERRIDE;
- virtual bool hasAlphaChannel() const;
+ bool hasAlphaChannel() const Q_DECL_OVERRIDE;
- virtual QImage toImage() const;
- virtual QImage toImage(const QRect &rect) const;
+ QImage toImage() const Q_DECL_OVERRIDE;
+ QImage toImage(const QRect &rect) const Q_DECL_OVERRIDE;
- virtual QPaintEngine* paintEngine() const;
+ QPaintEngine* paintEngine() const Q_DECL_OVERRIDE;
- virtual qreal devicePixelRatio() const;
- virtual void setDevicePixelRatio(qreal scaleFactor);
+ qreal devicePixelRatio() const Q_DECL_OVERRIDE;
+ void setDevicePixelRatio(qreal scaleFactor) Q_DECL_OVERRIDE;
QWindowsDirect2DBitmap *bitmap() const;
diff --git a/src/plugins/platforms/eglfs/qeglfscontext.cpp b/src/plugins/platforms/eglfs/qeglfscontext.cpp
index 4d443b91e3..71c3c1e59b 100644
--- a/src/plugins/platforms/eglfs/qeglfscontext.cpp
+++ b/src/plugins/platforms/eglfs/qeglfscontext.cpp
@@ -42,7 +42,6 @@
#include "qeglfscontext.h"
#include "qeglfswindow.h"
#include "qeglfshooks.h"
-#include "qeglfsintegration.h"
#include <QtPlatformSupport/private/qeglconvenience_p.h>
#include <QtPlatformSupport/private/qeglpbuffer_p.h>
@@ -52,9 +51,9 @@
QT_BEGIN_NAMESPACE
-QEglFSContext::QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display)
- : QEGLPlatformContext(format, share, display,
- QEglFSIntegration::chooseConfig(display, format))
+QEglFSContext::QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
+ EGLConfig *config, const QVariant &nativeHandle)
+ : QEGLPlatformContext(format, share, display, config, nativeHandle)
{
}
diff --git a/src/plugins/platforms/eglfs/qeglfscontext.h b/src/plugins/platforms/eglfs/qeglfscontext.h
index 5d406f09f1..d378b7818b 100644
--- a/src/plugins/platforms/eglfs/qeglfscontext.h
+++ b/src/plugins/platforms/eglfs/qeglfscontext.h
@@ -43,13 +43,15 @@
#define QEGLFSCONTEXT_H
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
+#include <QtCore/QVariant>
QT_BEGIN_NAMESPACE
class QEglFSContext : public QEGLPlatformContext
{
public:
- QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display);
+ QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
+ EGLConfig *config, const QVariant &nativeHandle);
EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) Q_DECL_OVERRIDE;
void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE;
};
diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
index 2941806f17..d770ea763a 100644
--- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
@@ -50,6 +50,7 @@
#include <QtPlatformSupport/private/qeglconvenience_p.h>
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
#include <QtPlatformSupport/private/qeglpbuffer_p.h>
+#include <QtPlatformHeaders/QEGLNativeContext>
#include <qpa/qplatformwindow.h>
#include <QtGui/QSurfaceFormat>
@@ -115,9 +116,20 @@ QEGLPlatformWindow *QEglFSIntegration::createWindow(QWindow *window) const
QEGLPlatformContext *QEglFSIntegration::createContext(const QSurfaceFormat &format,
QPlatformOpenGLContext *shareContext,
- EGLDisplay display) const
+ EGLDisplay display,
+ QVariant *nativeHandle) const
{
- return new QEglFSContext(QEglFSHooks::hooks()->surfaceFormatFor(format), shareContext, display);
+ QEglFSContext *ctx;
+ if (!nativeHandle || nativeHandle->isNull()) {
+ EGLConfig config = QEglFSIntegration::chooseConfig(display, format);
+ ctx = new QEglFSContext(QEglFSHooks::hooks()->surfaceFormatFor(format), shareContext, display,
+ &config, QVariant());
+ } else {
+ ctx = new QEglFSContext(QEglFSHooks::hooks()->surfaceFormatFor(format), shareContext, display,
+ 0, *nativeHandle);
+ }
+ *nativeHandle = QVariant::fromValue<QEGLNativeContext>(QEGLNativeContext(ctx->eglContext(), display));
+ return ctx;
}
QPlatformOffscreenSurface *QEglFSIntegration::createOffscreenSurface(EGLDisplay display,
diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.h b/src/plugins/platforms/eglfs/qeglfsintegration.h
index 99dda1ea96..fea05cd400 100644
--- a/src/plugins/platforms/eglfs/qeglfsintegration.h
+++ b/src/plugins/platforms/eglfs/qeglfsintegration.h
@@ -66,7 +66,8 @@ protected:
QEGLPlatformWindow *createWindow(QWindow *window) const Q_DECL_OVERRIDE;
QEGLPlatformContext *createContext(const QSurfaceFormat &format,
QPlatformOpenGLContext *shareContext,
- EGLDisplay display) const Q_DECL_OVERRIDE;
+ EGLDisplay display,
+ QVariant *nativeHandle) const Q_DECL_OVERRIDE;
QPlatformOffscreenSurface *createOffscreenSurface(EGLDisplay display,
const QSurfaceFormat &format,
QOffscreenSurface *surface) const Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp
index 2d36c0b58e..a0150b7ade 100644
--- a/src/plugins/platforms/eglfs/qeglfswindow.cpp
+++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp
@@ -82,8 +82,10 @@ void QEglFSWindow::create()
// they will be composited onto the root window's surface.
QEglFSScreen *screen = this->screen();
if (screen->primarySurface() != EGL_NO_SURFACE) {
- if (isRaster() && screen->compositingWindow())
+ if (isRaster() && screen->compositingWindow()) {
+ m_format = screen->compositingWindow()->format();
return;
+ }
#if !defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)
// We can have either a single OpenGL window or multiple raster windows.
diff --git a/src/plugins/platforms/ios/ios.pro b/src/plugins/platforms/ios/ios.pro
index ffc4ff9b12..ad9912a8d0 100644
--- a/src/plugins/platforms/ios/ios.pro
+++ b/src/plugins/platforms/ios/ios.pro
@@ -23,7 +23,10 @@ OBJECTIVE_SOURCES = \
qiostheme.mm \
qiosglobal.mm \
qiosservices.mm \
- qiosclipboard.mm
+ quiview.mm \
+ qiosclipboard.mm \
+ quiaccessibilityelement.mm \
+ qiosplatformaccessibility.mm \
HEADERS = \
qiosintegration.h \
@@ -40,7 +43,10 @@ HEADERS = \
qiosglobal.h \
qiosservices.h \
quiview.h \
- qiosclipboard.h
+ qiosclipboard.h \
+ quiaccessibilityelement.h \
+ qiosplatformaccessibility.h \
OTHER_FILES = \
- quiview_textinput.mm
+ quiview_textinput.mm \
+ quiview_accessibility.mm
diff --git a/src/plugins/platforms/ios/qiosapplicationdelegate.h b/src/plugins/platforms/ios/qiosapplicationdelegate.h
index 617b740d6e..f3c5c14502 100644
--- a/src/plugins/platforms/ios/qiosapplicationdelegate.h
+++ b/src/plugins/platforms/ios/qiosapplicationdelegate.h
@@ -45,7 +45,4 @@
#import "qiosviewcontroller.h"
@interface QIOSApplicationDelegate : UIResponder <UIApplicationDelegate>
-
-@property (strong, nonatomic) UIWindow *window;
-
@end
diff --git a/src/plugins/platforms/ios/qiosapplicationdelegate.mm b/src/plugins/platforms/ios/qiosapplicationdelegate.mm
index 9cf1047a6b..ef9f924384 100644
--- a/src/plugins/platforms/ios/qiosapplicationdelegate.mm
+++ b/src/plugins/platforms/ios/qiosapplicationdelegate.mm
@@ -46,47 +46,12 @@
#include "qiosviewcontroller.h"
#include "qioswindow.h"
-#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h>
#include <QtCore/QtCore>
@implementation QIOSApplicationDelegate
-@synthesize window;
-
-- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
-{
- Q_UNUSED(application);
- Q_UNUSED(launchOptions);
-
- self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
- self.window.rootViewController = [[[QIOSViewController alloc] init] autorelease];
-
-#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_7_0)
- QSysInfo::MacVersion iosVersion = QSysInfo::MacintoshVersion;
-
- // We prefer to keep the root viewcontroller in fullscreen layout, so that
- // we don't have to compensate for the viewcontroller position. This also
- // gives us the same behavior on iOS 5/6 as on iOS 7, where full screen layout
- // is the only way.
- if (iosVersion < QSysInfo::MV_IOS_7_0)
- self.window.rootViewController.wantsFullScreenLayout = YES;
-
- // Use translucent statusbar by default on iOS6 iPhones (unless the user changed
- // the default in the Info.plist), so that windows placed under the stausbar are
- // still visible, just like on iOS7.
- if (iosVersion >= QSysInfo::MV_IOS_6_0 && iosVersion < QSysInfo::MV_IOS_7_0
- && [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone
- && [UIApplication sharedApplication].statusBarStyle == UIStatusBarStyleDefault)
- [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent];
-#endif
-
- self.window.hidden = NO;
-
- return YES;
-}
-
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
Q_UNUSED(application);
@@ -96,17 +61,13 @@
if (!QGuiApplication::instance())
return NO;
- QIOSIntegration *iosIntegration = static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration());
+ QIOSIntegration *iosIntegration = QIOSIntegration::instance();
+ Q_ASSERT(iosIntegration);
+
QIOSServices *iosServices = static_cast<QIOSServices *>(iosIntegration->services());
return iosServices->handleUrl(QUrl::fromNSURL(url));
}
-- (void)dealloc
-{
- [window release];
- [super dealloc];
-}
-
@end
diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm
index ddee52196a..4083c2d5a9 100644
--- a/src/plugins/platforms/ios/qioscontext.mm
+++ b/src/plugins/platforms/ios/qioscontext.mm
@@ -47,6 +47,7 @@
#include <QtGui/QOpenGLContext>
#import <OpenGLES/EAGL.h>
+#import <OpenGLES/ES2/glext.h>
#import <QuartzCore/CAEAGLLayer.h>
QIOSContext::QIOSContext(QOpenGLContext *context)
diff --git a/src/plugins/platforms/ios/qiosintegration.h b/src/plugins/platforms/ios/qiosintegration.h
index 956c112399..89ca0349d9 100644
--- a/src/plugins/platforms/ios/qiosintegration.h
+++ b/src/plugins/platforms/ios/qiosintegration.h
@@ -82,14 +82,20 @@ public:
void *nativeResourceForWindow(const QByteArray &resource, QWindow *window);
QTouchDevice *touchDevice();
+ QPlatformAccessibility *accessibility() const Q_DECL_OVERRIDE;
+
+ void addScreen(QPlatformScreen *screen) { screenAdded(screen); }
+
+ static QIOSIntegration *instance();
+
private:
QPlatformFontDatabase *m_fontDatabase;
QPlatformClipboard *m_clipboard;
QPlatformInputContext *m_inputContext;
- QPlatformScreen *m_screen;
QTouchDevice *m_touchDevice;
QIOSApplicationState m_applicationState;
QIOSServices *m_platformServices;
+ mutable QPlatformAccessibility *m_accessibility;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
index 0fe7adff9f..9a722ead37 100644
--- a/src/plugins/platforms/ios/qiosintegration.mm
+++ b/src/plugins/platforms/ios/qiosintegration.mm
@@ -45,12 +45,15 @@
#include "qioswindow.h"
#include "qiosbackingstore.h"
#include "qiosscreen.h"
+#include "qiosplatformaccessibility.h"
#include "qioscontext.h"
#include "qiosclipboard.h"
#include "qiosinputcontext.h"
#include "qiostheme.h"
#include "qiosservices.h"
+#include <QtGui/private/qguiapplication_p.h>
+
#include <qpa/qplatformoffscreensurface.h>
#include <QtPlatformSupport/private/qcoretextfontdatabase_p.h>
@@ -61,12 +64,17 @@
QT_BEGIN_NAMESPACE
+QIOSIntegration *QIOSIntegration::instance()
+{
+ return static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration());
+}
+
QIOSIntegration::QIOSIntegration()
: m_fontDatabase(new QCoreTextFontDatabase)
, m_clipboard(new QIOSClipboard)
- , m_inputContext(new QIOSInputContext)
- , m_screen(new QIOSScreen(QIOSScreen::MainScreen))
+ , m_inputContext(0)
, m_platformServices(new QIOSServices)
+ , m_accessibility(0)
{
if (![UIApplication sharedApplication]) {
qWarning()
@@ -80,7 +88,11 @@ QIOSIntegration::QIOSIntegration()
// Set current directory to app bundle folder
QDir::setCurrent(QString::fromUtf8([[[NSBundle mainBundle] bundlePath] UTF8String]));
- screenAdded(m_screen);
+ for (UIScreen *screen in [UIScreen screens])
+ addScreen(new QIOSScreen(screen));
+
+ // Depends on a primary screen being present
+ m_inputContext = new QIOSInputContext;
m_touchDevice = new QTouchDevice;
m_touchDevice->setType(QTouchDevice::TouchScreen);
@@ -101,11 +113,14 @@ QIOSIntegration::~QIOSIntegration()
delete m_inputContext;
m_inputContext = 0;
- delete m_screen;
- m_screen = 0;
+ foreach (QScreen *screen, QGuiApplication::screens())
+ delete screen->handle();
delete m_platformServices;
m_platformServices = 0;
+
+ delete m_accessibility;
+ m_accessibility = 0;
}
bool QIOSIntegration::hasCapability(Capability cap) const
@@ -229,4 +244,11 @@ QTouchDevice *QIOSIntegration::touchDevice()
return m_touchDevice;
}
+QPlatformAccessibility *QIOSIntegration::accessibility() const
+{
+ if (!m_accessibility)
+ m_accessibility = new QIOSPlatformAccessibility;
+ return m_accessibility;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtplatformtheme.h b/src/plugins/platforms/ios/qiosplatformaccessibility.h
index f4a61982b2..beb0d006e1 100644
--- a/src/plugins/platforms/winrt/qwinrtplatformtheme.h
+++ b/src/plugins/platforms/ios/qiosplatformaccessibility.h
@@ -39,22 +39,22 @@
**
****************************************************************************/
-#ifndef QWINRTPLATFORMTHEME_H
-#define QWINRTPLATFORMTHEME_H
+#ifndef QIOSPLATFORMACCESSIBILITY_H
+#define QIOSPLATFORMACCESSIBILITY_H
-#include <qpa/qplatformtheme.h>
+#include <qpa/qplatformaccessibility.h>
QT_BEGIN_NAMESPACE
-class QWinRTPlatformTheme : public QPlatformTheme
+class QIOSPlatformAccessibility: public QPlatformAccessibility
{
public:
- QWinRTPlatformTheme();
+ QIOSPlatformAccessibility();
+ ~QIOSPlatformAccessibility();
- bool usePlatformNativeDialog(DialogType type) const;
- QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const;
+ virtual void notifyAccessibilityUpdate(QAccessibleEvent *event);
};
QT_END_NAMESPACE
-#endif // QWINRTPLATFORMTHEME_H
+#endif
diff --git a/src/plugins/platforms/ios/qiosplatformaccessibility.mm b/src/plugins/platforms/ios/qiosplatformaccessibility.mm
new file mode 100644
index 0000000000..db579ba559
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosplatformaccessibility.mm
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qiosplatformaccessibility.h"
+
+#include <QtGui/QtGui>
+#include "qioswindow.h"
+
+QIOSPlatformAccessibility::QIOSPlatformAccessibility()
+{}
+
+QIOSPlatformAccessibility::~QIOSPlatformAccessibility()
+{}
+
+
+void invalidateCache(QAccessibleInterface *iface)
+{
+ if (!iface || !iface->isValid()) {
+ qWarning() << "invalid accessible interface: " << iface;
+ return;
+ }
+
+ QWindow *win = 0;
+ QAccessibleInterface *parent = iface;
+ do {
+ win = parent->window();
+ parent = parent->parent();
+ } while (!win && parent);
+ Q_ASSERT(win && win->handle());
+ QIOSWindow *window = static_cast<QIOSWindow*>(win->handle());
+ window->clearAccessibleCache();
+}
+
+
+void QIOSPlatformAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
+{
+ switch (event->type()) {
+ case QAccessible::ObjectCreated:
+ case QAccessible::ObjectShow:
+ case QAccessible::ObjectHide:
+ case QAccessible::ObjectDestroyed:
+ invalidateCache(event->accessibleInterface());
+ break;
+ default:
+ break;
+ }
+}
diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h
index 173bd11719..9c7d53dcd6 100644
--- a/src/plugins/platforms/ios/qiosscreen.h
+++ b/src/plugins/platforms/ios/qiosscreen.h
@@ -55,11 +55,9 @@ class QIOSScreen : public QObject, public QPlatformScreen
Q_OBJECT
public:
- QIOSScreen(unsigned int screenIndex);
+ QIOSScreen(UIScreen *screen);
~QIOSScreen();
- enum ScreenIndex { MainScreen = 0 };
-
QRect geometry() const;
QRect availableGeometry() const;
int depth() const;
@@ -82,6 +80,7 @@ public slots:
private:
UIScreen *m_uiScreen;
+ UIWindow *m_uiWindow;
QRect m_geometry;
QRect m_availableGeometry;
int m_depth;
diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm
index 5331d05ae9..e876665431 100644
--- a/src/plugins/platforms/ios/qiosscreen.mm
+++ b/src/plugins/platforms/ios/qiosscreen.mm
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qiosglobal.h"
+#include "qiosintegration.h"
#include "qiosscreen.h"
#include "qioswindow.h"
#include <qpa/qwindowsysteminterface.h>
@@ -48,6 +49,63 @@
#include <sys/sysctl.h>
+// -------------------------------------------------------------------------
+
+static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
+{
+ foreach (QScreen *screen, QGuiApplication::screens()) {
+ QIOSScreen *platformScreen = static_cast<QIOSScreen *>(screen->handle());
+ if (platformScreen->uiScreen() == uiScreen)
+ return platformScreen;
+ }
+
+ return 0;
+}
+
+@interface QIOSScreenTracker : NSObject
+@end
+
+@implementation QIOSScreenTracker
+
++ (void)load
+{
+ NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+ [center addObserver:self selector:@selector(screenConnected:)
+ name:UIScreenDidConnectNotification object:nil];
+ [center addObserver:self selector:@selector(screenDisconnected:)
+ name:UIScreenDidDisconnectNotification object:nil];
+ [center addObserver:self selector:@selector(screenModeChanged:)
+ name:UIScreenModeDidChangeNotification object:nil];
+}
+
++ (void)screenConnected:(NSNotification*)notification
+{
+ QIOSIntegration *integration = QIOSIntegration::instance();
+ Q_ASSERT_X(integration, Q_FUNC_INFO, "Screen connected before QIOSIntegration creation");
+
+ integration->addScreen(new QIOSScreen([notification object]));
+}
+
++ (void)screenDisconnected:(NSNotification*)notification
+{
+ QIOSScreen *screen = qtPlatformScreenFor([notification object]);
+ Q_ASSERT_X(screen, Q_FUNC_INFO, "Screen disconnected that we didn't know about");
+
+ delete screen;
+}
+
++ (void)screenModeChanged:(NSNotification*)notification
+{
+ QIOSScreen *screen = qtPlatformScreenFor([notification object]);
+ Q_ASSERT_X(screen, Q_FUNC_INFO, "Screen changed that we didn't know about");
+
+ screen->updateProperties();
+}
+
+@end
+
+// -------------------------------------------------------------------------
+
@interface QIOSOrientationListener : NSObject {
@public
QIOSScreen *m_screen;
@@ -99,6 +157,8 @@
@end
+// -------------------------------------------------------------------------
+
/*!
Returns the model identifier of the device.
@@ -118,27 +178,51 @@ static QString deviceModelIdentifier()
return QString::fromLatin1(value);
}
-QIOSScreen::QIOSScreen(unsigned int screenIndex)
+QIOSScreen::QIOSScreen(UIScreen *screen)
: QPlatformScreen()
- , m_uiScreen([[UIScreen screens] count] > screenIndex
- ? [[UIScreen screens] objectAtIndex:screenIndex]
- : [UIScreen mainScreen])
+ , m_uiScreen(screen)
+ , m_uiWindow(0)
, m_orientationListener(0)
{
- QString deviceIdentifier = deviceModelIdentifier();
+ for (UIWindow *existingWindow in [[UIApplication sharedApplication] windows]) {
+ if (existingWindow.screen == m_uiScreen) {
+ m_uiWindow = [m_uiWindow retain];
+ break;
+ }
+ }
- if (deviceIdentifier == QStringLiteral("iPhone2,1") /* iPhone 3GS */
- || deviceIdentifier == QStringLiteral("iPod3,1") /* iPod touch 3G */) {
- m_depth = 18;
- } else {
- m_depth = 24;
+ if (!m_uiWindow) {
+ // Create a window and associated view-controller that we can use
+ m_uiWindow = [[UIWindow alloc] initWithFrame:[m_uiScreen bounds]];
+ m_uiWindow.rootViewController = [[[QIOSViewController alloc] initWithQIOSScreen:this] autorelease];
+
+ // FIXME: Only do once windows are added to the screen, and for any screen
+ if (screen == [UIScreen mainScreen]) {
+ m_uiWindow.screen = m_uiScreen;
+ m_uiWindow.hidden = NO;
+ }
}
- if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad
- && !deviceIdentifier.contains(QRegularExpression("^iPad2,[567]$")) /* excluding iPad Mini */) {
- m_unscaledDpi = 132;
+ if (screen == [UIScreen mainScreen]) {
+ QString deviceIdentifier = deviceModelIdentifier();
+
+ if (deviceIdentifier == QStringLiteral("iPhone2,1") /* iPhone 3GS */
+ || deviceIdentifier == QStringLiteral("iPod3,1") /* iPod touch 3G */) {
+ m_depth = 18;
+ } else {
+ m_depth = 24;
+ }
+
+ if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad
+ && !deviceIdentifier.contains(QRegularExpression("^iPad2,[567]$")) /* excluding iPad Mini */) {
+ m_unscaledDpi = 132;
+ } else {
+ m_unscaledDpi = 163; // Regular iPhone DPI
+ }
} else {
- m_unscaledDpi = 163; // Regular iPhone DPI
+ // External display, hard to say
+ m_depth = 24;
+ m_unscaledDpi = 96;
}
connect(qGuiApp, &QGuiApplication::focusWindowChanged, this, &QIOSScreen::updateStatusBarVisibility);
@@ -149,17 +233,12 @@ QIOSScreen::QIOSScreen(unsigned int screenIndex)
QIOSScreen::~QIOSScreen()
{
[m_orientationListener release];
+ [m_uiWindow release];
}
void QIOSScreen::updateProperties()
{
- UIWindow *uiWindow = 0;
- for (uiWindow in [[UIApplication sharedApplication] windows]) {
- if (uiWindow.screen == m_uiScreen)
- break;
- }
-
- bool inPortrait = UIInterfaceOrientationIsPortrait(uiWindow.rootViewController.interfaceOrientation);
+ bool inPortrait = UIInterfaceOrientationIsPortrait(m_uiWindow.rootViewController.interfaceOrientation);
QRect geometry = inPortrait ? fromCGRect(m_uiScreen.bounds).toRect()
: QRect(m_uiScreen.bounds.origin.x, m_uiScreen.bounds.origin.y,
m_uiScreen.bounds.size.height, m_uiScreen.bounds.size.width);
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.h b/src/plugins/platforms/ios/qiosviewcontroller.h
index a0017808d3..5e95cdd3ee 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.h
+++ b/src/plugins/platforms/ios/qiosviewcontroller.h
@@ -41,7 +41,13 @@
#import <UIKit/UIKit.h>
-@interface QIOSViewController : UIViewController
+class QIOSScreen;
+
+@interface QIOSViewController : UIViewController {
+ QIOSScreen *m_screen;
+}
+
+- (id)initWithQIOSScreen:(QIOSScreen *)screen;
- (BOOL)prefersStatusBarHidden;
@end
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index 2fe679fc20..73f1b51b83 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -53,6 +53,35 @@
@implementation QIOSViewController
+- (id)initWithQIOSScreen:(QIOSScreen *)screen
+{
+ if (self = [self init]) {
+ m_screen = screen;
+
+#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_7_0)
+ QSysInfo::MacVersion iosVersion = QSysInfo::MacintoshVersion;
+
+ // We prefer to keep the root viewcontroller in fullscreen layout, so that
+ // we don't have to compensate for the viewcontroller position. This also
+ // gives us the same behavior on iOS 5/6 as on iOS 7, where full screen layout
+ // is the only way.
+ if (iosVersion < QSysInfo::MV_IOS_7_0)
+ self.wantsFullScreenLayout = YES;
+
+ // Use translucent statusbar by default on iOS6 iPhones (unless the user changed
+ // the default in the Info.plist), so that windows placed under the stausbar are
+ // still visible, just like on iOS7.
+ if (screen->uiScreen() == [UIScreen mainScreen]
+ && iosVersion >= QSysInfo::MV_IOS_6_0 && iosVersion < QSysInfo::MV_IOS_7_0
+ && [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone
+ && [UIApplication sharedApplication].statusBarStyle == UIStatusBarStyleDefault)
+ [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent];
+#endif
+ }
+
+ return self;
+}
+
-(BOOL)shouldAutorotate
{
// Until a proper orientation and rotation API is in place, we always auto rotate.
@@ -85,8 +114,7 @@
if (!QCoreApplication::instance())
return; // FIXME: Store orientation for later (?)
- QIOSScreen *qiosScreen = static_cast<QIOSScreen *>(QGuiApplication::primaryScreen()->handle());
- qiosScreen->updateProperties();
+ m_screen->updateProperties();
}
#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0)
diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h
index 6b6892e6e4..bcff3e202c 100644
--- a/src/plugins/platforms/ios/qioswindow.h
+++ b/src/plugins/platforms/ios/qioswindow.h
@@ -87,6 +87,8 @@ public:
WId winId() const { return WId(m_view); };
+ void clearAccessibleCache();
+
private:
void applicationStateChanged(Qt::ApplicationState state);
void applyGeometry(const QRect &rect);
diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm
index 6f5c96cfc1..76bd9bb2b5 100644
--- a/src/plugins/platforms/ios/qioswindow.mm
+++ b/src/plugins/platforms/ios/qioswindow.mm
@@ -39,323 +39,23 @@
**
****************************************************************************/
-#include "qiosglobal.h"
#include "qioswindow.h"
-#include "quiview.h"
+
+#include "qiosapplicationdelegate.h"
#include "qioscontext.h"
-#include "qiosinputcontext.h"
+#include "qiosglobal.h"
+#include "qiosintegration.h"
#include "qiosscreen.h"
-#include "qiosapplicationdelegate.h"
#include "qiosviewcontroller.h"
-#include "qiosintegration.h"
-#include <QtGui/private/qguiapplication_p.h>
+#include "quiview.h"
+
#include <QtGui/private/qwindow_p.h>
#include <qpa/qplatformintegration.h>
#import <QuartzCore/CAEAGLLayer.h>
-#include <QtGui/QKeyEvent>
-#include <qpa/qwindowsysteminterface.h>
-
#include <QtDebug>
-// Include category as an alternative to using -ObjC (Apple QA1490)
-#include "quiview_textinput.mm"
-
-@implementation QUIView
-
-@synthesize autocapitalizationType;
-@synthesize autocorrectionType;
-@synthesize enablesReturnKeyAutomatically;
-@synthesize keyboardAppearance;
-@synthesize keyboardType;
-@synthesize returnKeyType;
-@synthesize secureTextEntry;
-
-+ (Class)layerClass
-{
- return [CAEAGLLayer class];
-}
-
--(id)initWithQIOSWindow:(QIOSWindow *)window
-{
- if (self = [self initWithFrame:toCGRect(window->geometry())])
- m_qioswindow = window;
-
- return self;
-}
-
-- (id)initWithFrame:(CGRect)frame
-{
- if ((self = [super initWithFrame:frame])) {
- // Set up EAGL layer
- CAEAGLLayer *eaglLayer = static_cast<CAEAGLLayer *>(self.layer);
- eaglLayer.opaque = TRUE;
- eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking,
- kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
-
- if (isQtApplication())
- self.hidden = YES;
-
- self.multipleTouchEnabled = YES;
- m_inSendEventToFocusObject = NO;
- }
-
- return self;
-}
-
-- (void)willMoveToWindow:(UIWindow *)newWindow
-{
- // UIKIt will normally set the scale factor of a view to match the corresponding
- // screen scale factor, but views backed by CAEAGLLayers need to do this manually.
- self.contentScaleFactor = newWindow && newWindow.screen ?
- newWindow.screen.scale : [[UIScreen mainScreen] scale];
-
- // FIXME: Allow the scale factor to be customized through QSurfaceFormat.
-}
-
-- (void)didAddSubview:(UIView *)subview
-{
- if ([subview isKindOfClass:[QUIView class]])
- self.clipsToBounds = YES;
-}
-
-- (void)willRemoveSubview:(UIView *)subview
-{
- for (UIView *view in self.subviews) {
- if (view != subview && [view isKindOfClass:[QUIView class]])
- return;
- }
-
- self.clipsToBounds = NO;
-}
-
-- (void)setNeedsDisplay
-{
- [super setNeedsDisplay];
-
- // We didn't implement drawRect: so we have to manually
- // mark the layer as needing display.
- [self.layer setNeedsDisplay];
-}
-
-- (void)layoutSubviews
-{
- // This method is the de facto way to know that view has been resized,
- // or otherwise needs invalidation of its buffers. Note though that we
- // do not get this callback when the view just changes its position, so
- // the position of our QWindow (and platform window) will only get updated
- // when the size is also changed.
-
- if (!CGAffineTransformIsIdentity(self.transform))
- 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;
- if (m_qioswindow->window()->isTopLevel()) {
- UIWindow *uiWindow = self.window;
- UIView *rootView = uiWindow.rootViewController.view;
- CGRect rootViewPositionInRelationToRootViewController =
- [rootView convertRect:uiWindow.bounds fromView:uiWindow];
-
- actualGeometry = fromCGRect(CGRectOffset([self.superview convertRect:self.frame toView:rootView],
- -rootViewPositionInRelationToRootViewController.origin.x,
- -rootViewPositionInRelationToRootViewController.origin.y
- + rootView.bounds.origin.y)).toRect();
- } else {
- actualGeometry = 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;
-
- QWindowSystemInterface::handleGeometryChange(m_qioswindow->window(), actualGeometry, previousGeometry);
- QWindowSystemInterface::flushWindowSystemEvents();
-
- if (actualGeometry.size() != previousGeometry.size()) {
- // Trigger expose event on resize
- [self setNeedsDisplay];
-
- // A new size means we also need to resize the FBO's corresponding buffers,
- // but we defer that to when the application calls makeCurrent.
- }
-}
-
-- (void)displayLayer:(CALayer *)layer
-{
- Q_UNUSED(layer);
- Q_ASSERT(layer == self.layer);
-
- [self sendUpdatedExposeEvent];
-}
-
-- (void)sendUpdatedExposeEvent
-{
- QRegion region;
-
- if (m_qioswindow->isExposed()) {
- QSize bounds = fromCGRect(self.layer.bounds).toRect().size();
-
- Q_ASSERT(m_qioswindow->geometry().size() == bounds);
- Q_ASSERT(self.hidden == !m_qioswindow->window()->isVisible());
-
- region = QRect(QPoint(), bounds);
- }
-
- QWindowSystemInterface::handleExposeEvent(m_qioswindow->window(), region);
- QWindowSystemInterface::flushWindowSystemEvents();
-}
-
-- (void)updateTouchList:(NSSet *)touches withState:(Qt::TouchPointState)state
-{
- // We deliver touch events in global coordinates. But global in this respect
- // means the same coordinate system that we use for describing the geometry
- // of the top level QWindow we're inside. And that would be the coordinate
- // system of the superview of the UIView that backs that window:
- QPlatformWindow *topLevel = m_qioswindow;
- while (QPlatformWindow *topLevelParent = topLevel->parent())
- topLevel = topLevelParent;
- UIView *rootView = reinterpret_cast<UIView *>(topLevel->winId()).superview;
- CGSize rootViewSize = rootView.frame.size;
-
- foreach (UITouch *uiTouch, m_activeTouches.keys()) {
- QWindowSystemInterface::TouchPoint &touchPoint = m_activeTouches[uiTouch];
- if (![touches containsObject:uiTouch]) {
- touchPoint.state = Qt::TouchPointStationary;
- } else {
- touchPoint.state = state;
- touchPoint.pressure = (state == Qt::TouchPointReleased) ? 0.0 : 1.0;
- QPoint touchPos = fromCGPoint([uiTouch locationInView:rootView]).toPoint();
- touchPoint.area = QRectF(touchPos, QSize(0, 0));
- touchPoint.normalPosition = QPointF(touchPos.x() / rootViewSize.width, touchPos.y() / rootViewSize.height);
- }
- }
-}
-
-- (void) sendTouchEventWithTimestamp:(ulong)timeStamp
-{
- // Send touch event synchronously
- QIOSIntegration *iosIntegration = static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration());
- QWindowSystemInterface::handleTouchEvent(m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values());
- QWindowSystemInterface::flushWindowSystemEvents();
-}
-
-- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
-{
- // UIKit generates [Began -> Moved -> Ended] event sequences for
- // each touch point. Internally we keep a hashmap of active UITouch
- // points to QWindowSystemInterface::TouchPoints, and assigns each TouchPoint
- // an id for use by Qt.
- for (UITouch *touch in touches) {
- Q_ASSERT(!m_activeTouches.contains(touch));
- m_activeTouches[touch].id = m_nextTouchId++;
- }
-
- if (m_activeTouches.size() == 1) {
- QPlatformWindow *topLevel = m_qioswindow;
- while (QPlatformWindow *p = topLevel->parent())
- topLevel = p;
- if (topLevel->window() != QGuiApplication::focusWindow())
- topLevel->requestActivateWindow();
- }
-
- [self updateTouchList:touches withState:Qt::TouchPointPressed];
- [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)];
-}
-
-- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
-{
- [self updateTouchList:touches withState:Qt::TouchPointMoved];
- [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)];
-}
-
-- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
-{
- [self updateTouchList:touches withState:Qt::TouchPointReleased];
- [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)];
-
- // Remove ended touch points from the active set:
- for (UITouch *touch in touches)
- m_activeTouches.remove(touch);
- if (m_activeTouches.isEmpty())
- m_nextTouchId = 0;
-}
-
-- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
-{
- if (m_activeTouches.isEmpty())
- return;
-
- // When four-finger swiping, we get a touchesCancelled callback
- // which includes all four touch points. The swipe gesture is
- // then active until all four touches have been released, and
- // we start getting touchesBegan events again.
-
- // When five-finger pinching, we also get a touchesCancelled
- // callback with all five touch points, but the pinch gesture
- // ends when the second to last finger is released from the
- // screen. The last finger will not emit any more touch
- // events, _but_, will contribute to starting another pinch
- // gesture. That second pinch gesture will _not_ trigger a
- // touchesCancelled event when starting, but as each finger
- // is released, and we may get touchesMoved events for the
- // remaining fingers. [event allTouches] also contains one
- // less touch point than it should, so this behavior is
- // likely a bug in the iOS system gesture recognizer, but we
- // have to take it into account when maintaining the Qt state.
- // We do this by assuming that there are no cases where a
- // sub-set of the active touch events are intentionally cancelled.
-
- if (touches && (static_cast<NSInteger>([touches count]) != m_activeTouches.count()))
- qWarning("Subset of active touches cancelled by UIKit");
-
- m_activeTouches.clear();
- m_nextTouchId = 0;
-
- NSTimeInterval timestamp = event ? event.timestamp : [[NSProcessInfo processInfo] systemUptime];
-
- // Send cancel touch event synchronously
- QIOSIntegration *iosIntegration = static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration());
- QWindowSystemInterface::handleTouchCancelEvent(m_qioswindow->window(), ulong(timestamp * 1000), iosIntegration->touchDevice());
- QWindowSystemInterface::flushWindowSystemEvents();
-}
-
-@end
-
-@implementation UIView (QIOS)
-
-- (QWindow *)qwindow
-{
- if ([self isKindOfClass:[QUIView class]]) {
- if (QIOSWindow *w = static_cast<QUIView *>(self)->m_qioswindow)
- return w->window();
- }
- return nil;
-}
-
-- (UIViewController *)viewController
-{
- id responder = self;
- while ((responder = [responder nextResponder])) {
- if ([responder isKindOfClass:UIViewController.class])
- return responder;
- }
- return nil;
-}
-
-@end
-
-QT_BEGIN_NAMESPACE
-
QIOSWindow::QIOSWindow(QWindow *window)
: QPlatformWindow(window)
, m_view([[QUIView alloc] initWithQIOSWindow:this])
@@ -634,6 +334,11 @@ qreal QIOSWindow::devicePixelRatio() const
return m_view.contentScaleFactor;
}
+void QIOSWindow::clearAccessibleCache()
+{
+ [m_view clearAccessibleCache];
+}
+
#include "moc_qioswindow.cpp"
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.h b/src/plugins/platforms/ios/quiaccessibilityelement.h
new file mode 100644
index 0000000000..7c5a930e86
--- /dev/null
+++ b/src/plugins/platforms/ios/quiaccessibilityelement.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QUIACCESSIBILITYELEMENT_H
+#define QUIACCESSIBILITYELEMENT_H
+
+#import <UIKit/UIKit.h>
+#import <QtGui/QtGui>
+
+@interface QMacAccessibilityElement : UIAccessibilityElement
+{}
+
+@property (readonly) QAccessible::Id axid;
+
+- (id) initWithId: (QAccessible::Id) anId withAccessibilityContainer: (id) view;
++ (QMacAccessibilityElement *) elementWithId: (QAccessible::Id) anId withAccessibilityContainer: (id) view;
+
+@end
+
+#endif
diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.mm b/src/plugins/platforms/ios/quiaccessibilityelement.mm
new file mode 100644
index 0000000000..331c38460c
--- /dev/null
+++ b/src/plugins/platforms/ios/quiaccessibilityelement.mm
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "quiaccessibilityelement.h"
+
+#include "private/qaccessiblecache_p.h"
+
+@implementation QMacAccessibilityElement
+
+- (id) initWithId: (QAccessible::Id) anId withAccessibilityContainer: (id) view
+{
+ Q_ASSERT((int)anId < 0);
+ self = [super initWithAccessibilityContainer: view];
+ if (self)
+ _axid = anId;
+
+ return self;
+}
+
++ (id) elementWithId: (QAccessible::Id) anId withAccessibilityContainer: (id) view
+{
+ Q_ASSERT(anId);
+ if (!anId)
+ return nil;
+
+ QAccessibleCache *cache = QAccessibleCache::instance();
+
+ QMacAccessibilityElement *element = cache->elementForId(anId);
+ if (!element) {
+ Q_ASSERT(QAccessible::accessibleInterface(anId));
+ element = [[self alloc] initWithId:anId withAccessibilityContainer: view];
+ cache->insertElement(anId, element);
+ }
+ return element;
+}
+
+- (void) invalidate
+{
+ [self release];
+}
+
+- (BOOL) isAccessibilityElement
+{
+ return YES;
+}
+
+- (NSString*) accessibilityLabel
+{
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
+ if (!iface) {
+ qWarning() << "invalid accessible interface for: " << self.axid;
+ return @"";
+ }
+
+ return iface->text(QAccessible::Name).toNSString();
+}
+
+- (NSString*) accessibilityHint
+{
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
+ if (!iface) {
+ qWarning() << "invalid accessible interface for: " << self.axid;
+ return @"";
+ }
+ return iface->text(QAccessible::Description).toNSString();
+}
+
+- (NSString*) accessibilityValue
+{
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
+ if (!iface) {
+ qWarning() << "invalid accessible interface for: " << self.axid;
+ return @"";
+ }
+
+ QAccessible::State state = iface->state();
+
+ if (state.checkable)
+ return state.checked ? @"checked" : @"unchecked"; // FIXME: translation
+
+ QAccessibleValueInterface *val = iface->valueInterface();
+ if (val) {
+ return val->currentValue().toString().toNSString();
+ } else if (QAccessibleTextInterface *text = iface->textInterface()) {
+ // FIXME doesn't work?
+ return text->text(0, text->characterCount() - 1).toNSString();
+ }
+
+ return [super accessibilityHint];
+}
+
+- (CGRect) accessibilityFrame
+{
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
+ if (!iface) {
+ qWarning() << "invalid accessible interface for: " << self.axid;
+ return CGRect();
+ }
+
+ QRect rect = iface->rect();
+ return CGRectMake(rect.x(), rect.y(), rect.width(), rect.height());
+}
+
+- (UIAccessibilityTraits) accessibilityTraits
+{
+ UIAccessibilityTraits traits = UIAccessibilityTraitNone;
+
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
+ if (!iface) {
+ qWarning() << "invalid accessible interface for: " << self.axid;
+ return traits;
+ }
+ QAccessible::State state = iface->state();
+ if (state.disabled)
+ traits |= UIAccessibilityTraitNotEnabled;
+
+ if (iface->role() == QAccessible::Button)
+ traits |= UIAccessibilityTraitButton;
+
+ if (iface->valueInterface())
+ traits |= UIAccessibilityTraitAdjustable;
+
+ return traits;
+}
+
+- (BOOL) accessibilityActivate
+{
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
+ if (QAccessibleActionInterface *action = iface->actionInterface()) {
+ if (action->actionNames().contains(QAccessibleActionInterface::pressAction())) {
+ action->doAction(QAccessibleActionInterface::pressAction());
+ return YES;
+ } else if (action->actionNames().contains(QAccessibleActionInterface::showMenuAction())) {
+ action->doAction(QAccessibleActionInterface::showMenuAction());
+ return YES;
+ }
+ }
+ return NO; // fall back to sending mouse clicks
+}
+
+- (void) accessibilityIncrement
+{
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
+ if (QAccessibleActionInterface *action = iface->actionInterface())
+ action->doAction(QAccessibleActionInterface::increaseAction());
+}
+
+- (void) accessibilityDecrement
+{
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
+ if (QAccessibleActionInterface *action = iface->actionInterface())
+ action->doAction(QAccessibleActionInterface::decreaseAction());
+}
+
+@end
diff --git a/src/plugins/platforms/ios/quiview.h b/src/plugins/platforms/ios/quiview.h
index 122e7c604b..99c710ffee 100644
--- a/src/plugins/platforms/ios/quiview.h
+++ b/src/plugins/platforms/ios/quiview.h
@@ -40,11 +40,23 @@
****************************************************************************/
#import <UIKit/UIKit.h>
-#include "qioswindow.h"
+
+#include <qhash.h>
+#include <qstring.h>
+
+#include <qpa/qwindowsysteminterface.h>
+
+class QIOSWindow;
@interface QUIView : UIView
{
-@public
+ @public
+ QIOSWindow *m_qioswindow;
+ @private
+ QHash<UITouch *, QWindowSystemInterface::TouchPoint> m_activeTouches;
+ int m_nextTouchId;
+
+ @public
UITextAutocapitalizationType autocapitalizationType;
UITextAutocorrectionType autocorrectionType;
BOOL enablesReturnKeyAutomatically;
@@ -52,11 +64,11 @@
UIKeyboardType keyboardType;
UIReturnKeyType returnKeyType;
BOOL secureTextEntry;
- QIOSWindow *m_qioswindow;
- QHash<UITouch *, QWindowSystemInterface::TouchPoint> m_activeTouches;
- int m_nextTouchId;
QString m_markedText;
BOOL m_inSendEventToFocusObject;
+
+ @private
+ NSMutableArray *m_accessibleElements;
}
@property(nonatomic, assign) id<UITextInputDelegate> inputDelegate;
@@ -69,6 +81,8 @@
@property(nonatomic) UIReturnKeyType returnKeyType;
@property(nonatomic, getter=isSecureTextEntry) BOOL secureTextEntry;
+- (id)initWithQIOSWindow:(QIOSWindow *)window;
+- (void)sendUpdatedExposeEvent;
@end
@interface QUIView (TextInput) <UITextInput>
@@ -77,3 +91,7 @@
- (void)commit;
+ (bool)inUpdateKeyboardLayout;
@end
+
+@interface QUIView (Accessibility)
+- (void)clearAccessibleCache;
+@end
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
new file mode 100644
index 0000000000..2726c6e3e0
--- /dev/null
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -0,0 +1,345 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "quiview.h"
+
+#include "qiosglobal.h"
+#include "qiosintegration.h"
+#include "qioswindow.h"
+
+#include <QtGui/private/qwindow_p.h>
+
+// Include category as an alternative to using -ObjC (Apple QA1490)
+#include "quiview_textinput.mm"
+#include "quiview_accessibility.mm"
+
+@implementation QUIView
+
+@synthesize autocapitalizationType;
+@synthesize autocorrectionType;
+@synthesize enablesReturnKeyAutomatically;
+@synthesize keyboardAppearance;
+@synthesize keyboardType;
+@synthesize returnKeyType;
+@synthesize secureTextEntry;
+
++ (Class)layerClass
+{
+ return [CAEAGLLayer class];
+}
+
+-(id)initWithQIOSWindow:(QIOSWindow *)window
+{
+ if (self = [self initWithFrame:toCGRect(window->geometry())])
+ m_qioswindow = window;
+
+ m_accessibleElements = [[NSMutableArray alloc] init];
+ return self;
+}
+
+- (id)initWithFrame:(CGRect)frame
+{
+ if ((self = [super initWithFrame:frame])) {
+ // Set up EAGL layer
+ CAEAGLLayer *eaglLayer = static_cast<CAEAGLLayer *>(self.layer);
+ eaglLayer.opaque = TRUE;
+ eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking,
+ kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
+
+ if (isQtApplication())
+ self.hidden = YES;
+
+ self.multipleTouchEnabled = YES;
+ m_inSendEventToFocusObject = NO;
+ }
+
+ return self;
+}
+
+- (void)willMoveToWindow:(UIWindow *)newWindow
+{
+ // UIKIt will normally set the scale factor of a view to match the corresponding
+ // screen scale factor, but views backed by CAEAGLLayers need to do this manually.
+ self.contentScaleFactor = newWindow && newWindow.screen ?
+ newWindow.screen.scale : [[UIScreen mainScreen] scale];
+
+ // FIXME: Allow the scale factor to be customized through QSurfaceFormat.
+}
+
+- (void)didAddSubview:(UIView *)subview
+{
+ if ([subview isKindOfClass:[QUIView class]])
+ self.clipsToBounds = YES;
+}
+
+- (void)willRemoveSubview:(UIView *)subview
+{
+ for (UIView *view in self.subviews) {
+ if (view != subview && [view isKindOfClass:[QUIView class]])
+ return;
+ }
+
+ self.clipsToBounds = NO;
+}
+
+- (void)setNeedsDisplay
+{
+ [super setNeedsDisplay];
+
+ // We didn't implement drawRect: so we have to manually
+ // mark the layer as needing display.
+ [self.layer setNeedsDisplay];
+}
+
+- (void)layoutSubviews
+{
+ // This method is the de facto way to know that view has been resized,
+ // or otherwise needs invalidation of its buffers. Note though that we
+ // do not get this callback when the view just changes its position, so
+ // the position of our QWindow (and platform window) will only get updated
+ // when the size is also changed.
+
+ if (!CGAffineTransformIsIdentity(self.transform))
+ 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;
+ if (m_qioswindow->window()->isTopLevel()) {
+ UIWindow *uiWindow = self.window;
+ UIView *rootView = uiWindow.rootViewController.view;
+ CGRect rootViewPositionInRelationToRootViewController =
+ [rootView convertRect:uiWindow.bounds fromView:uiWindow];
+
+ actualGeometry = fromCGRect(CGRectOffset([self.superview convertRect:self.frame toView:rootView],
+ -rootViewPositionInRelationToRootViewController.origin.x,
+ -rootViewPositionInRelationToRootViewController.origin.y
+ + rootView.bounds.origin.y)).toRect();
+ } else {
+ actualGeometry = 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;
+
+ QWindowSystemInterface::handleGeometryChange(m_qioswindow->window(), actualGeometry, previousGeometry);
+ QWindowSystemInterface::flushWindowSystemEvents();
+
+ if (actualGeometry.size() != previousGeometry.size()) {
+ // Trigger expose event on resize
+ [self setNeedsDisplay];
+
+ // A new size means we also need to resize the FBO's corresponding buffers,
+ // but we defer that to when the application calls makeCurrent.
+ }
+}
+
+- (void)displayLayer:(CALayer *)layer
+{
+ Q_UNUSED(layer);
+ Q_ASSERT(layer == self.layer);
+
+ [self sendUpdatedExposeEvent];
+}
+
+- (void)sendUpdatedExposeEvent
+{
+ QRegion region;
+
+ if (m_qioswindow->isExposed()) {
+ QSize bounds = fromCGRect(self.layer.bounds).toRect().size();
+
+ Q_ASSERT(m_qioswindow->geometry().size() == bounds);
+ Q_ASSERT(self.hidden == !m_qioswindow->window()->isVisible());
+
+ region = QRect(QPoint(), bounds);
+ }
+
+ QWindowSystemInterface::handleExposeEvent(m_qioswindow->window(), region);
+ QWindowSystemInterface::flushWindowSystemEvents();
+}
+
+- (void)updateTouchList:(NSSet *)touches withState:(Qt::TouchPointState)state
+{
+ // We deliver touch events in global coordinates. But global in this respect
+ // means the same coordinate system that we use for describing the geometry
+ // of the top level QWindow we're inside. And that would be the coordinate
+ // system of the superview of the UIView that backs that window:
+ QPlatformWindow *topLevel = m_qioswindow;
+ while (QPlatformWindow *topLevelParent = topLevel->parent())
+ topLevel = topLevelParent;
+ UIView *rootView = reinterpret_cast<UIView *>(topLevel->winId()).superview;
+ CGSize rootViewSize = rootView.frame.size;
+
+ foreach (UITouch *uiTouch, m_activeTouches.keys()) {
+ QWindowSystemInterface::TouchPoint &touchPoint = m_activeTouches[uiTouch];
+ if (![touches containsObject:uiTouch]) {
+ touchPoint.state = Qt::TouchPointStationary;
+ } else {
+ touchPoint.state = state;
+ touchPoint.pressure = (state == Qt::TouchPointReleased) ? 0.0 : 1.0;
+ QPoint touchPos = fromCGPoint([uiTouch locationInView:rootView]).toPoint();
+ touchPoint.area = QRectF(touchPos, QSize(0, 0));
+ touchPoint.normalPosition = QPointF(touchPos.x() / rootViewSize.width, touchPos.y() / rootViewSize.height);
+ }
+ }
+}
+
+- (void) sendTouchEventWithTimestamp:(ulong)timeStamp
+{
+ // Send touch event synchronously
+ QIOSIntegration *iosIntegration = QIOSIntegration::instance();
+ QWindowSystemInterface::handleTouchEvent(m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values());
+ QWindowSystemInterface::flushWindowSystemEvents();
+}
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ // UIKit generates [Began -> Moved -> Ended] event sequences for
+ // each touch point. Internally we keep a hashmap of active UITouch
+ // points to QWindowSystemInterface::TouchPoints, and assigns each TouchPoint
+ // an id for use by Qt.
+ for (UITouch *touch in touches) {
+ Q_ASSERT(!m_activeTouches.contains(touch));
+ m_activeTouches[touch].id = m_nextTouchId++;
+ }
+
+ if (m_activeTouches.size() == 1) {
+ QPlatformWindow *topLevel = m_qioswindow;
+ while (QPlatformWindow *p = topLevel->parent())
+ topLevel = p;
+ if (topLevel->window() != QGuiApplication::focusWindow())
+ topLevel->requestActivateWindow();
+ }
+
+ [self updateTouchList:touches withState:Qt::TouchPointPressed];
+ [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)];
+}
+
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ [self updateTouchList:touches withState:Qt::TouchPointMoved];
+ [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)];
+}
+
+- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ [self updateTouchList:touches withState:Qt::TouchPointReleased];
+ [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)];
+
+ // Remove ended touch points from the active set:
+ for (UITouch *touch in touches)
+ m_activeTouches.remove(touch);
+ if (m_activeTouches.isEmpty())
+ m_nextTouchId = 0;
+}
+
+- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ if (m_activeTouches.isEmpty())
+ return;
+
+ // When four-finger swiping, we get a touchesCancelled callback
+ // which includes all four touch points. The swipe gesture is
+ // then active until all four touches have been released, and
+ // we start getting touchesBegan events again.
+
+ // When five-finger pinching, we also get a touchesCancelled
+ // callback with all five touch points, but the pinch gesture
+ // ends when the second to last finger is released from the
+ // screen. The last finger will not emit any more touch
+ // events, _but_, will contribute to starting another pinch
+ // gesture. That second pinch gesture will _not_ trigger a
+ // touchesCancelled event when starting, but as each finger
+ // is released, and we may get touchesMoved events for the
+ // remaining fingers. [event allTouches] also contains one
+ // less touch point than it should, so this behavior is
+ // likely a bug in the iOS system gesture recognizer, but we
+ // have to take it into account when maintaining the Qt state.
+ // We do this by assuming that there are no cases where a
+ // sub-set of the active touch events are intentionally cancelled.
+
+ if (touches && (static_cast<NSInteger>([touches count]) != m_activeTouches.count()))
+ qWarning("Subset of active touches cancelled by UIKit");
+
+ m_activeTouches.clear();
+ m_nextTouchId = 0;
+
+ NSTimeInterval timestamp = event ? event.timestamp : [[NSProcessInfo processInfo] systemUptime];
+
+ // Send cancel touch event synchronously
+ QIOSIntegration *iosIntegration = static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration());
+ QWindowSystemInterface::handleTouchCancelEvent(m_qioswindow->window(), ulong(timestamp * 1000), iosIntegration->touchDevice());
+ QWindowSystemInterface::flushWindowSystemEvents();
+}
+
+@end
+
+@implementation UIView (QtHelpers)
+
+- (QWindow *)qwindow
+{
+ if ([self isKindOfClass:[QUIView class]]) {
+ if (QIOSWindow *w = static_cast<QUIView *>(self)->m_qioswindow)
+ return w->window();
+ }
+ return nil;
+}
+
+- (UIViewController *)viewController
+{
+ id responder = self;
+ while ((responder = [responder nextResponder])) {
+ if ([responder isKindOfClass:UIViewController.class])
+ return responder;
+ }
+ return nil;
+}
+
+@end
diff --git a/src/plugins/platforms/ios/quiview_accessibility.mm b/src/plugins/platforms/ios/quiview_accessibility.mm
new file mode 100644
index 0000000000..6565e08302
--- /dev/null
+++ b/src/plugins/platforms/ios/quiview_accessibility.mm
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qiosplatformaccessibility.h"
+#include "quiaccessibilityelement.h"
+
+#include <QtGui/private/qguiapplication_p.h>
+
+@implementation QUIView (Accessibility)
+
+- (void)createAccessibleElement:(QAccessibleInterface *)iface
+{
+ if (!iface || iface->state().invisible)
+ return;
+ QAccessible::Id accessibleId = QAccessible::uniqueId(iface);
+ UIAccessibilityElement *elem = [[QMacAccessibilityElement alloc] initWithId: accessibleId withAccessibilityContainer: self];
+ [m_accessibleElements addObject: elem];
+}
+
+- (void)createAccessibleContainer:(QAccessibleInterface *)iface
+{
+ if (!iface)
+ return;
+
+ if (iface->childCount() == 0) {
+ [self createAccessibleElement: iface];
+ } else {
+ for (int i = 0; i < iface->childCount(); ++i)
+ [self createAccessibleContainer: iface->child(i)];
+ }
+}
+
+- (void)initAccessibility
+{
+ static bool init = false;
+ if (!init)
+ QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true);
+ init = true;
+
+ if ([m_accessibleElements count])
+ return;
+
+ QWindow *win = m_qioswindow->window();
+ QAccessibleInterface *iface = win->accessibleRoot();
+ if (iface)
+ [self createAccessibleContainer: iface];
+}
+
+- (void)clearAccessibleCache
+{
+ [m_accessibleElements removeAllObjects];
+ UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, @"");
+}
+
+// this is a container, returning yes here means the functions below will never be called
+- (BOOL)isAccessibilityElement
+{
+ return NO;
+}
+
+- (NSInteger)accessibilityElementCount
+{
+ [self initAccessibility];
+ return [m_accessibleElements count];
+}
+
+- (id)accessibilityElementAtIndex:(NSInteger)index
+{
+ [self initAccessibility];
+ return m_accessibleElements[index];
+}
+
+- (NSInteger)indexOfAccessibilityElement:(id)element
+{
+ [self initAccessibility];
+ return [m_accessibleElements indexOfObject:element];
+}
+
+@end
diff --git a/src/plugins/platforms/ios/quiview_textinput.mm b/src/plugins/platforms/ios/quiview_textinput.mm
index e65ac1cc46..861c8151c6 100644
--- a/src/plugins/platforms/ios/quiview_textinput.mm
+++ b/src/plugins/platforms/ios/quiview_textinput.mm
@@ -39,7 +39,10 @@
**
****************************************************************************/
+#include "qiosinputcontext.h"
+
#include <QtGui/qtextformat.h>
+#include <QtGui/private/qguiapplication_p.h>
class StaticVariables
{
diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp
index 6c6c516a4e..3f959b859c 100644
--- a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp
+++ b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp
@@ -179,7 +179,7 @@ QOffscreenX11GLXContext::QOffscreenX11GLXContext(QOffscreenX11Info *x11, QOpenGL
// Get the basic surface format details
if (d->context)
- qglx_surfaceFormatFromGLXFBConfig(&d->format, x11->display(), config, d->context);
+ qglx_surfaceFormatFromGLXFBConfig(&d->format, x11->display(), config);
// Create a temporary window so that we can make the new context current
d->window = createDummyWindow(x11, config);
diff --git a/src/plugins/platforms/qnx/qqnxscreen.cpp b/src/plugins/platforms/qnx/qqnxscreen.cpp
index add45ecbe5..59dc84ebc8 100644
--- a/src/plugins/platforms/qnx/qqnxscreen.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreen.cpp
@@ -209,6 +209,103 @@ QQnxScreen::~QQnxScreen()
delete m_cursor;
}
+QPixmap QQnxScreen::grabWindow(WId window, int x, int y, int width, int height) const
+{
+ QQnxWindow *qnxWin = findWindow(reinterpret_cast<screen_window_t>(window));
+ if (!qnxWin) {
+ qWarning("grabWindow: unknown window");
+ return QPixmap();
+ }
+
+ QRect bound = qnxWin->geometry();
+
+ if (width < 0)
+ width = bound.width();
+ if (height < 0)
+ height = bound.height();
+
+ bound &= QRect(x + bound.x(), y + bound.y(), width, height);
+
+ if (bound.width() <= 0 || bound.height() <= 0) {
+ qWarning("grabWindow: size is null");
+ return QPixmap();
+ }
+
+ // Create new context, only SCREEN_DISPLAY_MANAGER_CONTEXT can read from screen
+ screen_context_t context;
+ if (screen_create_context(&context, SCREEN_DISPLAY_MANAGER_CONTEXT)) {
+ if (errno == EPERM)
+ qWarning("grabWindow: root privileges required");
+ else
+ qWarning("grabWindow: cannot create context");
+ return QPixmap();
+ }
+
+ // Find corresponding display in SCREEN_DISPLAY_MANAGER_CONTEXT
+ int count = 0;
+ screen_display_t display = 0;
+ screen_get_context_property_iv(context, SCREEN_PROPERTY_DISPLAY_COUNT, &count);
+ if (count > 0) {
+ const size_t idLen = 30;
+ char matchId[idLen];
+ char id[idLen];
+ bool found = false;
+
+ screen_display_t *displays = static_cast<screen_display_t*>
+ (calloc(count, sizeof(screen_display_t)));
+ screen_get_context_property_pv(context, SCREEN_PROPERTY_DISPLAYS, (void **)displays);
+ screen_get_display_property_cv(m_display, SCREEN_PROPERTY_ID_STRING, idLen, matchId);
+
+ while (count && !found) {
+ --count;
+ screen_get_display_property_cv(displays[count], SCREEN_PROPERTY_ID_STRING, idLen, id);
+ found = !strncmp(id, matchId, idLen);
+ }
+
+ if (found)
+ display = displays[count];
+
+ free(displays);
+ }
+
+ // Create screen and Qt pixmap
+ screen_pixmap_t pixmap;
+ QPixmap result;
+ if (display && !screen_create_pixmap(&pixmap, context)) {
+ screen_buffer_t buffer;
+ void *pointer;
+ int stride;
+ const int rect[4] = { bound.x(), bound.y(), bound.width(), bound.height() };
+
+ int val = SCREEN_USAGE_READ | SCREEN_USAGE_NATIVE;
+ screen_set_pixmap_property_iv(pixmap, SCREEN_PROPERTY_USAGE, &val);
+ val = SCREEN_FORMAT_RGBA8888;
+ screen_set_pixmap_property_iv(pixmap, SCREEN_PROPERTY_FORMAT, &val);
+
+ int err = screen_set_pixmap_property_iv(pixmap, SCREEN_PROPERTY_BUFFER_SIZE, rect+2);
+ err = err || screen_create_pixmap_buffer(pixmap);
+ err = err || screen_get_pixmap_property_pv(pixmap, SCREEN_PROPERTY_RENDER_BUFFERS,
+ reinterpret_cast<void**>(&buffer));
+ err = err || screen_get_buffer_property_pv(buffer, SCREEN_PROPERTY_POINTER, &pointer);
+ err = err || screen_get_buffer_property_iv(buffer, SCREEN_PROPERTY_STRIDE, &stride);
+ err = err || screen_read_display(display, buffer, 1, rect, 0);
+
+ if (!err) {
+ const QImage img(static_cast<unsigned char*>(pointer),
+ bound.width(), bound.height(), stride, QImage::Format_ARGB32);
+ result = QPixmap::fromImage(img);
+ } else {
+ qWarning("grabWindow: capture error");
+ }
+ screen_destroy_pixmap(pixmap);
+ } else {
+ qWarning("grabWindow: display/pixmap error ");
+ }
+ screen_destroy_context(context);
+
+ return result;
+}
+
static int defaultDepth()
{
qScreenDebug() << Q_FUNC_INFO;
@@ -463,7 +560,7 @@ void QQnxScreen::resizeWindows(const QRect &previousScreenGeometry)
}
}
-QQnxWindow *QQnxScreen::findWindow(screen_window_t windowHandle)
+QQnxWindow *QQnxScreen::findWindow(screen_window_t windowHandle) const
{
Q_FOREACH (QQnxWindow *window, m_childWindows) {
QQnxWindow * const result = window->findWindow(windowHandle);
diff --git a/src/plugins/platforms/qnx/qqnxscreen.h b/src/plugins/platforms/qnx/qqnxscreen.h
index 6b2281f7b9..a8a18c6240 100644
--- a/src/plugins/platforms/qnx/qqnxscreen.h
+++ b/src/plugins/platforms/qnx/qqnxscreen.h
@@ -62,6 +62,8 @@ public:
QQnxScreen(screen_context_t context, screen_display_t display, bool primaryScreen);
~QQnxScreen();
+ QPixmap grabWindow(WId window, int x, int y, int width, int height) const;
+
QRect geometry() const { return m_currentGeometry; }
QRect availableGeometry() const;
int depth() const;
@@ -86,7 +88,7 @@ public:
screen_context_t nativeContext() const { return m_screenContext; }
const char *windowGroupName() const { return m_rootWindow ? m_rootWindow->groupName().constData() : 0; }
- QQnxWindow *findWindow(screen_window_t windowHandle);
+ QQnxWindow *findWindow(screen_window_t windowHandle) const;
/* Window hierarchy management */
void addWindow(QQnxWindow *child);
diff --git a/src/plugins/platforms/windows/accessible/comutils.cpp b/src/plugins/platforms/windows/accessible/comutils.cpp
index 6c67345e05..366adb9059 100644
--- a/src/plugins/platforms/windows/accessible/comutils.cpp
+++ b/src/plugins/platforms/windows/accessible/comutils.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
diff --git a/src/plugins/platforms/windows/accessible/comutils.h b/src/plugins/platforms/windows/accessible/comutils.h
index ebf16dfdf8..2ef11ec0dd 100644
--- a/src/plugins/platforms/windows/accessible/comutils.h
+++ b/src/plugins/platforms/windows/accessible/comutils.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp
index 032f33163a..20658f9cad 100644
--- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp
+++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -43,7 +43,7 @@
#include "iaccessible2.h"
#include "qwindowsaccessibility.h"
-
+#include <QtPlatformSupport/private/qaccessiblebridgeutils_p.h>
#include <QtGui/qaccessible.h>
#include <QtGui/qclipboard.h>
#include <QtWidgets/qapplication.h>
@@ -358,6 +358,8 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::role(long *ia2role)
case QAccessible::LayeredPane: r = IA2_ROLE_LAYERED_PANE; break;
case QAccessible::Terminal: r = IA2_ROLE_TERMINAL; break;
case QAccessible::Desktop: r = IA2_ROLE_DESKTOP_PANE; break;
+ case QAccessible::Paragraph: r = IA2_ROLE_PARAGRAPH; break;
+ case QAccessible::Section: r = IA2_ROLE_SECTION; break;
default: break;
}
@@ -545,10 +547,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::nActions(long *nActions)
accessibleDebugClientCalls(accessible);
if (!accessible)
return E_FAIL;
- *nActions = 0;
-
- if (QAccessibleActionInterface *actionIface = actionInterface())
- *nActions = actionIface->actionNames().count();
+ *nActions = QAccessibleBridgeUtils::effectiveActionNames(accessible).count();
return S_OK;
}
@@ -558,15 +557,11 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::doAction(long actionIndex)
accessibleDebugClientCalls(accessible);
if (!accessible)
return E_FAIL;
- if (QAccessibleActionInterface *actionIface = actionInterface()) {
- const QStringList actionNames = actionIface->actionNames();
- if (actionIndex < 0 || actionIndex >= actionNames.count())
- return E_INVALIDARG;
- const QString actionName = actionNames.at(actionIndex);
- actionIface->doAction(actionName);
- return S_OK;
- }
- return S_FALSE;
+ const QStringList actionNames = QAccessibleBridgeUtils::effectiveActionNames(accessible);
+ if (actionIndex < 0 || actionIndex >= actionNames.count())
+ return E_INVALIDARG;
+ const QString actionName = actionNames.at(actionIndex);
+ return QAccessibleBridgeUtils::performEffectiveAction(accessible, actionName) ? S_OK : S_FALSE;
}
HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_description(long actionIndex, BSTR *description)
@@ -576,13 +571,15 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_description(long actionInde
if (!accessible)
return E_FAIL;
*description = 0;
- if (QAccessibleActionInterface *actionIface = actionInterface()) {
- const QStringList actionNames = actionIface->actionNames();
- if (actionIndex < 0 || actionIndex >= actionNames.count())
- return E_INVALIDARG;
- const QString actionName = actionNames.at(actionIndex);
+ const QStringList actionNames = QAccessibleBridgeUtils::effectiveActionNames(accessible);
+ if (actionIndex < 0 || actionIndex >= actionNames.count())
+ return E_INVALIDARG;
+ const QString actionName = actionNames.at(actionIndex);
+ if (QAccessibleActionInterface *actionIface = actionInterface())
*description = QStringToBSTR(actionIface->localizedActionDescription(actionName));
- }
+ else
+ *description = QStringToBSTR(qAccessibleLocalizedActionDescription(actionName));
+
return *description ? S_OK : S_FALSE;
}
@@ -622,13 +619,11 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_name(long actionIndex, BSTR
if (!accessible)
return E_FAIL;
*name = 0;
- if (QAccessibleActionInterface *actionIface = actionInterface()) {
- const QStringList actionNames = actionIface->actionNames();
- if (actionIndex < 0 || actionIndex >= actionNames.count())
- return E_INVALIDARG;
- const QString actionName = actionNames.at(actionIndex);
- *name = QStringToBSTR(actionName);
- }
+ const QStringList actionNames = QAccessibleBridgeUtils::effectiveActionNames(accessible);
+ if (actionIndex < 0 || actionIndex >= actionNames.count())
+ return E_INVALIDARG;
+ const QString actionName = actionNames.at(actionIndex);
+ *name = QStringToBSTR(actionName);
return *name ? S_OK : S_FALSE;
}
@@ -639,14 +634,16 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedName(long actionIn
if (!accessible)
return E_FAIL;
*localizedName = 0;
- if (QAccessibleActionInterface *actionIface = actionInterface()) {
- const QStringList actionNames = actionIface->actionNames();
- if (actionIndex < 0 || actionIndex >= actionNames.count())
- return E_INVALIDARG;
+ const QStringList actionNames = QAccessibleBridgeUtils::effectiveActionNames(accessible);
+ if (actionIndex < 0 || actionIndex >= actionNames.count())
+ return E_INVALIDARG;
- const QString actionName = actionNames.at(actionIndex);
+ const QString actionName = actionNames.at(actionIndex);
+ if (QAccessibleActionInterface *actionIface = actionInterface())
*localizedName = QStringToBSTR(actionIface->localizedActionName(actionName));
- }
+ else
+ *localizedName = QStringToBSTR(QAccessibleActionInterface::tr(qPrintable(actionName)));
+
return *localizedName ? S_OK : S_FALSE;
}
diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.h b/src/plugins/platforms/windows/accessible/iaccessible2.h
index 9c42fdc631..fd92fb25bf 100644
--- a/src/plugins/platforms/windows/accessible/iaccessible2.h
+++ b/src/plugins/platforms/windows/accessible/iaccessible2.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
index 307f2fc3bb..f5b0f2f166 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
+++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h
index f25e2281a0..9e14868415 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h
+++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
index bda806d102..d606ecb6a5 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
+++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -890,6 +890,11 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accName(VARIANT varID, BST
}
}
}
+
+ QString shortcut = accessible->text(QAccessible::Accelerator);
+ if (!shortcut.isEmpty())
+ name.append(QLatin1Char(' ') + shortcut);
+
if (name.size()) {
*pszName = QStringToBSTR(name);
return S_OK;
@@ -930,6 +935,8 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accRole(VARIANT varID, VAR
// does not support IAccessible2, since it should prefer IA2::role() then.
if (role == QAccessible::LayeredPane)
role = QAccessible::Pane;
+ else if (role == QAccessible::WebDocument)
+ role = QAccessible::Document;
else
role = QAccessible::Client;
}
@@ -1034,7 +1041,7 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accValue(VARIANT varID, BS
QString value;
if (accessible->valueInterface()) {
- value = QString::number(accessible->valueInterface()->currentValue().toDouble());
+ value = accessible->valueInterface()->currentValue().toString();
} else {
value = accessible->text(QAccessible::Value);
}
diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h
index 43482da4be..b9cc2ccb44 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h
+++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
diff --git a/src/plugins/platforms/windows/cursors.qrc b/src/plugins/platforms/windows/cursors.qrc
new file mode 100644
index 0000000000..fded527aac
--- /dev/null
+++ b/src/plugins/platforms/windows/cursors.qrc
@@ -0,0 +1,25 @@
+<RCC>
+ <qresource prefix="/qt-project.org/windows/cursors">
+ <file>images/closedhandcursor_32.png</file>
+ <file>images/closedhandcursor_48.png</file>
+ <file>images/closedhandcursor_64.png</file>
+ <file>images/dragcopycursor_32.png</file>
+ <file>images/dragcopycursor_48.png</file>
+ <file>images/dragcopycursor_64.png</file>
+ <file>images/draglinkcursor_32.png</file>
+ <file>images/draglinkcursor_48.png</file>
+ <file>images/draglinkcursor_64.png</file>
+ <file>images/dragmovecursor_32.png</file>
+ <file>images/dragmovecursor_48.png</file>
+ <file>images/dragmovecursor_64.png</file>
+ <file>images/openhandcursor_32.png</file>
+ <file>images/openhandcursor_48.png</file>
+ <file>images/openhandcursor_64.png</file>
+ <file>images/splithcursor_32.png</file>
+ <file>images/splithcursor_48.png</file>
+ <file>images/splithcursor_64.png</file>
+ <file>images/splitvcursor_32.png</file>
+ <file>images/splitvcursor_48.png</file>
+ <file>images/splitvcursor_64.png</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/platforms/windows/images/closedhandcursor_32.png b/src/plugins/platforms/windows/images/closedhandcursor_32.png
new file mode 100644
index 0000000000..7b3cba1965
--- /dev/null
+++ b/src/plugins/platforms/windows/images/closedhandcursor_32.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/closedhandcursor_48.png b/src/plugins/platforms/windows/images/closedhandcursor_48.png
new file mode 100644
index 0000000000..e63031605e
--- /dev/null
+++ b/src/plugins/platforms/windows/images/closedhandcursor_48.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/closedhandcursor_64.png b/src/plugins/platforms/windows/images/closedhandcursor_64.png
new file mode 100644
index 0000000000..438680ed4e
--- /dev/null
+++ b/src/plugins/platforms/windows/images/closedhandcursor_64.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/dragcopycursor_32.png b/src/plugins/platforms/windows/images/dragcopycursor_32.png
new file mode 100644
index 0000000000..f40ac6a600
--- /dev/null
+++ b/src/plugins/platforms/windows/images/dragcopycursor_32.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/dragcopycursor_48.png b/src/plugins/platforms/windows/images/dragcopycursor_48.png
new file mode 100644
index 0000000000..21ee467f46
--- /dev/null
+++ b/src/plugins/platforms/windows/images/dragcopycursor_48.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/dragcopycursor_64.png b/src/plugins/platforms/windows/images/dragcopycursor_64.png
new file mode 100644
index 0000000000..c49bcf33aa
--- /dev/null
+++ b/src/plugins/platforms/windows/images/dragcopycursor_64.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/draglinkcursor_32.png b/src/plugins/platforms/windows/images/draglinkcursor_32.png
new file mode 100644
index 0000000000..5efbce90d3
--- /dev/null
+++ b/src/plugins/platforms/windows/images/draglinkcursor_32.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/draglinkcursor_48.png b/src/plugins/platforms/windows/images/draglinkcursor_48.png
new file mode 100644
index 0000000000..51205101b1
--- /dev/null
+++ b/src/plugins/platforms/windows/images/draglinkcursor_48.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/draglinkcursor_64.png b/src/plugins/platforms/windows/images/draglinkcursor_64.png
new file mode 100644
index 0000000000..55eb0e313a
--- /dev/null
+++ b/src/plugins/platforms/windows/images/draglinkcursor_64.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/dragmovecursor_32.png b/src/plugins/platforms/windows/images/dragmovecursor_32.png
new file mode 100644
index 0000000000..32781a15ff
--- /dev/null
+++ b/src/plugins/platforms/windows/images/dragmovecursor_32.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/dragmovecursor_48.png b/src/plugins/platforms/windows/images/dragmovecursor_48.png
new file mode 100644
index 0000000000..6b15af6e84
--- /dev/null
+++ b/src/plugins/platforms/windows/images/dragmovecursor_48.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/dragmovecursor_64.png b/src/plugins/platforms/windows/images/dragmovecursor_64.png
new file mode 100644
index 0000000000..e9e4ece29f
--- /dev/null
+++ b/src/plugins/platforms/windows/images/dragmovecursor_64.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/openhandcursor_32.png b/src/plugins/platforms/windows/images/openhandcursor_32.png
new file mode 100644
index 0000000000..a6948d48f7
--- /dev/null
+++ b/src/plugins/platforms/windows/images/openhandcursor_32.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/openhandcursor_48.png b/src/plugins/platforms/windows/images/openhandcursor_48.png
new file mode 100644
index 0000000000..e8beb8d29d
--- /dev/null
+++ b/src/plugins/platforms/windows/images/openhandcursor_48.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/openhandcursor_64.png b/src/plugins/platforms/windows/images/openhandcursor_64.png
new file mode 100644
index 0000000000..d12e3a7283
--- /dev/null
+++ b/src/plugins/platforms/windows/images/openhandcursor_64.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/splithcursor_32.png b/src/plugins/platforms/windows/images/splithcursor_32.png
new file mode 100644
index 0000000000..1ad479eddf
--- /dev/null
+++ b/src/plugins/platforms/windows/images/splithcursor_32.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/splithcursor_48.png b/src/plugins/platforms/windows/images/splithcursor_48.png
new file mode 100644
index 0000000000..bf59b9cdca
--- /dev/null
+++ b/src/plugins/platforms/windows/images/splithcursor_48.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/splithcursor_64.png b/src/plugins/platforms/windows/images/splithcursor_64.png
new file mode 100644
index 0000000000..b857458671
--- /dev/null
+++ b/src/plugins/platforms/windows/images/splithcursor_64.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/splitvcursor_32.png b/src/plugins/platforms/windows/images/splitvcursor_32.png
new file mode 100644
index 0000000000..ebb55ae2e1
--- /dev/null
+++ b/src/plugins/platforms/windows/images/splitvcursor_32.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/splitvcursor_48.png b/src/plugins/platforms/windows/images/splitvcursor_48.png
new file mode 100644
index 0000000000..5408920652
--- /dev/null
+++ b/src/plugins/platforms/windows/images/splitvcursor_48.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/splitvcursor_64.png b/src/plugins/platforms/windows/images/splitvcursor_64.png
new file mode 100644
index 0000000000..7f09a40c01
--- /dev/null
+++ b/src/plugins/platforms/windows/images/splitvcursor_64.png
Binary files differ
diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h
index ee640224cf..3992f2d297 100644
--- a/src/plugins/platforms/windows/qtwindowsglobal.h
+++ b/src/plugins/platforms/windows/qtwindowsglobal.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -117,6 +117,14 @@ enum WindowsEventType // Simplify event types
UnknownEvent = 542
};
+// Matches Process_DPI_Awareness (Windows 8.1 onwards), used for SetProcessDpiAwareness()
+enum ProcessDpiAwareness
+{
+ ProcessDpiUnaware,
+ ProcessSystemDpiAware,
+ ProcessPerMonitorDpiAware
+};
+
} // namespace QtWindows
inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamIn)
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.h b/src/plugins/platforms/windows/qwindowsbackingstore.h
index 758f6c941f..e19b8a4db1 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.h
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.h
@@ -59,11 +59,11 @@ public:
QWindowsBackingStore(QWindow *window);
~QWindowsBackingStore();
- virtual QPaintDevice *paintDevice();
- virtual void flush(QWindow *window, const QRegion &region, const QPoint &offset);
- virtual void resize(const QSize &size, const QRegion &r);
- virtual bool scroll(const QRegion &area, int dx, int dy);
- virtual void beginPaint(const QRegion &);
+ QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
+ void flush(QWindow *window, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
+ void resize(const QSize &size, const QRegion &r) Q_DECL_OVERRIDE;
+ bool scroll(const QRegion &area, int dx, int dy) Q_DECL_OVERRIDE;
+ void beginPaint(const QRegion &) Q_DECL_OVERRIDE;
HDC getDC() const;
diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp
index dcfeba12fa..e43b524aa8 100644
--- a/src/plugins/platforms/windows/qwindowsclipboard.cpp
+++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -145,7 +145,7 @@ static void cleanClipboardPostRoutine()
QWindowsClipboard *QWindowsClipboard::m_instance = 0;
QWindowsClipboard::QWindowsClipboard() :
- m_data(0), m_clipboardViewer(0), m_nextClipboardViewer(0)
+ m_data(0), m_clipboardViewer(0), m_nextClipboardViewer(0), m_formatListenerRegistered(false)
{
QWindowsClipboard::m_instance = this;
qAddPostRoutine(cleanClipboardPostRoutine);
@@ -178,20 +178,40 @@ void QWindowsClipboard::registerViewer()
m_clipboardViewer = QWindowsContext::instance()->
createDummyWindow(QStringLiteral("Qt5ClipboardView"), L"Qt5ClipboardView",
qClipboardViewerWndProc, WS_OVERLAPPED);
- m_nextClipboardViewer = SetClipboardViewer(m_clipboardViewer);
- qCDebug(lcQpaMime) << __FUNCTION__ << "m_clipboardViewer: " << m_clipboardViewer << "next: " << m_nextClipboardViewer;
+ // Try format listener API (Vista onwards) first.
+ if (QWindowsContext::user32dll.addClipboardFormatListener && QWindowsContext::user32dll.removeClipboardFormatListener) {
+ m_formatListenerRegistered = QWindowsContext::user32dll.addClipboardFormatListener(m_clipboardViewer);
+ if (!m_formatListenerRegistered)
+ qErrnoWarning("AddClipboardFormatListener() failed.");
+ }
+
+ if (!m_formatListenerRegistered)
+ m_nextClipboardViewer = SetClipboardViewer(m_clipboardViewer);
+
+ qCDebug(lcQpaMime) << __FUNCTION__ << "m_clipboardViewer:" << m_clipboardViewer
+ << "format listener:" << m_formatListenerRegistered
+ << "next:" << m_nextClipboardViewer;
}
void QWindowsClipboard::unregisterViewer()
{
if (m_clipboardViewer) {
- ChangeClipboardChain(m_clipboardViewer, m_nextClipboardViewer);
+ if (m_formatListenerRegistered) {
+ QWindowsContext::user32dll.removeClipboardFormatListener(m_clipboardViewer);
+ m_formatListenerRegistered = false;
+ } else {
+ ChangeClipboardChain(m_clipboardViewer, m_nextClipboardViewer);
+ m_nextClipboardViewer = 0;
+ }
DestroyWindow(m_clipboardViewer);
- m_clipboardViewer = m_nextClipboardViewer = 0;
+ m_clipboardViewer = 0;
}
}
+// ### FIXME: Qt 6: Remove the clipboard chain handling code and make the
+// format listener the default.
+
static bool isProcessBeingDebugged(HWND hwnd)
{
DWORD pid = 0;
@@ -232,6 +252,8 @@ void QWindowsClipboard::propagateClipboardMessage(UINT message, WPARAM wParam, L
bool QWindowsClipboard::clipboardViewerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result)
{
+ enum { wMClipboardUpdate = 0x031D };
+
*result = 0;
if (QWindowsContext::verbose)
qCDebug(lcQpaMime) << __FUNCTION__ << hwnd << message << QWindowsGuiEventDispatcher::windowsMessageName(message);
@@ -246,14 +268,16 @@ bool QWindowsClipboard::clipboardViewerWndProc(HWND hwnd, UINT message, WPARAM w
}
}
return true;
- case WM_DRAWCLIPBOARD: {
+ case wMClipboardUpdate: // Clipboard Format listener (Vista onwards)
+ case WM_DRAWCLIPBOARD: { // Clipboard Viewer Chain handling (up to XP)
const bool owned = ownsClipboard();
qCDebug(lcQpaMime) << "Clipboard changed owned " << owned;
emitChanged(QClipboard::Clipboard);
// clean up the clipboard object if we no longer own the clipboard
if (!owned && m_data)
releaseIData();
- propagateClipboardMessage(message, wParam, lParam);
+ if (!m_formatListenerRegistered)
+ propagateClipboardMessage(message, wParam, lParam);
}
return true;
case WM_DESTROY:
diff --git a/src/plugins/platforms/windows/qwindowsclipboard.h b/src/plugins/platforms/windows/qwindowsclipboard.h
index 30bc0143f4..a3e9da7f3f 100644
--- a/src/plugins/platforms/windows/qwindowsclipboard.h
+++ b/src/plugins/platforms/windows/qwindowsclipboard.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -54,8 +54,8 @@ class QWindowsClipboardRetrievalMimeData : public QWindowsInternalMimeData {
public:
protected:
- virtual IDataObject *retrieveDataObject() const;
- virtual void releaseDataObject(IDataObject *) const;
+ IDataObject *retrieveDataObject() const Q_DECL_OVERRIDE;
+ void releaseDataObject(IDataObject *) const Q_DECL_OVERRIDE;
};
class QWindowsClipboard : public QPlatformClipboard
@@ -66,10 +66,10 @@ public:
void registerViewer(); // Call in initialization, when context is up.
void cleanup();
- virtual QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard);
- virtual void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard);
- virtual bool supportsMode(QClipboard::Mode mode) const;
- virtual bool ownsMode(QClipboard::Mode mode) const;
+ QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE;
+ void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE;
+ bool supportsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE;
+ bool ownsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE;
inline bool clipboardViewerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result);
@@ -88,6 +88,7 @@ private:
QWindowsOleDataObject *m_data;
HWND m_clipboardViewer;
HWND m_nextClipboardViewer;
+ bool m_formatListenerRegistered;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index f2f285f0f6..322bae10aa 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -191,7 +191,8 @@ QWindowsUser32DLL::QWindowsUser32DLL() :
updateLayeredWindowIndirect(0),
isHungAppWindow(0),
registerTouchWindow(0), unregisterTouchWindow(0),
- getTouchInputInfo(0), closeTouchInputHandle(0), setProcessDPIAware(0)
+ getTouchInputInfo(0), closeTouchInputHandle(0), setProcessDPIAware(0),
+ addClipboardFormatListener(0), removeClipboardFormatListener(0)
{
}
@@ -207,6 +208,11 @@ void QWindowsUser32DLL::init()
updateLayeredWindowIndirect = (UpdateLayeredWindowIndirect)(library.resolve("UpdateLayeredWindowIndirect"));
isHungAppWindow = (IsHungAppWindow)library.resolve("IsHungAppWindow");
setProcessDPIAware = (SetProcessDPIAware)library.resolve("SetProcessDPIAware");
+
+ if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA) {
+ addClipboardFormatListener = (AddClipboardFormatListener)library.resolve("AddClipboardFormatListener");
+ removeClipboardFormatListener = (RemoveClipboardFormatListener)library.resolve("RemoveClipboardFormatListener");
+ }
}
bool QWindowsUser32DLL::initTouch()
@@ -247,8 +253,26 @@ void QWindowsShell32DLL::init()
sHGetImageList = (SHGetImageList)library.resolve("SHGetImageList");
}
+QWindowsShcoreDLL::QWindowsShcoreDLL()
+ : getProcessDpiAwareness(0)
+ , setProcessDpiAwareness(0)
+ , getDpiForMonitor(0)
+{
+}
+
+void QWindowsShcoreDLL::init()
+{
+ if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS8_1)
+ return;
+ QSystemLibrary library(QStringLiteral("SHCore"));
+ getProcessDpiAwareness = (GetProcessDpiAwareness)library.resolve("GetProcessDpiAwareness");
+ setProcessDpiAwareness = (SetProcessDpiAwareness)library.resolve("SetProcessDpiAwareness");
+ getDpiForMonitor = (GetDpiForMonitor)library.resolve("GetDpiForMonitor");
+}
+
QWindowsUser32DLL QWindowsContext::user32dll;
QWindowsShell32DLL QWindowsContext::shell32dll;
+QWindowsShcoreDLL QWindowsContext::shcoredll;
#endif // !Q_OS_WINCE
@@ -299,9 +323,7 @@ QWindowsContextPrivate::QWindowsContextPrivate()
#ifndef Q_OS_WINCE
QWindowsContext::user32dll.init();
QWindowsContext::shell32dll.init();
- // Ensure metrics functions report correct data, QTBUG-30063.
- if (QWindowsContext::user32dll.setProcessDPIAware)
- QWindowsContext::user32dll.setProcessDPIAware();
+ QWindowsContext::shcoredll.init();
if (hasTouchSupport(ver) && QWindowsContext::user32dll.initTouch())
m_systemInfo |= QWindowsContext::SI_SupportsTouch;
@@ -358,6 +380,25 @@ void QWindowsContext::setTabletAbsoluteRange(int a)
#endif
}
+void QWindowsContext::setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness)
+{
+#ifndef Q_OS_WINCE
+ qCDebug(lcQpaWindows) << __FUNCTION__ << dpiAwareness;
+ if (QWindowsContext::shcoredll.isValid()) {
+ const HRESULT hr = QWindowsContext::shcoredll.setProcessDpiAwareness(dpiAwareness);
+ if (FAILED(hr))
+ qWarning() << "SetProcessDpiAwareness failed:" << QWindowsContext::comErrorString(hr);
+ } else {
+ if (dpiAwareness != QtWindows::ProcessDpiUnaware && QWindowsContext::user32dll.setProcessDPIAware) {
+ if (!QWindowsContext::user32dll.setProcessDPIAware())
+ qErrnoWarning("SetProcessDPIAware() failed");
+ }
+ }
+#else // !Q_OS_WINCE
+ Q_UNUSED(dpiAwareness)
+#endif
+}
+
QWindowsContext *QWindowsContext::instance()
{
return m_instance;
@@ -419,9 +460,17 @@ QString QWindowsContext::registerWindowClass(const QWindow *w, bool isGL)
&& (type == Qt::Popup || w->property("_q_windowsDropShadow").toBool())) {
style |= CS_DROPSHADOW;
}
- if (type == Qt::Tool || type == Qt::ToolTip || type == Qt::Popup) {
+ switch (type) {
+ case Qt::Tool:
+ case Qt::ToolTip:
+ case Qt::Popup:
style |= CS_SAVEBITS; // Save/restore background
icon = false;
+ break;
+ case Qt::Dialog:
+ if (!(flags & Qt::WindowSystemMenuHint))
+ icon = false; // QTBUG-2027, dialogs without system menu.
+ break;
}
// Create a unique name for the flag combination
QString cname = QStringLiteral("Qt5QWindow");
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index f5dbd072c7..086b968255 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -94,6 +94,8 @@ struct QWindowsUser32DLL
typedef BOOL (WINAPI *UpdateLayeredWindowIndirect)(HWND, const UPDATELAYEREDWINDOWINFO *);
typedef BOOL (WINAPI *IsHungAppWindow)(HWND);
typedef BOOL (WINAPI *SetProcessDPIAware)();
+ typedef BOOL (WINAPI *AddClipboardFormatListener)(HWND);
+ typedef BOOL (WINAPI *RemoveClipboardFormatListener)(HWND);
// Functions missing in Q_CC_GNU stub libraries.
SetLayeredWindowAttributes setLayeredWindowAttributes;
@@ -111,6 +113,10 @@ struct QWindowsUser32DLL
// Windows Vista onwards
SetProcessDPIAware setProcessDPIAware;
+
+ // Clipboard listeners, Windows Vista onwards
+ AddClipboardFormatListener addClipboardFormatListener;
+ RemoveClipboardFormatListener removeClipboardFormatListener;
};
struct QWindowsShell32DLL
@@ -126,6 +132,22 @@ struct QWindowsShell32DLL
SHGetStockIconInfo sHGetStockIconInfo;
SHGetImageList sHGetImageList;
};
+
+// Shell scaling library (Windows 8.1 onwards)
+struct QWindowsShcoreDLL {
+ QWindowsShcoreDLL();
+ void init();
+ inline bool isValid() const { return getProcessDpiAwareness && setProcessDpiAwareness && getDpiForMonitor; }
+
+ typedef HRESULT (WINAPI *GetProcessDpiAwareness)(HANDLE,int);
+ typedef HRESULT (WINAPI *SetProcessDpiAwareness)(int);
+ typedef HRESULT (WINAPI *GetDpiForMonitor)(HMONITOR,int,UINT *,UINT *);
+
+ GetProcessDpiAwareness getProcessDpiAwareness;
+ SetProcessDpiAwareness setProcessDpiAwareness;
+ GetDpiForMonitor getDpiForMonitor;
+};
+
#endif // Q_OS_WINCE
class QWindowsContext
@@ -184,6 +206,7 @@ public:
void setWindowCreationContext(const QSharedPointer<QWindowCreationContext> &ctx);
void setTabletAbsoluteRange(int a);
+ void setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness);
// Returns a combination of SystemInfoFlags
unsigned systemInfo() const;
@@ -197,6 +220,7 @@ public:
#ifndef Q_OS_WINCE
static QWindowsUser32DLL user32dll;
static QWindowsShell32DLL shell32dll;
+ static QWindowsShcoreDLL shcoredll;
#endif
static QByteArray comErrorString(HRESULT hr);
diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp
index d8fb104b3c..8352dac0b6 100644
--- a/src/plugins/platforms/windows/qwindowscursor.cpp
+++ b/src/plugins/platforms/windows/qwindowscursor.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -98,7 +98,7 @@ QWindowsCursorCacheKey::QWindowsCursorCacheKey(const QCursor &c)
\sa QWindowsWindowCursor
*/
-HCURSOR QWindowsCursor::createPixmapCursor(const QPixmap &pixmap, int hotX, int hotY)
+HCURSOR QWindowsCursor::createPixmapCursor(const QPixmap &pixmap, const QPoint &hotSpot)
{
HCURSOR cur = 0;
QBitmap mask = pixmap.mask();
@@ -112,8 +112,8 @@ HCURSOR QWindowsCursor::createPixmapCursor(const QPixmap &pixmap, int hotX, int
ICONINFO ii;
ii.fIcon = 0;
- ii.xHotspot = hotX;
- ii.yHotspot = hotY;
+ ii.xHotspot = hotSpot.x();
+ ii.yHotspot = hotSpot.y();
ii.hbmMask = im;
ii.hbmColor = ic;
@@ -124,20 +124,120 @@ HCURSOR QWindowsCursor::createPixmapCursor(const QPixmap &pixmap, int hotX, int
return cur;
}
-HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c)
+// Create a cursor from image and mask of the format QImage::Format_Mono.
+static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits,
+ QPoint hotSpot = QPoint(),
+ bool invb = false, bool invm = false)
{
- int hx = c.hotSpot().x();
- int hy = c.hotSpot().y();
- const Qt::CursorShape cshape = c.shape();
- if (cshape == Qt::BitmapCursor) {
- const QPixmap pixmap = c.pixmap();
- if (!pixmap.isNull())
- if (const HCURSOR hc = createPixmapCursor(pixmap, hx, hy))
- return hc;
+ const int width = bbits.width();
+ const int height = bbits.height();
+ if (hotSpot.isNull())
+ hotSpot = QPoint(width / 2, height / 2);
+ const int n = qMax(1, width / 8);
+#if !defined(Q_OS_WINCE)
+ QScopedArrayPointer<uchar> xBits(new uchar[height * n]);
+ QScopedArrayPointer<uchar> xMask(new uchar[height * n]);
+ int x = 0;
+ for (int i = 0; i < height; ++i) {
+ const uchar *bits = bbits.scanLine(i);
+ const uchar *mask = mbits.scanLine(i);
+ for (int j = 0; j < n; ++j) {
+ uchar b = bits[j];
+ uchar m = mask[j];
+ if (invb)
+ b ^= 0xff;
+ if (invm)
+ m ^= 0xff;
+ xBits[x] = ~m;
+ xMask[x] = b ^ m;
+ ++x;
+ }
+ }
+ return CreateCursor(GetModuleHandle(0), hotSpot.x(), hotSpot.y(), width, height,
+ xBits.data(), xMask.data());
+#elif defined(GWES_ICONCURS) // Q_OS_WINCE
+ // Windows CE only supports fixed cursor size.
+ int sysW = GetSystemMetrics(SM_CXCURSOR);
+ int sysH = GetSystemMetrics(SM_CYCURSOR);
+ int sysN = qMax(1, sysW / 8);
+ uchar* xBits = new uchar[sysH * sysN];
+ uchar* xMask = new uchar[sysH * sysN];
+ int x = 0;
+ for (int i = 0; i < sysH; ++i) {
+ if (i >= height) {
+ memset(&xBits[x] , 255, sysN);
+ memset(&xMask[x] , 0, sysN);
+ x += sysN;
+ } else {
+ int fillWidth = n > sysN ? sysN : n;
+ const uchar *bits = bbits.scanLine(i);
+ const uchar *mask = mbits.scanLine(i);
+ for (int j = 0; j < fillWidth; ++j) {
+ uchar b = bits[j];
+ uchar m = mask[j];
+ if (invb)
+ b ^= 0xFF;
+ if (invm)
+ m ^= 0xFF;
+ xBits[x] = ~m;
+ xMask[x] = b ^ m;
+ ++x;
+ }
+ for (int j = fillWidth; j < sysN; ++j ) {
+ xBits[x] = 255;
+ xMask[x] = 0;
+ ++x;
+ }
+ }
}
- // Non-standard Windows cursors are created from bitmaps
+ HCURSOR hcurs = CreateCursor(qWinAppInst(), hotSpot.x(), hotSpot.y(), sysW, sysH,
+ xBits, xMask);
+ delete [] xBits;
+ delete [] xMask;
+ return hcurs;
+#else
+ Q_UNUSED(n);
+ Q_UNUSED(invm);
+ Q_UNUSED(invb);
+ Q_UNUSED(mbits);
+ return 0;
+#endif
+}
+static inline QSize systemCursorSize() { return QSize(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR)); }
+static inline QSize standardCursorSize() { return QSize(32, 32); }
+
+#if defined (Q_OS_WINCE) || defined (QT_NO_IMAGEFORMAT_PNG)
+// Create pixmap cursors from data and scale the image if the cursor size is
+// higher than the standard 32. Note that bitmap cursors as produced by
+// createBitmapCursor() only work for standard sizes (32,48,64...), which does
+// not work when scaling the 16x16 openhand cursor bitmaps to 150% (resulting
+// in a non-standard 24x24 size).
+static QCursor createPixmapCursorFromData(const QSize &systemCursorSize,
+ // The cursor size the bitmap is targeted for
+ const QSize &bitmapTargetCursorSize,
+ // The actual size of the bitmap data
+ int bitmapSize, const uchar *bits,
+ const uchar *maskBits)
+{
+ QPixmap rawImage = QPixmap::fromImage(QBitmap::fromData(QSize(bitmapSize, bitmapSize), bits).toImage());
+ rawImage.setMask(QBitmap::fromData(QSize(bitmapSize, bitmapSize), maskBits));
+
+ const qreal factor = qreal(systemCursorSize.width()) / qreal(bitmapTargetCursorSize.width());
+ // Scale images if the cursor size is significantly different, starting with 150% where the system cursor
+ // size is 48.
+ if (qAbs(factor - 1.0) > 0.4) {
+ const QTransform transform = QTransform::fromScale(factor, factor);
+ rawImage = rawImage.transformed(transform, Qt::SmoothTransformation);
+ }
+ const QPoint hotSpot(rawImage.width() / 2, rawImage.height() / 2);
+ return QCursor(rawImage, hotSpot.x(), hotSpot.y());
+}
+
+QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
+{
+ // Non-standard Windows cursors are created from bitmaps
static const uchar vsplit_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -203,171 +303,250 @@ HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c)
0xf0,0x7f,0xf8,0x7f,0xfc,0x7f,0xfc,0x3f,0xf8,0x3f,0xf0,0x1f,
0xe0,0x1f,0xe0,0x1f,0x00,0x00,0x00,0x00};
- wchar_t *sh = 0;
- switch (c.shape()) { // map to windows cursor
- case Qt::ArrowCursor:
- sh = IDC_ARROW;
- break;
- case Qt::UpArrowCursor:
- sh = IDC_UPARROW;
- break;
- case Qt::CrossCursor:
- sh = IDC_CROSS;
- break;
- case Qt::WaitCursor:
- sh = IDC_WAIT;
- break;
- case Qt::IBeamCursor:
- sh = IDC_IBEAM;
- break;
- case Qt::SizeVerCursor:
- sh = IDC_SIZENS;
- break;
- case Qt::SizeHorCursor:
- sh = IDC_SIZEWE;
- break;
- case Qt::SizeBDiagCursor:
- sh = IDC_SIZENESW;
- break;
- case Qt::SizeFDiagCursor:
- sh = IDC_SIZENWSE;
- break;
- case Qt::SizeAllCursor:
- sh = IDC_SIZEALL;
- break;
- case Qt::ForbiddenCursor:
- sh = IDC_NO;
- break;
- case Qt::WhatsThisCursor:
- sh = IDC_HELP;
- break;
- case Qt::BusyCursor:
- sh = IDC_APPSTARTING;
- break;
- case Qt::PointingHandCursor:
- sh = IDC_HAND;
- break;
- case Qt::BlankCursor:
+ static const char * const moveDragCursorXpmC[] = {
+ "11 20 3 1",
+ ". c None",
+ "a c #FFFFFF",
+ "X c #000000", // X11 cursor is traditionally black
+ "aa.........",
+ "aXa........",
+ "aXXa.......",
+ "aXXXa......",
+ "aXXXXa.....",
+ "aXXXXXa....",
+ "aXXXXXXa...",
+ "aXXXXXXXa..",
+ "aXXXXXXXXa.",
+ "aXXXXXXXXXa",
+ "aXXXXXXaaaa",
+ "aXXXaXXa...",
+ "aXXaaXXa...",
+ "aXa..aXXa..",
+ "aa...aXXa..",
+ "a.....aXXa.",
+ "......aXXa.",
+ ".......aXXa",
+ ".......aXXa",
+ "........aa."};
+
+ static const char * const copyDragCursorXpmC[] = {
+ "24 30 3 1",
+ ". c None",
+ "a c #000000",
+ "X c #FFFFFF",
+ "XX......................",
+ "XaX.....................",
+ "XaaX....................",
+ "XaaaX...................",
+ "XaaaaX..................",
+ "XaaaaaX.................",
+ "XaaaaaaX................",
+ "XaaaaaaaX...............",
+ "XaaaaaaaaX..............",
+ "XaaaaaaaaaX.............",
+ "XaaaaaaXXXX.............",
+ "XaaaXaaX................",
+ "XaaXXaaX................",
+ "XaX..XaaX...............",
+ "XX...XaaX...............",
+ "X.....XaaX..............",
+ "......XaaX..............",
+ ".......XaaX.............",
+ ".......XaaX.............",
+ "........XX...aaaaaaaaaaa",
+ ".............aXXXXXXXXXa",
+ ".............aXXXXXXXXXa",
+ ".............aXXXXaXXXXa",
+ ".............aXXXXaXXXXa",
+ ".............aXXaaaaaXXa",
+ ".............aXXXXaXXXXa",
+ ".............aXXXXaXXXXa",
+ ".............aXXXXXXXXXa",
+ ".............aXXXXXXXXXa",
+ ".............aaaaaaaaaaa"};
+
+ static const char * const linkDragCursorXpmC[] = {
+ "24 30 3 1",
+ ". c None",
+ "a c #000000",
+ "X c #FFFFFF",
+ "XX......................",
+ "XaX.....................",
+ "XaaX....................",
+ "XaaaX...................",
+ "XaaaaX..................",
+ "XaaaaaX.................",
+ "XaaaaaaX................",
+ "XaaaaaaaX...............",
+ "XaaaaaaaaX..............",
+ "XaaaaaaaaaX.............",
+ "XaaaaaaXXXX.............",
+ "XaaaXaaX................",
+ "XaaXXaaX................",
+ "XaX..XaaX...............",
+ "XX...XaaX...............",
+ "X.....XaaX..............",
+ "......XaaX..............",
+ ".......XaaX.............",
+ ".......XaaX.............",
+ "........XX...aaaaaaaaaaa",
+ ".............aXXXXXXXXXa",
+ ".............aXXXaaaaXXa",
+ ".............aXXXXaaaXXa",
+ ".............aXXXaaaaXXa",
+ ".............aXXaaaXaXXa",
+ ".............aXXaaXXXXXa",
+ ".............aXXaXXXXXXa",
+ ".............aXXXaXXXXXa",
+ ".............aXXXXXXXXXa",
+ ".............aaaaaaaaaaa"};
+
+ switch (cursorShape) {
case Qt::SplitVCursor:
+ return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 32, vsplit_bits, vsplitm_bits);
case Qt::SplitHCursor:
+ return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 32, hsplit_bits, hsplitm_bits);
case Qt::OpenHandCursor:
+ return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 16, openhand_bits, openhandm_bits);
case Qt::ClosedHandCursor:
- case Qt::BitmapCursor: {
- QImage bbits, mbits;
- bool invb, invm;
- if (cshape == Qt::BlankCursor) {
- bbits = QImage(32, 32, QImage::Format_Mono);
- bbits.fill(0); // ignore color table
- mbits = bbits.copy();
- hx = hy = 16;
- invb = invm = false;
- } else if (cshape == Qt::OpenHandCursor || cshape == Qt::ClosedHandCursor) {
- bool open = cshape == Qt::OpenHandCursor;
- QBitmap cb = QBitmap::fromData(QSize(16, 16), open ? openhand_bits : closedhand_bits);
- QBitmap cm = QBitmap::fromData(QSize(16, 16), open ? openhandm_bits : closedhandm_bits);
- bbits = cb.toImage().convertToFormat(QImage::Format_Mono);
- mbits = cm.toImage().convertToFormat(QImage::Format_Mono);
- hx = hy = 8;
- invb = invm = false;
- } else if (cshape == Qt::BitmapCursor) {
- bbits = c.bitmap()->toImage().convertToFormat(QImage::Format_Mono);
- mbits = c.mask()->toImage().convertToFormat(QImage::Format_Mono);
- invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1));
- invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1));
- } else { // Qt::SplitVCursor, Qt::SplitHCursor
- const QBitmap cb = QBitmap::fromData(QSize(32, 32), cshape == Qt::SplitVCursor ? vsplit_bits : hsplit_bits);
- const QBitmap cm = QBitmap::fromData(QSize(32, 32), cshape == Qt::SplitVCursor ? vsplitm_bits : hsplitm_bits);
- bbits = cb.toImage().convertToFormat(QImage::Format_Mono);
- mbits = cm.toImage().convertToFormat(QImage::Format_Mono);
- hx = hy = 16;
- invb = invm = false;
- }
- const int n = qMax(1, bbits.width() / 8);
- const int h = bbits.height();
-#if !defined(Q_OS_WINCE)
- QScopedArrayPointer<uchar> xBits(new uchar[h * n]);
- QScopedArrayPointer<uchar> xMask(new uchar[h * n]);
- int x = 0;
- for (int i = 0; i < h; ++i) {
- uchar *bits = bbits.scanLine(i);
- uchar *mask = mbits.scanLine(i);
- for (int j = 0; j < n; ++j) {
- uchar b = bits[j];
- uchar m = mask[j];
- if (invb)
- b ^= 0xff;
- if (invm)
- m ^= 0xff;
- xBits[x] = ~m;
- xMask[x] = b ^ m;
- ++x;
- }
- }
- return CreateCursor(GetModuleHandle(0), hx, hy, bbits.width(), bbits.height(),
- xBits.data(), xMask.data());
-#elif defined(GWES_ICONCURS) // Q_WS_WINCE
- // Windows CE only supports fixed cursor size.
- int sysW = GetSystemMetrics(SM_CXCURSOR);
- int sysH = GetSystemMetrics(SM_CYCURSOR);
- int sysN = qMax(1, sysW / 8);
- uchar* xBits = new uchar[sysH * sysN];
- uchar* xMask = new uchar[sysH * sysN];
- int x = 0;
- for (int i = 0; i < sysH; ++i) {
- if (i >= h) {
- memset(&xBits[x] , 255, sysN);
- memset(&xMask[x] , 0, sysN);
- x += sysN;
- } else {
- int fillWidth = n > sysN ? sysN : n;
- uchar *bits = bbits.scanLine(i);
- uchar *mask = mbits.scanLine(i);
- for (int j = 0; j < fillWidth; ++j) {
- uchar b = bits[j];
- uchar m = mask[j];
- if (invb)
- b ^= 0xFF;
- if (invm)
- m ^= 0xFF;
- xBits[x] = ~m;
- xMask[x] = b ^ m;
- ++x;
- }
- for (int j = fillWidth; j < sysN; ++j ) {
- xBits[x] = 255;
- xMask[x] = 0;
- ++x;
- }
- }
+ return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 16, closedhand_bits, closedhandm_bits);
+ case Qt::DragCopyCursor:
+ return QCursor(QPixmap(copyDragCursorXpmC), 0, 0);
+ case Qt::DragMoveCursor:
+ return QCursor(QPixmap(moveDragCursorXpmC), 0, 0);
+ case Qt::DragLinkCursor:
+ return QCursor(QPixmap(linkDragCursorXpmC), 0, 0);
+ }
+
+ return QCursor();
+}
+#else // Q_OS_WINCE || QT_NO_IMAGEFORMAT_PNG
+struct QWindowsCustomPngCursor {
+ Qt::CursorShape shape;
+ int size;
+ const char *fileName;
+ int hotSpotX;
+ int hotSpotY;
+};
+
+QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
+{
+ static const QWindowsCustomPngCursor pngCursors[] = {
+ { Qt::SplitVCursor, 32, "splitvcursor_32.png", 11, 11 },
+ { Qt::SplitVCursor, 48, "splitvcursor_48.png", 16, 17 },
+ { Qt::SplitVCursor, 64, "splitvcursor_64.png", 22, 22 },
+ { Qt::SplitHCursor, 32, "splithcursor_32.png", 11, 11 },
+ { Qt::SplitHCursor, 48, "splithcursor_48.png", 16, 17 },
+ { Qt::SplitHCursor, 64, "splithcursor_64.png", 22, 22 },
+ { Qt::OpenHandCursor, 32, "openhandcursor_32.png", 10, 12 },
+ { Qt::OpenHandCursor, 48, "openhandcursor_48.png", 15, 16 },
+ { Qt::OpenHandCursor, 64, "openhandcursor_64.png", 20, 24 },
+ { Qt::ClosedHandCursor, 32, "closedhandcursor_32.png", 10, 12 },
+ { Qt::ClosedHandCursor, 48, "closedhandcursor_48.png", 15, 16 },
+ { Qt::ClosedHandCursor, 64, "closedhandcursor_64.png", 20, 24 },
+ { Qt::DragCopyCursor, 32, "dragcopycursor_32.png", 0, 0 },
+ { Qt::DragCopyCursor, 48, "dragcopycursor_48.png", 0, 0 },
+ { Qt::DragCopyCursor, 64, "dragcopycursor_64.png", 0, 0 },
+ { Qt::DragMoveCursor, 32, "dragmovecursor_32.png", 0, 0 },
+ { Qt::DragMoveCursor, 48, "dragmovecursor_48.png", 0, 0 },
+ { Qt::DragMoveCursor, 64, "dragmovecursor_64.png", 0, 0 },
+ { Qt::DragLinkCursor, 32, "draglinkcursor_32.png", 0, 0 },
+ { Qt::DragLinkCursor, 48, "draglinkcursor_48.png", 0, 0 },
+ { Qt::DragLinkCursor, 64, "draglinkcursor_64.png", 0, 0 }
+ };
+
+ const int cursorSize = GetSystemMetrics(SM_CXCURSOR);
+ const QWindowsCustomPngCursor *sEnd = pngCursors + sizeof(pngCursors) / sizeof(pngCursors[0]);
+ const QWindowsCustomPngCursor *bestFit = 0;
+ int sizeDelta = INT_MAX;
+ for (const QWindowsCustomPngCursor *s = pngCursors; s < sEnd; ++s) {
+ if (s->shape != cursorShape)
+ continue;
+ const int currentSizeDelta = qMax(s->size, cursorSize) - qMin(s->size, cursorSize);
+ if (currentSizeDelta < sizeDelta) {
+ bestFit = s;
+ if (currentSizeDelta == 0)
+ break; // Perfect match found
+ sizeDelta = currentSizeDelta;
}
+ }
- HCURSOR hcurs = CreateCursor(qWinAppInst(), hx, hy, sysW, sysH,
- xBits, xMask);
- delete [] xBits;
- delete [] xMask;
- return hcurs;
-#else
- Q_UNUSED(n);
- Q_UNUSED(h);
- return 0;
-#endif
+ if (!bestFit)
+ return QCursor();
+ const QPixmap rawImage(QStringLiteral(":/qt-project.org/windows/cursors/images/") +
+ QString::fromLatin1(bestFit->fileName));
+ return QCursor(rawImage, bestFit->hotSpotX, bestFit->hotSpotY);
+}
+#endif // Q_OS_WINCE || QT_NO_IMAGEFORMAT_PNG
+
+struct QWindowsStandardCursorMapping {
+ Qt::CursorShape shape;
+ LPCWSTR resource;
+};
+
+HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c)
+{
+ static const QWindowsStandardCursorMapping standardCursors[] = {
+ { Qt::ArrowCursor, IDC_ARROW},
+ { Qt::UpArrowCursor, IDC_UPARROW },
+ { Qt::CrossCursor, IDC_CROSS },
+ { Qt::WaitCursor, IDC_WAIT },
+ { Qt::IBeamCursor, IDC_IBEAM },
+ { Qt::SizeVerCursor, IDC_SIZENS },
+ { Qt::SizeHorCursor, IDC_SIZEWE },
+ { Qt::SizeBDiagCursor, IDC_SIZENESW },
+ { Qt::SizeFDiagCursor, IDC_SIZENWSE },
+ { Qt::SizeAllCursor, IDC_SIZEALL },
+ { Qt::ForbiddenCursor, IDC_NO },
+ { Qt::WhatsThisCursor, IDC_HELP },
+ { Qt::BusyCursor, IDC_APPSTARTING },
+ { Qt::PointingHandCursor, IDC_HAND }
+ };
+
+ const Qt::CursorShape cursorShape = c.shape();
+ switch (cursorShape) {
+ case Qt::BitmapCursor: {
+ const QPixmap pixmap = c.pixmap();
+ if (!pixmap.isNull())
+ return QWindowsCursor::createPixmapCursor(pixmap, c.hotSpot());
+ const QImage bbits = c.bitmap()->toImage().convertToFormat(QImage::Format_Mono);
+ const QImage mbits = c.mask()->toImage().convertToFormat(QImage::Format_Mono);
+ const bool invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1));
+ const bool invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1));
+ return createBitmapCursor(bbits, mbits, c.hotSpot(), invb, invm);
}
+ case Qt::BlankCursor: {
+ QImage blank = QImage(systemCursorSize(), QImage::Format_Mono);
+ blank.fill(0); // ignore color table
+ return createBitmapCursor(blank, blank);
+ }
+ case Qt::SplitVCursor:
+ case Qt::SplitHCursor:
+ case Qt::OpenHandCursor:
+ case Qt::ClosedHandCursor:
case Qt::DragCopyCursor:
case Qt::DragMoveCursor:
- case Qt::DragLinkCursor: {
- const QPixmap pixmap = QGuiApplicationPrivate::instance()->getPixmapCursor(cshape);
- return createPixmapCursor(pixmap, hx, hy);
- }
+ case Qt::DragLinkCursor:
+ return createSystemCursor(customCursor(cursorShape));
default:
- qWarning("%s: Invalid cursor shape %d", __FUNCTION__, cshape);
- return 0;
+ break;
}
-#ifdef Q_OS_WINCE
- return LoadCursor(0, sh);
+
+ // Load available standard cursors from resources
+ const QWindowsStandardCursorMapping *sEnd = standardCursors + sizeof(standardCursors) / sizeof(standardCursors[0]);
+ for (const QWindowsStandardCursorMapping *s = standardCursors; s < sEnd; ++s) {
+ if (s->shape == cursorShape) {
+#ifndef Q_OS_WINCE
+ return (HCURSOR)LoadImage(0, s->resource, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
#else
- return (HCURSOR)LoadImage(0, sh, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
+ return LoadCursor(0, s->resource);
#endif
+ }
+ }
+
+ qWarning("%s: Invalid cursor shape %d", __FUNCTION__, cursorShape);
+ return 0;
}
/*!
diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h
index 31da4e367d..34cb668856 100644
--- a/src/plugins/platforms/windows/qwindowscursor.h
+++ b/src/plugins/platforms/windows/qwindowscursor.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -101,12 +101,13 @@ public:
QWindowsCursor() {}
- virtual void changeCursor(QCursor * widgetCursor, QWindow * widget);
- virtual QPoint pos() const { return mousePosition(); }
- virtual void setPos(const QPoint &pos);
+ void changeCursor(QCursor * widgetCursor, QWindow * widget) Q_DECL_OVERRIDE;
+ QPoint pos() const Q_DECL_OVERRIDE { return mousePosition(); }
+ void setPos(const QPoint &pos) Q_DECL_OVERRIDE;
- static HCURSOR createPixmapCursor(const QPixmap &pixmap, int hotX, int hotY);
+ static HCURSOR createPixmapCursor(const QPixmap &pixmap, const QPoint &hotSpot);
static HCURSOR createSystemCursor(const QCursor &c);
+ static QCursor customCursor(Qt::CursorShape cursorShape);
static QPoint mousePosition();
static CursorState cursorState();
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.h b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
index bcf9f544b5..864c9e40f5 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.h
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
@@ -71,11 +71,11 @@ public:
typedef QSharedPointer<QWindowsNativeDialogBase> QWindowsNativeDialogBasePtr;
~QWindowsDialogHelperBase() { cleanupThread(); }
- virtual void exec();
+ void exec() Q_DECL_OVERRIDE;
virtual bool show(Qt::WindowFlags windowFlags,
Qt::WindowModality windowModality,
QWindow *parent);
- virtual void hide();
+ void hide() Q_DECL_OVERRIDE;
virtual bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const { return true; }
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
index 60c3daff23..861ddbe5b6 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
@@ -69,146 +69,6 @@
QT_BEGIN_NAMESPACE
-// These pixmaps approximate the images in the Windows User Interface Guidelines.
-// XPM
-
-static const char * const moveDragCursorXpmC[] = {
-"11 20 3 1",
-". c None",
-"a c #FFFFFF",
-"X c #000000", // X11 cursor is traditionally black
-"aa.........",
-"aXa........",
-"aXXa.......",
-"aXXXa......",
-"aXXXXa.....",
-"aXXXXXa....",
-"aXXXXXXa...",
-"aXXXXXXXa..",
-"aXXXXXXXXa.",
-"aXXXXXXXXXa",
-"aXXXXXXaaaa",
-"aXXXaXXa...",
-"aXXaaXXa...",
-"aXa..aXXa..",
-"aa...aXXa..",
-"a.....aXXa.",
-"......aXXa.",
-".......aXXa",
-".......aXXa",
-"........aa."};
-
-
-/* XPM */
-static const char * const copyDragCursorXpmC[] = {
-"24 30 3 1",
-". c None",
-"a c #000000",
-"X c #FFFFFF",
-"XX......................",
-"XaX.....................",
-"XaaX....................",
-"XaaaX...................",
-"XaaaaX..................",
-"XaaaaaX.................",
-"XaaaaaaX................",
-"XaaaaaaaX...............",
-"XaaaaaaaaX..............",
-"XaaaaaaaaaX.............",
-"XaaaaaaXXXX.............",
-"XaaaXaaX................",
-"XaaXXaaX................",
-"XaX..XaaX...............",
-"XX...XaaX...............",
-"X.....XaaX..............",
-"......XaaX..............",
-".......XaaX.............",
-".......XaaX.............",
-"........XX...aaaaaaaaaaa",
-".............aXXXXXXXXXa",
-".............aXXXXXXXXXa",
-".............aXXXXaXXXXa",
-".............aXXXXaXXXXa",
-".............aXXaaaaaXXa",
-".............aXXXXaXXXXa",
-".............aXXXXaXXXXa",
-".............aXXXXXXXXXa",
-".............aXXXXXXXXXa",
-".............aaaaaaaaaaa"};
-
-/* XPM */
-static const char * const linkDragCursorXpmC[] = {
-"24 30 3 1",
-". c None",
-"a c #000000",
-"X c #FFFFFF",
-"XX......................",
-"XaX.....................",
-"XaaX....................",
-"XaaaX...................",
-"XaaaaX..................",
-"XaaaaaX.................",
-"XaaaaaaX................",
-"XaaaaaaaX...............",
-"XaaaaaaaaX..............",
-"XaaaaaaaaaX.............",
-"XaaaaaaXXXX.............",
-"XaaaXaaX................",
-"XaaXXaaX................",
-"XaX..XaaX...............",
-"XX...XaaX...............",
-"X.....XaaX..............",
-"......XaaX..............",
-".......XaaX.............",
-".......XaaX.............",
-"........XX...aaaaaaaaaaa",
-".............aXXXXXXXXXa",
-".............aXXXaaaaXXa",
-".............aXXXXaaaXXa",
-".............aXXXaaaaXXa",
-".............aXXaaaXaXXa",
-".............aXXaaXXXXXa",
-".............aXXaXXXXXXa",
-".............aXXXaXXXXXa",
-".............aXXXXXXXXXa",
-".............aaaaaaaaaaa"};
-
-static const char * const ignoreDragCursorXpmC[] = {
-"24 30 3 1",
-". c None",
-"a c #000000",
-"X c #FFFFFF",
-"aa......................",
-"aXa.....................",
-"aXXa....................",
-"aXXXa...................",
-"aXXXXa..................",
-"aXXXXXa.................",
-"aXXXXXXa................",
-"aXXXXXXXa...............",
-"aXXXXXXXXa..............",
-"aXXXXXXXXXa.............",
-"aXXXXXXaaaa.............",
-"aXXXaXXa................",
-"aXXaaXXa................",
-"aXa..aXXa...............",
-"aa...aXXa...............",
-"a.....aXXa..............",
-"......aXXa.....XXXX.....",
-".......aXXa..XXaaaaXX...",
-".......aXXa.XaaaaaaaaX..",
-"........aa.XaaaXXXXaaaX.",
-"...........XaaaaX..XaaX.",
-"..........XaaXaaaX..XaaX",
-"..........XaaXXaaaX.XaaX",
-"..........XaaX.XaaaXXaaX",
-"..........XaaX..XaaaXaaX",
-"...........XaaX..XaaaaX.",
-"...........XaaaXXXXaaaX.",
-"............XaaaaaaaaX..",
-".............XXaaaaXX...",
-"...............XXXX....."};
-
/*!
\class QWindowsDragCursorWindow
\brief A toplevel window showing the drag icon in case of touch drag.
@@ -490,7 +350,7 @@ void QWindowsOleDropSource::createCursors()
newHotSpot = QPoint(qMax(0, hotSpot.x()), qMax(0, hotSpot.y()));
}
- if (const HCURSOR sysCursor = QWindowsCursor::createPixmapCursor(newPixmap, newHotSpot.x(), newHotSpot.y())) {
+ if (const HCURSOR sysCursor = QWindowsCursor::createPixmapCursor(newPixmap, newHotSpot)) {
const CursorEntry entry(newPixmap, cacheKey, DragCursorHandlePtr(new DragCursorHandle(sysCursor)), newHotSpot);
if (it == m_cursors.end())
m_cursors.insert(action, entry);
@@ -864,22 +724,86 @@ QPixmap QWindowsDrag::defaultCursor(Qt::DropAction action) const
switch (action) {
case Qt::CopyAction:
if (m_copyDragCursor.isNull())
- m_copyDragCursor = QPixmap(copyDragCursorXpmC);
+ m_copyDragCursor = QWindowsCursor::customCursor(Qt::DragCopyCursor).pixmap();
return m_copyDragCursor;
case Qt::TargetMoveAction:
case Qt::MoveAction:
if (m_moveDragCursor.isNull())
- m_moveDragCursor = QPixmap(moveDragCursorXpmC);
+ m_moveDragCursor = QWindowsCursor::customCursor(Qt::DragMoveCursor).pixmap();
return m_moveDragCursor;
case Qt::LinkAction:
if (m_linkDragCursor.isNull())
- m_linkDragCursor = QPixmap(linkDragCursorXpmC);
+ m_linkDragCursor = QWindowsCursor::customCursor(Qt::DragLinkCursor).pixmap();
return m_linkDragCursor;
default:
break;
}
- if (m_ignoreDragCursor.isNull())
+
+ static const char * const ignoreDragCursorXpmC[] = {
+ "24 30 3 1",
+ ". c None",
+ "a c #000000",
+ "X c #FFFFFF",
+ "aa......................",
+ "aXa.....................",
+ "aXXa....................",
+ "aXXXa...................",
+ "aXXXXa..................",
+ "aXXXXXa.................",
+ "aXXXXXXa................",
+ "aXXXXXXXa...............",
+ "aXXXXXXXXa..............",
+ "aXXXXXXXXXa.............",
+ "aXXXXXXaaaa.............",
+ "aXXXaXXa................",
+ "aXXaaXXa................",
+ "aXa..aXXa...............",
+ "aa...aXXa...............",
+ "a.....aXXa..............",
+ "......aXXa.....XXXX.....",
+ ".......aXXa..XXaaaaXX...",
+ ".......aXXa.XaaaaaaaaX..",
+ "........aa.XaaaXXXXaaaX.",
+ "...........XaaaaX..XaaX.",
+ "..........XaaXaaaX..XaaX",
+ "..........XaaXXaaaX.XaaX",
+ "..........XaaX.XaaaXXaaX",
+ "..........XaaX..XaaaXaaX",
+ "...........XaaX..XaaaaX.",
+ "...........XaaaXXXXaaaX.",
+ "............XaaaaaaaaX..",
+ ".............XXaaaaXX...",
+ "...............XXXX....."};
+
+ if (m_ignoreDragCursor.isNull()) {
+#if !defined (Q_OS_WINCE)
+ HCURSOR cursor = LoadCursor(NULL, IDC_NO);
+ ICONINFO iconInfo = {0, 0, 0, 0, 0};
+ GetIconInfo(cursor, &iconInfo);
+ BITMAP bmColor = {0, 0, 0, 0, 0, 0, 0};
+
+ if (iconInfo.hbmColor
+ && GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bmColor)
+ && bmColor.bmWidth == bmColor.bmWidthBytes / 4) {
+ const int colorBitsLength = bmColor.bmHeight * bmColor.bmWidthBytes;
+ uchar *colorBits = new uchar[colorBitsLength];
+ GetBitmapBits(iconInfo.hbmColor, colorBitsLength, colorBits);
+ const QImage colorImage(colorBits, bmColor.bmWidth, bmColor.bmHeight,
+ bmColor.bmWidthBytes, QImage::Format_ARGB32);
+
+ m_ignoreDragCursor = QPixmap::fromImage(colorImage);
+ delete [] colorBits;
+ } else {
+ m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC);
+ }
+
+ DeleteObject(iconInfo.hbmMask);
+ DeleteObject(iconInfo.hbmColor);
+ DestroyCursor(cursor);
+#else // !Q_OS_WINCE
m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC);
+#endif // !Q_OS_WINCE
+ }
return m_ignoreDragCursor;
}
diff --git a/src/plugins/platforms/windows/qwindowsdrag.h b/src/plugins/platforms/windows/qwindowsdrag.h
index 4f758fbf3f..b4d303a10f 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.h
+++ b/src/plugins/platforms/windows/qwindowsdrag.h
@@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE
class QWindowsDropMimeData : public QWindowsInternalMimeData {
public:
QWindowsDropMimeData() {}
- virtual IDataObject *retrieveDataObject() const;
+ IDataObject *retrieveDataObject() const Q_DECL_OVERRIDE;
};
class QWindowsOleDropTarget : public IDropTarget
@@ -90,9 +90,9 @@ public:
QWindowsDrag();
virtual ~QWindowsDrag();
- virtual QMimeData *platformDropData() { return &m_dropData; }
+ QMimeData *platformDropData() Q_DECL_OVERRIDE { return &m_dropData; }
- virtual Qt::DropAction drag(QDrag *drag);
+ Qt::DropAction drag(QDrag *drag) Q_DECL_OVERRIDE;
static QWindowsDrag *instance();
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
index d5ca06bb3f..3fdfb55dcf 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -46,23 +46,297 @@
#include <QtCore/QDebug>
#include <QtGui/QOpenGLContext>
-#include <QtPlatformSupport/private/qeglconvenience_p.h>
-
QT_BEGIN_NAMESPACE
/*!
\class QWindowsEGLStaticContext
\brief Static data for QWindowsEGLContext.
- Keeps the display. The class is shared via
- QSharedPointer in the windows, the contexts
- and in QWindowsIntegration. The display will
- be closed if the last instance is deleted.
+ Keeps the display. The class is shared via QSharedPointer in the windows, the
+ contexts and in QWindowsIntegration. The display will be closed if the last instance
+ is deleted.
+
+ No EGL or OpenGL functions are called directly. Instead, they are resolved
+ dynamically. This works even if the plugin links directly to libegl/libglesv2 so
+ there is no need to differentiate between dynamic or Angle-only builds in here.
\internal
\ingroup qt-lighthouse-win
*/
+QWindowsLibEGL QWindowsEGLStaticContext::libEGL;
+QWindowsLibGLESv2 QWindowsEGLStaticContext::libGLESv2;
+
+#ifndef QT_STATIC
+
+#ifdef Q_CC_MINGW
+static void *resolveFunc(HMODULE lib, const char *name)
+{
+ QString baseNameStr = QString::fromLatin1(name);
+ QString nameStr;
+ void *proc = 0;
+
+ // Play nice with 32-bit mingw: Try func first, then func@0, func@4,
+ // func@8, func@12, ..., func@64. The def file does not provide any aliases
+ // in libEGL and libGLESv2 in these builds which results in exporting
+ // function names like eglInitialize@12. This cannot be fixed without
+ // breaking binary compatibility. So be flexible here instead.
+
+ int argSize = -1;
+ while (!proc && argSize <= 64) {
+ nameStr = baseNameStr;
+ if (argSize >= 0)
+ nameStr += QLatin1Char('@') + QString::number(argSize);
+ argSize = argSize < 0 ? 0 : argSize + 4;
+ proc = (void *) ::GetProcAddress(lib, nameStr.toLatin1().constData());
+ }
+ return proc;
+}
+#else
+static void *resolveFunc(HMODULE lib, const char *name)
+{
+# ifndef Q_OS_WINCE
+ return (void *) ::GetProcAddress(lib, name);
+# else
+ return (void *) ::GetProcAddress(lib, (const wchar_t *) QString::fromLatin1(name).utf16());
+# endif // Q_OS_WINCE
+}
+#endif // Q_CC_MINGW
+
+void *QWindowsLibEGL::resolve(const char *name)
+{
+ void *proc = m_lib ? resolveFunc(m_lib, name) : 0;
+ if (!proc)
+ qErrnoWarning(::GetLastError(), "Failed to resolve EGL function %s", name);
+
+ return proc;
+}
+
+#endif // !QT_STATIC
+
+#ifndef QT_STATIC
+# define RESOLVE(signature, name) signature(resolve( #name ));
+#else
+# define RESOLVE(signature, name) signature(&::name);
+#endif
+
+bool QWindowsLibEGL::init()
+{
+#ifdef QT_DEBUG
+ const char dllName[] = "libEGLd.dll";
+#else
+ const char dllName[] = "libEGL.dll";
+#endif
+
+ qCDebug(lcQpaGl) << "Qt: Using EGL from" << dllName;
+
+#ifndef QT_STATIC
+ m_lib = ::LoadLibraryW((const wchar_t *) QString::fromLatin1(dllName).utf16());
+ if (!m_lib) {
+ qErrnoWarning(::GetLastError(), "Failed to load %s", dllName);
+ return false;
+ }
+#endif
+
+ eglGetError = RESOLVE((EGLint (EGLAPIENTRY *)(void)), eglGetError);
+ eglGetDisplay = RESOLVE((EGLDisplay (EGLAPIENTRY *)(EGLNativeDisplayType)), eglGetDisplay);
+ eglInitialize = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, EGLint *, EGLint *)), eglInitialize);
+ eglTerminate = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay)), eglTerminate);
+ eglChooseConfig = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, const EGLint *, EGLConfig *, EGLint, EGLint *)), eglChooseConfig);
+ eglGetConfigAttrib = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, EGLConfig, EGLint, EGLint *)), eglGetConfigAttrib);
+ eglCreateWindowSurface = RESOLVE((EGLSurface (EGLAPIENTRY *)(EGLDisplay, EGLConfig, EGLNativeWindowType, const EGLint *)), eglCreateWindowSurface);
+ eglCreatePbufferSurface = RESOLVE((EGLSurface (EGLAPIENTRY *)(EGLDisplay , EGLConfig, const EGLint *)), eglCreatePbufferSurface);
+ eglDestroySurface = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface )), eglDestroySurface);
+ eglBindAPI = RESOLVE((EGLBoolean (EGLAPIENTRY * )(EGLenum )), eglBindAPI);
+ eglSwapInterval = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLint )), eglSwapInterval);
+ eglCreateContext = RESOLVE((EGLContext (EGLAPIENTRY *)(EGLDisplay , EGLConfig , EGLContext , const EGLint *)), eglCreateContext);
+ eglDestroyContext = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, EGLContext)), eglDestroyContext);
+ eglMakeCurrent = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface , EGLSurface , EGLContext )), eglMakeCurrent);
+ eglGetCurrentContext = RESOLVE((EGLContext (EGLAPIENTRY *)(void)), eglGetCurrentContext);
+ eglGetCurrentSurface = RESOLVE((EGLSurface (EGLAPIENTRY *)(EGLint )), eglGetCurrentSurface);
+ eglGetCurrentDisplay = RESOLVE((EGLDisplay (EGLAPIENTRY *)(void)), eglGetCurrentDisplay);
+ eglSwapBuffers = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface)), eglSwapBuffers);
+ eglGetProcAddress = RESOLVE((__eglMustCastToProperFunctionPointerType (EGLAPIENTRY * )(const char *)), eglGetProcAddress);
+
+ return eglGetError && eglGetDisplay && eglInitialize;
+}
+
+#ifndef QT_STATIC
+void *QWindowsLibGLESv2::resolve(const char *name)
+{
+ void *proc = m_lib ? resolveFunc(m_lib, name) : 0;
+ if (!proc)
+ qWarning() << "Failed to resolve OpenGL ES function" << name;
+
+ return proc;
+}
+#endif // !QT_STATIC
+
+bool QWindowsLibGLESv2::init()
+{
+#ifdef QT_DEBUG
+ const char dllName[] = "libGLESv2d.dll";
+#else
+ const char dllName[] = "libGLESv2.dll";
+#endif
+
+ qCDebug(lcQpaGl) << "Qt: Using OpenGL ES 2.0 from" << dllName;
+#ifndef QT_STATIC
+ m_lib = ::LoadLibraryW((const wchar_t *) QString::fromLatin1(dllName).utf16());
+ if (!m_lib) {
+ qErrnoWarning(::GetLastError(), "Failed to load %s", dllName);
+ return false;
+ }
+#endif // !QT_STATIC
+
+ glBindTexture = RESOLVE((void (APIENTRY *)(GLenum , GLuint )), glBindTexture);
+ glBlendFunc = RESOLVE((void (APIENTRY *)(GLenum , GLenum )), glBlendFunc);
+ glClear = RESOLVE((void (APIENTRY *)(GLbitfield )), glClear);
+ glClearColor = RESOLVE((void (APIENTRY *)(GLfloat , GLfloat , GLfloat , GLfloat )), glClearColor);
+ glClearStencil = RESOLVE((void (APIENTRY *)(GLint )), glClearStencil);
+ glColorMask = RESOLVE((void (APIENTRY *)(GLboolean , GLboolean , GLboolean , GLboolean )), glColorMask);
+ glCopyTexImage2D = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLenum , GLint , GLint , GLsizei , GLsizei , GLint )), glCopyTexImage2D);
+ glCopyTexSubImage2D = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLint , GLint , GLint , GLint , GLsizei , GLsizei )), glCopyTexSubImage2D);
+ glCullFace = RESOLVE((void (APIENTRY *)(GLenum )), glCullFace);
+ glDeleteTextures = RESOLVE((void (APIENTRY *)(GLsizei , const GLuint *)), glDeleteTextures);
+ glDepthFunc = RESOLVE((void (APIENTRY *)(GLenum )), glDepthFunc);
+ glDepthMask = RESOLVE((void (APIENTRY *)(GLboolean )), glDepthMask);
+ glDisable = RESOLVE((void (APIENTRY *)(GLenum )), glDisable);
+ glDrawArrays = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLsizei )), glDrawArrays);
+ glDrawElements = RESOLVE((void (APIENTRY *)(GLenum , GLsizei , GLenum , const GLvoid *)), glDrawElements);
+ glEnable = RESOLVE((void (APIENTRY *)(GLenum )), glEnable);
+ glFinish = RESOLVE((void (APIENTRY *)()), glFinish);
+ glFlush = RESOLVE((void (APIENTRY *)()), glFlush);
+ glFrontFace = RESOLVE((void (APIENTRY *)(GLenum )), glFrontFace);
+ glGenTextures = RESOLVE((void (APIENTRY *)(GLsizei , GLuint *)), glGenTextures);
+ glGetBooleanv = RESOLVE((void (APIENTRY *)(GLenum , GLboolean *)), glGetBooleanv);
+ glGetError = RESOLVE((GLenum (APIENTRY *)()), glGetError);
+ glGetFloatv = RESOLVE((void (APIENTRY *)(GLenum , GLfloat *)), glGetFloatv);
+ glGetIntegerv = RESOLVE((void (APIENTRY *)(GLenum , GLint *)), glGetIntegerv);
+ glGetString = RESOLVE((const GLubyte * (APIENTRY *)(GLenum )), glGetString);
+ glGetTexParameterfv = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLfloat *)), glGetTexParameterfv);
+ glGetTexParameteriv = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLint *)), glGetTexParameteriv);
+ glHint = RESOLVE((void (APIENTRY *)(GLenum , GLenum )), glHint);
+ glIsEnabled = RESOLVE((GLboolean (APIENTRY *)(GLenum )), glIsEnabled);
+ glIsTexture = RESOLVE((GLboolean (APIENTRY *)(GLuint )), glIsTexture);
+ glLineWidth = RESOLVE((void (APIENTRY *)(GLfloat )), glLineWidth);
+ glPixelStorei = RESOLVE((void (APIENTRY *)(GLenum , GLint )), glPixelStorei);
+ glPolygonOffset = RESOLVE((void (APIENTRY *)(GLfloat , GLfloat )), glPolygonOffset);
+ glReadPixels = RESOLVE((void (APIENTRY *)(GLint , GLint , GLsizei , GLsizei , GLenum , GLenum , GLvoid *)), glReadPixels);
+ glScissor = RESOLVE((void (APIENTRY *)(GLint , GLint , GLsizei , GLsizei )), glScissor);
+ glStencilFunc = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLuint )), glStencilFunc);
+ glStencilMask = RESOLVE((void (APIENTRY *)(GLuint )), glStencilMask);
+ glStencilOp = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLenum )), glStencilOp);
+ glTexImage2D = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLint , GLsizei , GLsizei , GLint , GLenum , GLenum , const GLvoid *)), glTexImage2D);
+ glTexParameterf = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLfloat )), glTexParameterf);
+ glTexParameterfv = RESOLVE((void (APIENTRY *)(GLenum , GLenum , const GLfloat *)), glTexParameterfv);
+ glTexParameteri = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLint )), glTexParameteri);
+ glTexParameteriv = RESOLVE((void (APIENTRY *)(GLenum , GLenum , const GLint *)), glTexParameteriv);
+ glTexSubImage2D = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLint , GLint , GLsizei , GLsizei , GLenum , GLenum , const GLvoid *)), glTexSubImage2D);
+ glViewport = RESOLVE((void (APIENTRY *)(GLint , GLint , GLsizei , GLsizei )), glViewport);
+
+ glActiveTexture = RESOLVE((void (APIENTRY *)(GLenum)), glActiveTexture);
+ glAttachShader = RESOLVE((void (APIENTRY *)(GLuint , GLuint )), glAttachShader);
+ glBindAttribLocation = RESOLVE((void (APIENTRY *)(GLuint , GLuint , const GLchar* )), glBindAttribLocation);
+ glBindBuffer = RESOLVE((void (APIENTRY *)(GLenum , GLuint )), glBindBuffer);
+ glBindFramebuffer = RESOLVE((void (APIENTRY *)(GLenum , GLuint )), glBindFramebuffer);
+ glBindRenderbuffer = RESOLVE((void (APIENTRY *)(GLenum , GLuint )), glBindRenderbuffer);
+ glBlendColor = RESOLVE((void (APIENTRY *)(GLclampf , GLclampf , GLclampf , GLclampf )), glBlendColor);
+ glBlendEquation = RESOLVE((void (APIENTRY *)(GLenum )), glBlendEquation);
+ glBlendEquationSeparate = RESOLVE((void (APIENTRY *)(GLenum , GLenum )), glBlendEquationSeparate);
+ glBlendFuncSeparate = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLenum , GLenum )), glBlendFuncSeparate);
+ glBufferData = RESOLVE((void (APIENTRY *)(GLenum , qopengl_GLsizeiptr , const GLvoid* , GLenum )), glBufferData);
+ glBufferSubData = RESOLVE((void (APIENTRY *)(GLenum , qopengl_GLintptr , qopengl_GLsizeiptr , const GLvoid* )), glBufferSubData);
+ glCheckFramebufferStatus = RESOLVE((GLenum (APIENTRY *)(GLenum )), glCheckFramebufferStatus);
+ glCompileShader = RESOLVE((void (APIENTRY *)(GLuint )), glCompileShader);
+ glCompressedTexImage2D = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLenum , GLsizei , GLsizei, GLint, GLsizei, const GLvoid* )), glCompressedTexImage2D);
+ glCompressedTexSubImage2D = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLint , GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid* )), glCompressedTexSubImage2D);
+ glCreateProgram = RESOLVE((GLuint (APIENTRY *)(void)), glCreateProgram);
+ glCreateShader = RESOLVE((GLuint (APIENTRY *)(GLenum )), glCreateShader);
+ glDeleteBuffers = RESOLVE((void (APIENTRY *)(GLsizei , const GLuint*)), glDeleteBuffers);
+ glDeleteFramebuffers = RESOLVE((void (APIENTRY *)(GLsizei , const GLuint* )), glDeleteFramebuffers);
+ glDeleteProgram = RESOLVE((void (APIENTRY *)(GLuint )), glDeleteProgram);
+ glDeleteRenderbuffers = RESOLVE((void (APIENTRY *)(GLsizei , const GLuint* )), glDeleteRenderbuffers);
+ glDeleteShader = RESOLVE((void (APIENTRY *)(GLuint )), glDeleteShader);
+ glDetachShader = RESOLVE((void (APIENTRY *)(GLuint , GLuint )), glDetachShader);
+ glDisableVertexAttribArray = RESOLVE((void (APIENTRY *)(GLuint )), glDisableVertexAttribArray);
+ glEnableVertexAttribArray = RESOLVE((void (APIENTRY *)(GLuint )), glEnableVertexAttribArray);
+ glFramebufferRenderbuffer = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLenum , GLuint )), glFramebufferRenderbuffer);
+ glFramebufferTexture2D = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLenum , GLuint , GLint )), glFramebufferTexture2D);
+ glGenBuffers = RESOLVE((void (APIENTRY *)(GLsizei , GLuint* )), glGenBuffers);
+ glGenerateMipmap = RESOLVE((void (APIENTRY *)(GLenum )), glGenerateMipmap);
+ glGenFramebuffers = RESOLVE((void (APIENTRY *)(GLsizei , GLuint* )), glGenFramebuffers);
+ glGenRenderbuffers = RESOLVE((void (APIENTRY *)(GLsizei , GLuint* )), glGenRenderbuffers);
+ glGetActiveAttrib = RESOLVE((void (APIENTRY *)(GLuint , GLuint , GLsizei , GLsizei* , GLint* , GLenum* , GLchar* )), glGetActiveAttrib);
+ glGetActiveUniform = RESOLVE((void (APIENTRY *)(GLuint , GLuint , GLsizei , GLsizei* , GLint* , GLenum* , GLchar* )), glGetActiveUniform);
+ glGetAttachedShaders = RESOLVE((void (APIENTRY *)(GLuint , GLsizei , GLsizei*, GLuint* )), glGetAttachedShaders);
+ glGetAttribLocation = RESOLVE((int (APIENTRY *)(GLuint , const GLchar* )), glGetAttribLocation);
+ glGetBufferParameteriv = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLint* )), glGetBufferParameteriv);
+ glGetFramebufferAttachmentParameteriv = RESOLVE((void (APIENTRY *)(GLenum , GLenum, GLenum , GLint* )), glGetFramebufferAttachmentParameteriv);
+ glGetProgramiv = RESOLVE((void (APIENTRY *)(GLuint , GLenum , GLint* )), glGetProgramiv);
+ glGetProgramInfoLog = RESOLVE((void (APIENTRY *)(GLuint , GLsizei , GLsizei* , GLchar* )), glGetProgramInfoLog);
+ glGetRenderbufferParameteriv = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLint* )), glGetRenderbufferParameteriv);
+ glGetShaderiv = RESOLVE((void (APIENTRY *)(GLuint , GLenum , GLint* )), glGetShaderiv);
+ glGetShaderInfoLog = RESOLVE((void (APIENTRY *)(GLuint , GLsizei , GLsizei*, GLchar*)), glGetShaderInfoLog);
+ glGetShaderPrecisionFormat = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLint* , GLint* )), glGetShaderPrecisionFormat);
+ glGetShaderSource = RESOLVE((void (APIENTRY *)(GLuint , GLsizei , GLsizei* , GLchar* )), glGetShaderSource);
+ glGetUniformfv = RESOLVE((void (APIENTRY *)(GLuint , GLint , GLfloat*)), glGetUniformfv);
+ glGetUniformiv = RESOLVE((void (APIENTRY *)(GLuint , GLint , GLint*)), glGetUniformiv);
+ glGetUniformLocation = RESOLVE((int (APIENTRY *)(GLuint , const GLchar* )), glGetUniformLocation);
+ glGetVertexAttribfv = RESOLVE((void (APIENTRY *)(GLuint , GLenum , GLfloat* )), glGetVertexAttribfv);
+ glGetVertexAttribiv = RESOLVE((void (APIENTRY *)(GLuint , GLenum , GLint* )), glGetVertexAttribiv);
+ glGetVertexAttribPointerv = RESOLVE((void (APIENTRY *)(GLuint , GLenum , GLvoid** pointer)), glGetVertexAttribPointerv);
+ glIsBuffer = RESOLVE((GLboolean (APIENTRY *)(GLuint )), glIsBuffer);
+ glIsFramebuffer = RESOLVE((GLboolean (APIENTRY *)(GLuint )), glIsFramebuffer);
+ glIsProgram = RESOLVE((GLboolean (APIENTRY *)(GLuint )), glIsProgram);
+ glIsRenderbuffer = RESOLVE((GLboolean (APIENTRY *)(GLuint )), glIsRenderbuffer);
+ glIsShader = RESOLVE((GLboolean (APIENTRY *)(GLuint )), glIsShader);
+ glLinkProgram = RESOLVE((void (APIENTRY *)(GLuint )), glLinkProgram);
+ glReleaseShaderCompiler = RESOLVE((void (APIENTRY *)(void)), glReleaseShaderCompiler);
+ glRenderbufferStorage = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLsizei , GLsizei )), glRenderbufferStorage);
+ glSampleCoverage = RESOLVE((void (APIENTRY *)(GLclampf , GLboolean )), glSampleCoverage);
+ glShaderBinary = RESOLVE((void (APIENTRY *)(GLsizei , const GLuint*, GLenum , const GLvoid* , GLsizei )), glShaderBinary);
+ glShaderSource = RESOLVE((void (APIENTRY *)(GLuint , GLsizei , const GLchar* *, const GLint* )), glShaderSource);
+ glStencilFuncSeparate = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLint , GLuint )), glStencilFuncSeparate);
+ glStencilMaskSeparate = RESOLVE((void (APIENTRY *)(GLenum , GLuint )), glStencilMaskSeparate);
+ glStencilOpSeparate = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLenum , GLenum )), glStencilOpSeparate);
+ glUniform1f = RESOLVE((void (APIENTRY *)(GLint , GLfloat )), glUniform1f);
+ glUniform1fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLfloat* )), glUniform1fv);
+ glUniform1i = RESOLVE((void (APIENTRY *)(GLint , GLint )), glUniform1i);
+ glUniform1iv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLint* )), glUniform1iv);
+ glUniform2f = RESOLVE((void (APIENTRY *)(GLint , GLfloat , GLfloat )), glUniform2f);
+ glUniform2fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLfloat* )), glUniform2fv);
+ glUniform2i = RESOLVE((void (APIENTRY *)(GLint , GLint , GLint )), glUniform2i);
+ glUniform2iv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLint* )), glUniform2iv);
+ glUniform3f = RESOLVE((void (APIENTRY *)(GLint , GLfloat , GLfloat , GLfloat )), glUniform3f);
+ glUniform3fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLfloat* )), glUniform3fv);
+ glUniform3i = RESOLVE((void (APIENTRY *)(GLint , GLint , GLint , GLint )), glUniform3i);
+ glUniform3iv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLint* )), glUniform3iv);
+ glUniform4f = RESOLVE((void (APIENTRY *)(GLint , GLfloat , GLfloat , GLfloat , GLfloat )), glUniform4f);
+ glUniform4fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLfloat* )), glUniform4fv);
+ glUniform4i = RESOLVE((void (APIENTRY *)(GLint , GLint , GLint , GLint , GLint )), glUniform4i);
+ glUniform4iv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLint* )), glUniform4iv);
+ glUniformMatrix2fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , GLboolean , const GLfloat* )), glUniformMatrix2fv);
+ glUniformMatrix3fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , GLboolean , const GLfloat* )), glUniformMatrix3fv);
+ glUniformMatrix4fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , GLboolean , const GLfloat* )), glUniformMatrix4fv);
+ glUseProgram = RESOLVE((void (APIENTRY *)(GLuint )), glUseProgram);
+ glValidateProgram = RESOLVE((void (APIENTRY *)(GLuint )), glValidateProgram);
+ glVertexAttrib1f = RESOLVE((void (APIENTRY *)(GLuint , GLfloat )), glVertexAttrib1f);
+ glVertexAttrib1fv = RESOLVE((void (APIENTRY *)(GLuint , const GLfloat* )), glVertexAttrib1fv);
+ glVertexAttrib2f = RESOLVE((void (APIENTRY *)(GLuint , GLfloat , GLfloat )), glVertexAttrib2f);
+ glVertexAttrib2fv = RESOLVE((void (APIENTRY *)(GLuint , const GLfloat* )), glVertexAttrib2fv);
+ glVertexAttrib3f = RESOLVE((void (APIENTRY *)(GLuint , GLfloat , GLfloat , GLfloat )), glVertexAttrib3f);
+ glVertexAttrib3fv = RESOLVE((void (APIENTRY *)(GLuint , const GLfloat* )), glVertexAttrib3fv);
+ glVertexAttrib4f = RESOLVE((void (APIENTRY *)(GLuint , GLfloat , GLfloat , GLfloat , GLfloat )), glVertexAttrib4f);
+ glVertexAttrib4fv = RESOLVE((void (APIENTRY *)(GLuint , const GLfloat* )), glVertexAttrib4fv);
+ glVertexAttribPointer = RESOLVE((void (APIENTRY *)(GLuint , GLint, GLenum, GLboolean, GLsizei, const GLvoid* )), glVertexAttribPointer);
+
+ glClearDepthf = RESOLVE((void (APIENTRY *)(GLclampf )), glClearDepthf);
+ glDepthRangef = RESOLVE((void (APIENTRY *)(GLclampf , GLclampf )), glDepthRangef);
+
+ return glBindTexture && glCreateShader && glClearDepthf;
+}
+
QWindowsEGLStaticContext::QWindowsEGLStaticContext(EGLDisplay display, int version)
: m_display(display), m_version(version)
{
@@ -76,7 +350,16 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create()
return 0;
}
- EGLDisplay display = eglGetDisplay((EGLNativeDisplayType)dc);
+ if (!libEGL.init()) {
+ qWarning("%s: Failed to load and resolve libEGL functions", Q_FUNC_INFO);
+ return 0;
+ }
+ if (!libGLESv2.init()) {
+ qWarning("%s: Failed to load and resolve libGLESv2 functions", Q_FUNC_INFO);
+ return 0;
+ }
+
+ EGLDisplay display = libEGL.eglGetDisplay((EGLNativeDisplayType)dc);
if (!display) {
qWarning("%s: Could not obtain EGL display", Q_FUNC_INFO);
return 0;
@@ -84,9 +367,11 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create()
EGLint major;
EGLint minor;
- if (!eglInitialize(display, &major, &minor)) {
- qWarning("%s: Could not initialize egl display: error %d\n",
- Q_FUNC_INFO, eglGetError());
+ if (!libEGL.eglInitialize(display, &major, &minor)) {
+ int err = libEGL.eglGetError();
+ qWarning("%s: Could not initialize EGL display: error 0x%x\n", Q_FUNC_INFO, err);
+ if (err == 0x3001)
+ qWarning("%s: When using ANGLE, check if d3dcompiler_4x.dll is available", Q_FUNC_INFO);
return 0;
}
@@ -97,7 +382,70 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create()
QWindowsEGLStaticContext::~QWindowsEGLStaticContext()
{
qCDebug(lcQpaGl) << __FUNCTION__ << "Releasing EGL display " << m_display;
- eglTerminate(m_display);
+ libEGL.eglTerminate(m_display);
+}
+
+QWindowsOpenGLContext *QWindowsEGLStaticContext::createContext(QOpenGLContext *context)
+{
+ return new QWindowsEGLContext(this, context->format(), context->shareHandle());
+}
+
+void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *nativeConfig)
+{
+ EGLSurface surface = libEGL.eglCreateWindowSurface(m_display, (EGLConfig) nativeConfig,
+ (EGLNativeWindowType) nativeWindow, 0);
+ if (surface == EGL_NO_SURFACE)
+ qWarning("%s: Could not create the EGL window surface: 0x%x\n", Q_FUNC_INFO, libEGL.eglGetError());
+
+ return surface;
+}
+
+void QWindowsEGLStaticContext::destroyWindowSurface(void *nativeSurface)
+{
+ libEGL.eglDestroySurface(m_display, (EGLSurface) nativeSurface);
+}
+
+QSurfaceFormat QWindowsEGLStaticContext::formatFromConfig(EGLDisplay display, EGLConfig config,
+ const QSurfaceFormat &referenceFormat)
+{
+ QSurfaceFormat format;
+ EGLint redSize = 0;
+ EGLint greenSize = 0;
+ EGLint blueSize = 0;
+ EGLint alphaSize = 0;
+ EGLint depthSize = 0;
+ EGLint stencilSize = 0;
+ EGLint sampleCount = 0;
+
+ libEGL.eglGetConfigAttrib(display, config, EGL_RED_SIZE, &redSize);
+ libEGL.eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &greenSize);
+ libEGL.eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blueSize);
+ libEGL.eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alphaSize);
+ libEGL.eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depthSize);
+ libEGL.eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &stencilSize);
+ libEGL.eglGetConfigAttrib(display, config, EGL_SAMPLES, &sampleCount);
+
+ format.setRenderableType(QSurfaceFormat::OpenGLES);
+ format.setVersion(referenceFormat.majorVersion(), referenceFormat.minorVersion());
+ format.setProfile(referenceFormat.profile());
+ format.setOptions(referenceFormat.options());
+
+ format.setRedBufferSize(redSize);
+ format.setGreenBufferSize(greenSize);
+ format.setBlueBufferSize(blueSize);
+ format.setAlphaBufferSize(alphaSize);
+ format.setDepthBufferSize(depthSize);
+ format.setStencilBufferSize(stencilSize);
+ format.setSamples(sampleCount);
+ format.setStereo(false);
+ format.setSwapInterval(referenceFormat.swapInterval());
+
+ // Clear the EGL error state because some of the above may
+ // have errored out because the attribute is not applicable
+ // to the surface type. Such errors don't matter.
+ libEGL.eglGetError();
+
+ return format;
}
/*!
@@ -121,40 +469,465 @@ QWindowsEGLStaticContext::~QWindowsEGLStaticContext()
\ingroup qt-lighthouse-win
*/
-QWindowsEGLContext::QWindowsEGLContext(const QWindowsEGLStaticContextPtr &staticContext,
+QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext,
const QSurfaceFormat &format,
QPlatformOpenGLContext *share)
- : QEGLPlatformContext(format, share, staticContext->display())
- , m_staticContext(staticContext)
+ : m_staticContext(staticContext)
+ , m_eglDisplay(staticContext->display())
+ , m_api(EGL_OPENGL_ES_API)
+ , m_swapInterval(-1)
{
+ if (!m_staticContext)
+ return;
+
+ m_eglConfig = chooseConfig(format);
+ m_format = m_staticContext->formatFromConfig(m_eglDisplay, m_eglConfig, format);
+ m_shareContext = share ? static_cast<QWindowsEGLContext *>(share)->m_eglContext : 0;
+
+ QVector<EGLint> contextAttrs;
+ contextAttrs.append(EGL_CONTEXT_CLIENT_VERSION);
+ contextAttrs.append(m_format.majorVersion());
+ contextAttrs.append(EGL_NONE);
+
+ QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
+ m_eglContext = QWindowsEGLStaticContext::libEGL.eglCreateContext(m_eglDisplay, m_eglConfig, m_shareContext, contextAttrs.constData());
+ if (m_eglContext == EGL_NO_CONTEXT && m_shareContext != EGL_NO_CONTEXT) {
+ m_shareContext = 0;
+ m_eglContext = QWindowsEGLStaticContext::libEGL.eglCreateContext(m_eglDisplay, m_eglConfig, 0, contextAttrs.constData());
+ }
+
+ if (m_eglContext == EGL_NO_CONTEXT) {
+ qWarning("QWindowsEGLContext: eglError: %x, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
+ return;
+ }
+
+ // Make the context current to ensure the GL version query works. This needs a surface too.
+ const EGLint pbufferAttributes[] = {
+ EGL_WIDTH, 1,
+ EGL_HEIGHT, 1,
+ EGL_LARGEST_PBUFFER, EGL_FALSE,
+ EGL_NONE
+ };
+ EGLSurface pbuffer = QWindowsEGLStaticContext::libEGL.eglCreatePbufferSurface(m_eglDisplay, m_eglConfig, pbufferAttributes);
+ if (pbuffer == EGL_NO_SURFACE)
+ return;
+
+ if (QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, pbuffer, pbuffer, m_eglContext)) {
+ const GLubyte *s = QWindowsEGLStaticContext::libGLESv2.glGetString(GL_VERSION);
+ if (s) {
+ QByteArray version = QByteArray(reinterpret_cast<const char *>(s));
+ int major, minor;
+ if (QPlatformOpenGLContext::parseOpenGLVersion(version, major, minor)) {
+ m_format.setMajorVersion(major);
+ m_format.setMinorVersion(minor);
+ }
+ }
+ m_format.setProfile(QSurfaceFormat::NoProfile);
+ m_format.setOptions(QSurfaceFormat::FormatOptions());
+ QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ }
+ QWindowsEGLStaticContext::libEGL.eglDestroySurface(m_eglDisplay, pbuffer);
}
QWindowsEGLContext::~QWindowsEGLContext()
{
+ if (m_eglContext != EGL_NO_CONTEXT) {
+ QWindowsEGLStaticContext::libEGL.eglDestroyContext(m_eglDisplay, m_eglContext);
+ m_eglContext = EGL_NO_CONTEXT;
+ }
}
-bool QWindowsEGLContext::hasThreadedOpenGLCapability()
+bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
{
- return false;
+ Q_ASSERT(surface->surface()->supportsOpenGL());
+
+ QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
+
+ QWindowsWindow *window = static_cast<QWindowsWindow *>(surface);
+ EGLSurface eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig));
+ Q_ASSERT(eglSurface);
+
+ // shortcut: on some GPUs, eglMakeCurrent is not a cheap operation
+ if (QWindowsEGLStaticContext::libEGL.eglGetCurrentContext() == m_eglContext &&
+ QWindowsEGLStaticContext::libEGL.eglGetCurrentDisplay() == m_eglDisplay &&
+ QWindowsEGLStaticContext::libEGL.eglGetCurrentSurface(EGL_READ) == eglSurface &&
+ QWindowsEGLStaticContext::libEGL.eglGetCurrentSurface(EGL_DRAW) == eglSurface) {
+ return true;
+ }
+
+ const bool ok = QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, eglSurface, eglSurface, m_eglContext);
+ if (ok) {
+ const int requestedSwapInterval = surface->format().swapInterval();
+ if (requestedSwapInterval >= 0 && m_swapInterval != requestedSwapInterval) {
+ m_swapInterval = requestedSwapInterval;
+ QWindowsEGLStaticContext::libEGL.eglSwapInterval(m_staticContext->display(), m_swapInterval);
+ }
+ } else {
+ qWarning("QWindowsEGLContext::makeCurrent: eglError: %x, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
+ }
+
+ return ok;
}
-EGLSurface QWindowsEGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
+void QWindowsEGLContext::doneCurrent()
{
- const QWindowsWindow *window = static_cast<const QWindowsWindow *>(surface);
- return window->eglSurfaceHandle();
+ QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
+ bool ok = QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (!ok)
+ qWarning("QWindowsEGLContext::doneCurrent: eglError: %d, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
}
-bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
+void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface)
{
- bool ok = false;
+ QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
QWindowsWindow *window = static_cast<QWindowsWindow *>(surface);
- if (EGLSurface eglSurface = window->ensureEglSurfaceHandle(m_staticContext, eglConfig())) {
- ok = eglMakeCurrent(eglDisplay(), eglSurface, eglSurface, eglContext());
- if (!ok)
- qWarning("%s: eglMakeCurrent() failed, eglError: 0x%x, this: %p \n",
- Q_FUNC_INFO, eglGetError(), this);
+ EGLSurface eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig));
+ Q_ASSERT(eglSurface);
+
+ bool ok = QWindowsEGLStaticContext::libEGL.eglSwapBuffers(m_eglDisplay, eglSurface);
+ if (!ok)
+ qWarning("QWindowsEGLContext::swapBuffers: eglError: %d, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
+}
+
+QFunctionPointer QWindowsEGLContext::getProcAddress(const QByteArray &procName)
+{
+ // We support AllGLFunctionsQueryable, which means this function must be able to
+ // return a function pointer for standard GLES2 functions too. These are not
+ // guaranteed to be queryable via eglGetProcAddress().
+ static struct StdFunc {
+ const char *name;
+ void *func;
+ } standardFuncs[] = {
+ { "glBindTexture", (void *) QWindowsEGLStaticContext::libGLESv2.glBindTexture },
+ { "glBlendFunc", (void *) QWindowsEGLStaticContext::libGLESv2.glBlendFunc },
+ { "glClear", (void *) QWindowsEGLStaticContext::libGLESv2.glClear },
+ { "glClearColor", (void *) QWindowsEGLStaticContext::libGLESv2.glClearColor },
+ { "glClearStencil", (void *) QWindowsEGLStaticContext::libGLESv2.glClearStencil },
+ { "glColorMask", (void *) QWindowsEGLStaticContext::libGLESv2.glColorMask },
+ { "glCopyTexImage2D", (void *) QWindowsEGLStaticContext::libGLESv2.glCopyTexImage2D },
+ { "glCopyTexSubImage2D", (void *) QWindowsEGLStaticContext::libGLESv2.glCopyTexSubImage2D },
+ { "glCullFace", (void *) QWindowsEGLStaticContext::libGLESv2.glCullFace },
+ { "glDeleteTextures", (void *) QWindowsEGLStaticContext::libGLESv2.glDeleteTextures },
+ { "glDepthFunc", (void *) QWindowsEGLStaticContext::libGLESv2.glDepthFunc },
+ { "glDepthMask", (void *) QWindowsEGLStaticContext::libGLESv2.glDepthMask },
+ { "glDisable", (void *) QWindowsEGLStaticContext::libGLESv2.glDisable },
+ { "glDrawArrays", (void *) QWindowsEGLStaticContext::libGLESv2.glDrawArrays },
+ { "glDrawElements", (void *) QWindowsEGLStaticContext::libGLESv2.glDrawElements },
+ { "glEnable", (void *) QWindowsEGLStaticContext::libGLESv2.glEnable },
+ { "glFinish", (void *) QWindowsEGLStaticContext::libGLESv2.glFinish },
+ { "glFlush", (void *) QWindowsEGLStaticContext::libGLESv2.glFlush },
+ { "glFrontFace", (void *) QWindowsEGLStaticContext::libGLESv2.glFrontFace },
+ { "glGenTextures", (void *) QWindowsEGLStaticContext::libGLESv2.glGenTextures },
+ { "glGetBooleanv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetBooleanv },
+ { "glGetError", (void *) QWindowsEGLStaticContext::libGLESv2.glGetError },
+ { "glGetFloatv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetFloatv },
+ { "glGetIntegerv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetIntegerv },
+ { "glGetString", (void *) QWindowsEGLStaticContext::libGLESv2.glGetString },
+ { "glGetTexParameterfv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetTexParameterfv },
+ { "glGetTexParameteriv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetTexParameteriv },
+ { "glHint", (void *) QWindowsEGLStaticContext::libGLESv2.glHint },
+ { "glIsEnabled", (void *) QWindowsEGLStaticContext::libGLESv2.glIsEnabled },
+ { "glIsTexture", (void *) QWindowsEGLStaticContext::libGLESv2.glIsTexture },
+ { "glLineWidth", (void *) QWindowsEGLStaticContext::libGLESv2.glLineWidth },
+ { "glPixelStorei", (void *) QWindowsEGLStaticContext::libGLESv2.glPixelStorei },
+ { "glPolygonOffset", (void *) QWindowsEGLStaticContext::libGLESv2.glPolygonOffset },
+ { "glReadPixels", (void *) QWindowsEGLStaticContext::libGLESv2.glReadPixels },
+ { "glScissor", (void *) QWindowsEGLStaticContext::libGLESv2.glScissor },
+ { "glStencilFunc", (void *) QWindowsEGLStaticContext::libGLESv2.glStencilFunc },
+ { "glStencilMask", (void *) QWindowsEGLStaticContext::libGLESv2.glStencilMask },
+ { "glStencilOp", (void *) QWindowsEGLStaticContext::libGLESv2.glStencilOp },
+ { "glTexImage2D", (void *) QWindowsEGLStaticContext::libGLESv2.glTexImage2D },
+ { "glTexParameterf", (void *) QWindowsEGLStaticContext::libGLESv2.glTexParameterf },
+ { "glTexParameterfv", (void *) QWindowsEGLStaticContext::libGLESv2.glTexParameterfv },
+ { "glTexParameteri", (void *) QWindowsEGLStaticContext::libGLESv2.glTexParameteri },
+ { "glTexParameteriv", (void *) QWindowsEGLStaticContext::libGLESv2.glTexParameteriv },
+ { "glTexSubImage2D", (void *) QWindowsEGLStaticContext::libGLESv2.glTexSubImage2D },
+ { "glViewport", (void *) QWindowsEGLStaticContext::libGLESv2.glViewport },
+
+ { "glActiveTexture", (void *) QWindowsEGLStaticContext::libGLESv2.glActiveTexture },
+ { "glAttachShader", (void *) QWindowsEGLStaticContext::libGLESv2.glAttachShader },
+ { "glBindAttribLocation", (void *) QWindowsEGLStaticContext::libGLESv2.glBindAttribLocation },
+ { "glBindBuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glBindBuffer },
+ { "glBindFramebuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glBindFramebuffer },
+ { "glBindRenderbuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glBindRenderbuffer },
+ { "glBlendColor", (void *) QWindowsEGLStaticContext::libGLESv2.glBlendColor },
+ { "glBlendEquation", (void *) QWindowsEGLStaticContext::libGLESv2.glBlendEquation },
+ { "glBlendEquationSeparate", (void *) QWindowsEGLStaticContext::libGLESv2.glBlendEquationSeparate },
+ { "glBlendFuncSeparate", (void *) QWindowsEGLStaticContext::libGLESv2.glBlendFuncSeparate },
+ { "glBufferData", (void *) QWindowsEGLStaticContext::libGLESv2.glBufferData },
+ { "glBufferSubData", (void *) QWindowsEGLStaticContext::libGLESv2.glBufferSubData },
+ { "glCheckFramebufferStatus", (void *) QWindowsEGLStaticContext::libGLESv2.glCheckFramebufferStatus },
+ { "glCompileShader", (void *) QWindowsEGLStaticContext::libGLESv2.glCompileShader },
+ { "glCompressedTexImage2D", (void *) QWindowsEGLStaticContext::libGLESv2.glCompressedTexImage2D },
+ { "glCompressedTexSubImage2D", (void *) QWindowsEGLStaticContext::libGLESv2.glCompressedTexSubImage2D },
+ { "glCreateProgram", (void *) QWindowsEGLStaticContext::libGLESv2.glCreateProgram },
+ { "glCreateShader", (void *) QWindowsEGLStaticContext::libGLESv2.glCreateShader },
+ { "glDeleteBuffers", (void *) QWindowsEGLStaticContext::libGLESv2.glDeleteBuffers },
+ { "glDeleteFramebuffers", (void *) QWindowsEGLStaticContext::libGLESv2.glDeleteFramebuffers },
+ { "glDeleteProgram", (void *) QWindowsEGLStaticContext::libGLESv2.glDeleteProgram },
+ { "glDeleteRenderbuffers", (void *) QWindowsEGLStaticContext::libGLESv2.glDeleteRenderbuffers },
+ { "glDeleteShader", (void *) QWindowsEGLStaticContext::libGLESv2.glDeleteShader },
+ { "glDetachShader", (void *) QWindowsEGLStaticContext::libGLESv2.glDetachShader },
+ { "glDisableVertexAttribArray", (void *) QWindowsEGLStaticContext::libGLESv2.glDisableVertexAttribArray },
+ { "glEnableVertexAttribArray", (void *) QWindowsEGLStaticContext::libGLESv2.glEnableVertexAttribArray },
+ { "glFramebufferRenderbuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glFramebufferRenderbuffer },
+ { "glFramebufferTexture2D", (void *) QWindowsEGLStaticContext::libGLESv2.glFramebufferTexture2D },
+ { "glGenBuffers", (void *) QWindowsEGLStaticContext::libGLESv2.glGenBuffers },
+ { "glGenerateMipmap", (void *) QWindowsEGLStaticContext::libGLESv2.glGenerateMipmap },
+ { "glGenFramebuffers", (void *) QWindowsEGLStaticContext::libGLESv2.glGenFramebuffers },
+ { "glGenRenderbuffers", (void *) QWindowsEGLStaticContext::libGLESv2.glGenRenderbuffers },
+ { "glGetActiveAttrib", (void *) QWindowsEGLStaticContext::libGLESv2.glGetActiveAttrib },
+ { "glGetActiveUniform", (void *) QWindowsEGLStaticContext::libGLESv2.glGetActiveUniform },
+ { "glGetAttachedShaders", (void *) QWindowsEGLStaticContext::libGLESv2.glGetAttachedShaders },
+ { "glGetAttribLocation", (void *) QWindowsEGLStaticContext::libGLESv2.glGetAttribLocation },
+ { "glGetBufferParameteriv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetBufferParameteriv },
+ { "glGetFramebufferAttachmentParameteriv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetFramebufferAttachmentParameteriv },
+ { "glGetProgramiv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetProgramiv },
+ { "glGetProgramInfoLog", (void *) QWindowsEGLStaticContext::libGLESv2.glGetProgramInfoLog },
+ { "glGetRenderbufferParameteriv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetRenderbufferParameteriv },
+ { "glGetShaderiv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetShaderiv },
+ { "glGetShaderInfoLog", (void *) QWindowsEGLStaticContext::libGLESv2.glGetShaderInfoLog },
+ { "glGetShaderPrecisionFormat", (void *) QWindowsEGLStaticContext::libGLESv2.glGetShaderPrecisionFormat },
+ { "glGetShaderSource", (void *) QWindowsEGLStaticContext::libGLESv2.glGetShaderSource },
+ { "glGetUniformfv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetUniformfv },
+ { "glGetUniformiv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetUniformiv },
+ { "glGetUniformLocation", (void *) QWindowsEGLStaticContext::libGLESv2.glGetUniformLocation },
+ { "glGetVertexAttribfv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetVertexAttribfv },
+ { "glGetVertexAttribiv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetVertexAttribiv },
+ { "glGetVertexAttribPointerv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetVertexAttribPointerv },
+ { "glIsBuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glIsBuffer },
+ { "glIsFramebuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glIsFramebuffer },
+ { "glIsProgram", (void *) QWindowsEGLStaticContext::libGLESv2.glIsProgram },
+ { "glIsRenderbuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glIsRenderbuffer },
+ { "glIsShader", (void *) QWindowsEGLStaticContext::libGLESv2.glIsShader },
+ { "glLinkProgram", (void *) QWindowsEGLStaticContext::libGLESv2.glLinkProgram },
+ { "glReleaseShaderCompiler", (void *) QWindowsEGLStaticContext::libGLESv2.glReleaseShaderCompiler },
+ { "glRenderbufferStorage", (void *) QWindowsEGLStaticContext::libGLESv2.glRenderbufferStorage },
+ { "glSampleCoverage", (void *) QWindowsEGLStaticContext::libGLESv2.glSampleCoverage },
+ { "glShaderBinary", (void *) QWindowsEGLStaticContext::libGLESv2.glShaderBinary },
+ { "glShaderSource", (void *) QWindowsEGLStaticContext::libGLESv2.glShaderSource },
+ { "glStencilFuncSeparate", (void *) QWindowsEGLStaticContext::libGLESv2.glStencilFuncSeparate },
+ { "glStencilMaskSeparate", (void *) QWindowsEGLStaticContext::libGLESv2.glStencilMaskSeparate },
+ { "glStencilOpSeparate", (void *) QWindowsEGLStaticContext::libGLESv2.glStencilOpSeparate },
+ { "glUniform1f", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform1f },
+ { "glUniform1fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform1fv },
+ { "glUniform1i", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform1i },
+ { "glUniform1iv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform1iv },
+ { "glUniform2f", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform2f },
+ { "glUniform2fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform2fv },
+ { "glUniform2i", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform2i },
+ { "glUniform2iv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform2iv },
+ { "glUniform3f", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform3f },
+ { "glUniform3fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform3fv },
+ { "glUniform3i", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform3i },
+ { "glUniform3iv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform3iv },
+ { "glUniform4f", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform4f },
+ { "glUniform4fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform4fv },
+ { "glUniform4i", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform4i },
+ { "glUniform4iv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform4iv },
+ { "glUniformMatrix2fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniformMatrix2fv },
+ { "glUniformMatrix3fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniformMatrix3fv },
+ { "glUniformMatrix4fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniformMatrix4fv },
+ { "glUseProgram", (void *) QWindowsEGLStaticContext::libGLESv2.glUseProgram },
+ { "glValidateProgram", (void *) QWindowsEGLStaticContext::libGLESv2.glValidateProgram },
+ { "glVertexAttrib1f", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib1f },
+ { "glVertexAttrib1fv", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib1fv },
+ { "glVertexAttrib2f", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib2f },
+ { "glVertexAttrib2fv", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib2fv },
+ { "glVertexAttrib3f", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib3f },
+ { "glVertexAttrib3fv", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib3fv },
+ { "glVertexAttrib4f", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib4f },
+ { "glVertexAttrib4fv", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib4fv },
+ { "glVertexAttribPointer", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttribPointer },
+
+ { "glClearDepthf", (void *) QWindowsEGLStaticContext::libGLESv2.glClearDepthf },
+ { "glDepthRangef", (void *) QWindowsEGLStaticContext::libGLESv2.glDepthRangef }
+ };
+ for (size_t i = 0; i < sizeof(standardFuncs) / sizeof(StdFunc); ++i)
+ if (procName == standardFuncs[i].name)
+ return reinterpret_cast<QFunctionPointer>(standardFuncs[i].func);
+
+ QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
+ QFunctionPointer procAddress = reinterpret_cast<QFunctionPointer>(QWindowsEGLStaticContext::libEGL.eglGetProcAddress(procName.constData()));
+ if (QWindowsContext::verbose > 1)
+ qCDebug(lcQpaGl) << __FUNCTION__ << procName << QWindowsEGLStaticContext::libEGL.eglGetCurrentContext() << "returns" << procAddress;
+ if (!procAddress)
+ qWarning("%s: Unable to resolve '%s'", __FUNCTION__, procName.constData());
+ return procAddress;
+}
+
+static QVector<EGLint> createConfigAttributesFromFormat(const QSurfaceFormat &format)
+{
+ int redSize = format.redBufferSize();
+ int greenSize = format.greenBufferSize();
+ int blueSize = format.blueBufferSize();
+ int alphaSize = format.alphaBufferSize();
+ int depthSize = format.depthBufferSize();
+ int stencilSize = format.stencilBufferSize();
+ int sampleCount = format.samples();
+
+ QVector<EGLint> configAttributes;
+ configAttributes.reserve(16);
+
+ configAttributes.append(EGL_RED_SIZE);
+ configAttributes.append(redSize > 0 ? redSize : 0);
+
+ configAttributes.append(EGL_GREEN_SIZE);
+ configAttributes.append(greenSize > 0 ? greenSize : 0);
+
+ configAttributes.append(EGL_BLUE_SIZE);
+ configAttributes.append(blueSize > 0 ? blueSize : 0);
+
+ configAttributes.append(EGL_ALPHA_SIZE);
+ configAttributes.append(alphaSize > 0 ? alphaSize : 0);
+
+ configAttributes.append(EGL_DEPTH_SIZE);
+ configAttributes.append(depthSize > 0 ? depthSize : 0);
+
+ configAttributes.append(EGL_STENCIL_SIZE);
+ configAttributes.append(stencilSize > 0 ? stencilSize : 0);
+
+ configAttributes.append(EGL_SAMPLES);
+ configAttributes.append(sampleCount > 0 ? sampleCount : 0);
+
+ configAttributes.append(EGL_SAMPLE_BUFFERS);
+ configAttributes.append(sampleCount > 0);
+
+ return configAttributes;
+}
+
+static bool reduceConfigAttributes(QVector<EGLint> *configAttributes)
+{
+ int i = -1;
+
+ i = configAttributes->indexOf(EGL_SWAP_BEHAVIOR);
+ if (i >= 0) {
+ configAttributes->remove(i,2);
}
- return ok;
+
+ i = configAttributes->indexOf(EGL_BUFFER_SIZE);
+ if (i >= 0) {
+ if (configAttributes->at(i+1) == 16) {
+ configAttributes->remove(i,2);
+ return true;
+ }
+ }
+
+ i = configAttributes->indexOf(EGL_SAMPLES);
+ if (i >= 0) {
+ EGLint value = configAttributes->value(i+1, 0);
+ if (value > 1)
+ configAttributes->replace(i+1, qMin(EGLint(16), value / 2));
+ else
+ configAttributes->remove(i, 2);
+ return true;
+ }
+
+ i = configAttributes->indexOf(EGL_SAMPLE_BUFFERS);
+ if (i >= 0) {
+ configAttributes->remove(i,2);
+ return true;
+ }
+
+ i = configAttributes->indexOf(EGL_ALPHA_SIZE);
+ if (i >= 0) {
+ configAttributes->remove(i,2);
+#if defined(EGL_BIND_TO_TEXTURE_RGBA) && defined(EGL_BIND_TO_TEXTURE_RGB)
+ i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGBA);
+ if (i >= 0) {
+ configAttributes->replace(i,EGL_BIND_TO_TEXTURE_RGB);
+ configAttributes->replace(i+1,true);
+
+ }
+#endif
+ return true;
+ }
+
+ i = configAttributes->indexOf(EGL_STENCIL_SIZE);
+ if (i >= 0) {
+ if (configAttributes->at(i + 1) > 1)
+ configAttributes->replace(i + 1, 1);
+ else
+ configAttributes->remove(i, 2);
+ return true;
+ }
+
+ i = configAttributes->indexOf(EGL_DEPTH_SIZE);
+ if (i >= 0) {
+ if (configAttributes->at(i + 1) > 1)
+ configAttributes->replace(i + 1, 1);
+ else
+ configAttributes->remove(i, 2);
+ return true;
+ }
+#ifdef EGL_BIND_TO_TEXTURE_RGB
+ i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGB);
+ if (i >= 0) {
+ configAttributes->remove(i,2);
+ return true;
+ }
+#endif
+
+ return false;
+}
+
+EGLConfig QWindowsEGLContext::chooseConfig(const QSurfaceFormat &format)
+{
+ QVector<EGLint> configureAttributes = createConfigAttributesFromFormat(format);
+ configureAttributes.append(EGL_SURFACE_TYPE);
+ configureAttributes.append(EGL_WINDOW_BIT);
+ configureAttributes.append(EGL_RENDERABLE_TYPE);
+ configureAttributes.append(EGL_OPENGL_ES2_BIT);
+ configureAttributes.append(EGL_NONE);
+
+ EGLDisplay display = m_staticContext->display();
+ EGLConfig cfg = 0;
+ do {
+ // Get the number of matching configurations for this set of properties.
+ EGLint matching = 0;
+ if (!QWindowsEGLStaticContext::libEGL.eglChooseConfig(display, configureAttributes.constData(), 0, 0, &matching) || !matching)
+ continue;
+
+ // Fetch all of the matching configurations and find the
+ // first that matches the pixel format we wanted.
+ int i = configureAttributes.indexOf(EGL_RED_SIZE);
+ int confAttrRed = configureAttributes.at(i+1);
+ i = configureAttributes.indexOf(EGL_GREEN_SIZE);
+ int confAttrGreen = configureAttributes.at(i+1);
+ i = configureAttributes.indexOf(EGL_BLUE_SIZE);
+ int confAttrBlue = configureAttributes.at(i+1);
+ i = configureAttributes.indexOf(EGL_ALPHA_SIZE);
+ int confAttrAlpha = i == -1 ? 0 : configureAttributes.at(i+1);
+
+ QVector<EGLConfig> configs(matching);
+ QWindowsEGLStaticContext::libEGL.eglChooseConfig(display, configureAttributes.constData(), configs.data(), configs.size(), &matching);
+ if (!cfg && matching > 0)
+ cfg = configs.first();
+
+ EGLint red = 0;
+ EGLint green = 0;
+ EGLint blue = 0;
+ EGLint alpha = 0;
+ for (int i = 0; i < configs.size(); ++i) {
+ if (confAttrRed)
+ QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, configs[i], EGL_RED_SIZE, &red);
+ if (confAttrGreen)
+ QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, configs[i], EGL_GREEN_SIZE, &green);
+ if (confAttrBlue)
+ QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, configs[i], EGL_BLUE_SIZE, &blue);
+ if (confAttrAlpha)
+ QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, configs[i], EGL_ALPHA_SIZE, &alpha);
+
+ if (red == confAttrRed && green == confAttrGreen
+ && blue == confAttrBlue && alpha == confAttrAlpha)
+ return configs[i];
+ }
+ } while (reduceConfigAttributes(&configureAttributes));
+
+ if (!cfg)
+ qWarning("Cannot find EGLConfig, returning null config");
+
+ return cfg;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h
index 33653b2f2e..6c4ac08da1 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.h
+++ b/src/plugins/platforms/windows/qwindowseglcontext.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -42,20 +42,237 @@
#ifndef QWINDOWSEGLCONTEXT_H
#define QWINDOWSEGLCONTEXT_H
-#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
-#include <QSharedPointer>
+#include "qwindowsopenglcontext.h"
+#include <EGL/egl.h>
QT_BEGIN_NAMESPACE
-class QWindowsEGLStaticContext
+struct QWindowsLibEGL
+{
+ bool init();
+
+ EGLint (EGLAPIENTRY * eglGetError)(void);
+ EGLDisplay (EGLAPIENTRY * eglGetDisplay)(EGLNativeDisplayType display_id);
+ EGLBoolean (EGLAPIENTRY * eglInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor);
+ EGLBoolean (EGLAPIENTRY * eglTerminate)(EGLDisplay dpy);
+ EGLBoolean (EGLAPIENTRY * eglChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list,
+ EGLConfig *configs, EGLint config_size,
+ EGLint *num_config);
+ EGLBoolean (EGLAPIENTRY * eglGetConfigAttrib)(EGLDisplay dpy, EGLConfig config,
+ EGLint attribute, EGLint *value);
+ EGLSurface (EGLAPIENTRY * eglCreateWindowSurface)(EGLDisplay dpy, EGLConfig config,
+ EGLNativeWindowType win,
+ const EGLint *attrib_list);
+ EGLSurface (EGLAPIENTRY * eglCreatePbufferSurface)(EGLDisplay dpy, EGLConfig config,
+ const EGLint *attrib_list);
+ EGLBoolean (EGLAPIENTRY * eglDestroySurface)(EGLDisplay dpy, EGLSurface surface);
+ EGLBoolean (EGLAPIENTRY * eglBindAPI)(EGLenum api);
+ EGLBoolean (EGLAPIENTRY * eglSwapInterval)(EGLDisplay dpy, EGLint interval);
+ EGLContext (EGLAPIENTRY * eglCreateContext)(EGLDisplay dpy, EGLConfig config,
+ EGLContext share_context,
+ const EGLint *attrib_list);
+ EGLBoolean (EGLAPIENTRY * eglDestroyContext)(EGLDisplay dpy, EGLContext ctx);
+ EGLBoolean (EGLAPIENTRY * eglMakeCurrent)(EGLDisplay dpy, EGLSurface draw,
+ EGLSurface read, EGLContext ctx);
+ EGLContext (EGLAPIENTRY * eglGetCurrentContext)(void);
+ EGLSurface (EGLAPIENTRY * eglGetCurrentSurface)(EGLint readdraw);
+ EGLDisplay (EGLAPIENTRY * eglGetCurrentDisplay)(void);
+ EGLBoolean (EGLAPIENTRY * eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
+ __eglMustCastToProperFunctionPointerType (EGLAPIENTRY * eglGetProcAddress)(const char *procname);
+
+private:
+#ifndef QT_STATIC
+ void *resolve(const char *name);
+ HMODULE m_lib;
+#endif
+};
+
+struct QWindowsLibGLESv2
+{
+ bool init();
+#ifndef QT_STATIC
+ void *moduleHandle() const { return m_lib; }
+#else
+ void *moduleHandle() const { return Q_NULLPTR; }
+#endif
+
+ // GL1+GLES2 common
+ void (APIENTRY * glBindTexture)(GLenum target, GLuint texture);
+ void (APIENTRY * glBlendFunc)(GLenum sfactor, GLenum dfactor);
+ void (APIENTRY * glClear)(GLbitfield mask);
+ void (APIENTRY * glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+ void (APIENTRY * glClearStencil)(GLint s);
+ void (APIENTRY * glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+ void (APIENTRY * glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+ void (APIENTRY * glCopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+ void (APIENTRY * glCullFace)(GLenum mode);
+ void (APIENTRY * glDeleteTextures)(GLsizei n, const GLuint* textures);
+ void (APIENTRY * glDepthFunc)(GLenum func);
+ void (APIENTRY * glDepthMask)(GLboolean flag);
+ void (APIENTRY * glDisable)(GLenum cap);
+ void (APIENTRY * glDrawArrays)(GLenum mode, GLint first, GLsizei count);
+ void (APIENTRY * glDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
+ void (APIENTRY * glEnable)(GLenum cap);
+ void (APIENTRY * glFinish)();
+ void (APIENTRY * glFlush)();
+ void (APIENTRY * glFrontFace)(GLenum mode);
+ void (APIENTRY * glGenTextures)(GLsizei n, GLuint* textures);
+ void (APIENTRY * glGetBooleanv)(GLenum pname, GLboolean* params);
+ GLenum (APIENTRY * glGetError)();
+ void (APIENTRY * glGetFloatv)(GLenum pname, GLfloat* params);
+ void (APIENTRY * glGetIntegerv)(GLenum pname, GLint* params);
+ const GLubyte * (APIENTRY * glGetString)(GLenum name);
+ void (APIENTRY * glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat* params);
+ void (APIENTRY * glGetTexParameteriv)(GLenum target, GLenum pname, GLint* params);
+ void (APIENTRY * glHint)(GLenum target, GLenum mode);
+ GLboolean (APIENTRY * glIsEnabled)(GLenum cap);
+ GLboolean (APIENTRY * glIsTexture)(GLuint texture);
+ void (APIENTRY * glLineWidth)(GLfloat width);
+ void (APIENTRY * glPixelStorei)(GLenum pname, GLint param);
+ void (APIENTRY * glPolygonOffset)(GLfloat factor, GLfloat units);
+ void (APIENTRY * glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
+ void (APIENTRY * glScissor)(GLint x, GLint y, GLsizei width, GLsizei height);
+ void (APIENTRY * glStencilFunc)(GLenum func, GLint ref, GLuint mask);
+ void (APIENTRY * glStencilMask)(GLuint mask);
+ void (APIENTRY * glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass);
+ void (APIENTRY * glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+ void (APIENTRY * glTexParameterf)(GLenum target, GLenum pname, GLfloat param);
+ void (APIENTRY * glTexParameterfv)(GLenum target, GLenum pname, const GLfloat* params);
+ void (APIENTRY * glTexParameteri)(GLenum target, GLenum pname, GLint param);
+ void (APIENTRY * glTexParameteriv)(GLenum target, GLenum pname, const GLint* params);
+ void (APIENTRY * glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
+ void (APIENTRY * glViewport)(GLint x, GLint y, GLsizei width, GLsizei height);
+
+ // GLES2
+ void (APIENTRY * glActiveTexture)(GLenum texture);
+ void (APIENTRY * glAttachShader)(GLuint program, GLuint shader);
+ void (APIENTRY * glBindAttribLocation)(GLuint program, GLuint index, const char* name);
+ void (APIENTRY * glBindBuffer)(GLenum target, GLuint buffer);
+ void (APIENTRY * glBindFramebuffer)(GLenum target, GLuint framebuffer);
+ void (APIENTRY * glBindRenderbuffer)(GLenum target, GLuint renderbuffer);
+ void (APIENTRY * glBlendColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+ void (APIENTRY * glBlendEquation)(GLenum mode);
+ void (APIENTRY * glBlendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha);
+ void (APIENTRY * glBlendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+ void (APIENTRY * glBufferData)(GLenum target, qopengl_GLsizeiptr size, const void* data, GLenum usage);
+ void (APIENTRY * glBufferSubData)(GLenum target, qopengl_GLintptr offset, qopengl_GLsizeiptr size, const void* data);
+ GLenum (APIENTRY * glCheckFramebufferStatus)(GLenum target);
+ void (APIENTRY * glCompileShader)(GLuint shader);
+ void (APIENTRY * glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
+ void (APIENTRY * glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
+ GLuint (APIENTRY * glCreateProgram)();
+ GLuint (APIENTRY * glCreateShader)(GLenum type);
+ void (APIENTRY * glDeleteBuffers)(GLsizei n, const GLuint* buffers);
+ void (APIENTRY * glDeleteFramebuffers)(GLsizei n, const GLuint* framebuffers);
+ void (APIENTRY * glDeleteProgram)(GLuint program);
+ void (APIENTRY * glDeleteRenderbuffers)(GLsizei n, const GLuint* renderbuffers);
+ void (APIENTRY * glDeleteShader)(GLuint shader);
+ void (APIENTRY * glDetachShader)(GLuint program, GLuint shader);
+ void (APIENTRY * glDisableVertexAttribArray)(GLuint index);
+ void (APIENTRY * glEnableVertexAttribArray)(GLuint index);
+ void (APIENTRY * glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+ void (APIENTRY * glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+ void (APIENTRY * glGenBuffers)(GLsizei n, GLuint* buffers);
+ void (APIENTRY * glGenerateMipmap)(GLenum target);
+ void (APIENTRY * glGenFramebuffers)(GLsizei n, GLuint* framebuffers);
+ void (APIENTRY * glGenRenderbuffers)(GLsizei n, GLuint* renderbuffers);
+ void (APIENTRY * glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
+ void (APIENTRY * glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
+ void (APIENTRY * glGetAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+ GLint (APIENTRY * glGetAttribLocation)(GLuint program, const char* name);
+ void (APIENTRY * glGetBufferParameteriv)(GLenum target, GLenum pname, GLint* params);
+ void (APIENTRY * glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params);
+ void (APIENTRY * glGetProgramiv)(GLuint program, GLenum pname, GLint* params);
+ void (APIENTRY * glGetProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog);
+ void (APIENTRY * glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params);
+ void (APIENTRY * glGetShaderiv)(GLuint shader, GLenum pname, GLint* params);
+ void (APIENTRY * glGetShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog);
+ void (APIENTRY * glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+ void (APIENTRY * glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, char* source);
+ void (APIENTRY * glGetUniformfv)(GLuint program, GLint location, GLfloat* params);
+ void (APIENTRY * glGetUniformiv)(GLuint program, GLint location, GLint* params);
+ GLint (APIENTRY * glGetUniformLocation)(GLuint program, const char* name);
+ void (APIENTRY * glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params);
+ void (APIENTRY * glGetVertexAttribiv)(GLuint index, GLenum pname, GLint* params);
+ void (APIENTRY * glGetVertexAttribPointerv)(GLuint index, GLenum pname, void** pointer);
+ GLboolean (APIENTRY * glIsBuffer)(GLuint buffer);
+ GLboolean (APIENTRY * glIsFramebuffer)(GLuint framebuffer);
+ GLboolean (APIENTRY * glIsProgram)(GLuint program);
+ GLboolean (APIENTRY * glIsRenderbuffer)(GLuint renderbuffer);
+ GLboolean (APIENTRY * glIsShader)(GLuint shader);
+ void (APIENTRY * glLinkProgram)(GLuint program);
+ void (APIENTRY * glReleaseShaderCompiler)();
+ void (APIENTRY * glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+ void (APIENTRY * glSampleCoverage)(GLclampf value, GLboolean invert);
+ void (APIENTRY * glShaderBinary)(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length);
+ void (APIENTRY * glShaderSource)(GLuint shader, GLsizei count, const char** string, const GLint* length);
+ void (APIENTRY * glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask);
+ void (APIENTRY * glStencilMaskSeparate)(GLenum face, GLuint mask);
+ void (APIENTRY * glStencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+ void (APIENTRY * glUniform1f)(GLint location, GLfloat x);
+ void (APIENTRY * glUniform1fv)(GLint location, GLsizei count, const GLfloat* v);
+ void (APIENTRY * glUniform1i)(GLint location, GLint x);
+ void (APIENTRY * glUniform1iv)(GLint location, GLsizei count, const GLint* v);
+ void (APIENTRY * glUniform2f)(GLint location, GLfloat x, GLfloat y);
+ void (APIENTRY * glUniform2fv)(GLint location, GLsizei count, const GLfloat* v);
+ void (APIENTRY * glUniform2i)(GLint location, GLint x, GLint y);
+ void (APIENTRY * glUniform2iv)(GLint location, GLsizei count, const GLint* v);
+ void (APIENTRY * glUniform3f)(GLint location, GLfloat x, GLfloat y, GLfloat z);
+ void (APIENTRY * glUniform3fv)(GLint location, GLsizei count, const GLfloat* v);
+ void (APIENTRY * glUniform3i)(GLint location, GLint x, GLint y, GLint z);
+ void (APIENTRY * glUniform3iv)(GLint location, GLsizei count, const GLint* v);
+ void (APIENTRY * glUniform4f)(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void (APIENTRY * glUniform4fv)(GLint location, GLsizei count, const GLfloat* v);
+ void (APIENTRY * glUniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w);
+ void (APIENTRY * glUniform4iv)(GLint location, GLsizei count, const GLint* v);
+ void (APIENTRY * glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+ void (APIENTRY * glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+ void (APIENTRY * glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+ void (APIENTRY * glUseProgram)(GLuint program);
+ void (APIENTRY * glValidateProgram)(GLuint program);
+ void (APIENTRY * glVertexAttrib1f)(GLuint indx, GLfloat x);
+ void (APIENTRY * glVertexAttrib1fv)(GLuint indx, const GLfloat* values);
+ void (APIENTRY * glVertexAttrib2f)(GLuint indx, GLfloat x, GLfloat y);
+ void (APIENTRY * glVertexAttrib2fv)(GLuint indx, const GLfloat* values);
+ void (APIENTRY * glVertexAttrib3f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+ void (APIENTRY * glVertexAttrib3fv)(GLuint indx, const GLfloat* values);
+ void (APIENTRY * glVertexAttrib4f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void (APIENTRY * glVertexAttrib4fv)(GLuint indx, const GLfloat* values);
+ void (APIENTRY * glVertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr);
+
+ // ES only
+ void (APIENTRY * glClearDepthf)(GLclampf depth);
+ void (APIENTRY * glDepthRangef)(GLclampf nearVal, GLclampf farVal);
+
+private:
+#ifndef QT_STATIC
+ void *resolve(const char *name);
+ HMODULE m_lib;
+#endif
+};
+
+class QWindowsEGLStaticContext : public QWindowsStaticOpenGLContext
{
Q_DISABLE_COPY(QWindowsEGLStaticContext)
+
public:
static QWindowsEGLStaticContext *create();
~QWindowsEGLStaticContext();
EGLDisplay display() const { return m_display; }
+ QWindowsOpenGLContext *createContext(QOpenGLContext *context);
+ void *moduleHandle() const { return libGLESv2.moduleHandle(); }
+ QOpenGLContext::OpenGLModuleType moduleType() const { return QOpenGLContext::LibGLES; }
+
+ void *createWindowSurface(void *nativeWindow, void *nativeConfig) Q_DECL_OVERRIDE;
+ void destroyWindowSurface(void *nativeSurface) Q_DECL_OVERRIDE;
+
+ QSurfaceFormat formatFromConfig(EGLDisplay display, EGLConfig config, const QSurfaceFormat &referenceFormat);
+
+ static QWindowsLibEGL libEGL;
+ static QWindowsLibGLESv2 libGLESv2;
+
private:
QWindowsEGLStaticContext(EGLDisplay display, int version);
@@ -63,26 +280,38 @@ private:
const int m_version; //! majorVersion<<8 + minorVersion
};
-class QWindowsEGLContext : public QEGLPlatformContext
+class QWindowsEGLContext : public QWindowsOpenGLContext
{
public:
- typedef QSharedPointer<QWindowsEGLStaticContext> QWindowsEGLStaticContextPtr;
-
- QWindowsEGLContext(const QWindowsEGLStaticContextPtr& staticContext,
+ QWindowsEGLContext(QWindowsEGLStaticContext *staticContext,
const QSurfaceFormat &format,
QPlatformOpenGLContext *share);
-
~QWindowsEGLContext();
- static bool hasThreadedOpenGLCapability();
+ bool makeCurrent(QPlatformSurface *surface) Q_DECL_OVERRIDE;
+ void doneCurrent() Q_DECL_OVERRIDE;
+ void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE;
+ QFunctionPointer getProcAddress(const QByteArray &procName) Q_DECL_OVERRIDE;
- bool makeCurrent(QPlatformSurface *surface);
+ QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; }
+ bool isSharing() const Q_DECL_OVERRIDE { return m_shareContext != EGL_NO_CONTEXT; }
+ bool isValid() const Q_DECL_OVERRIDE { return m_eglContext != EGL_NO_CONTEXT; }
-protected:
- EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface);
+ void *nativeContext() const Q_DECL_OVERRIDE { return m_eglContext; }
+ void *nativeDisplay() const Q_DECL_OVERRIDE { return m_eglDisplay; }
+ void *nativeConfig() const Q_DECL_OVERRIDE { return m_eglConfig; }
private:
- const QWindowsEGLStaticContextPtr m_staticContext;
+ EGLConfig chooseConfig(const QSurfaceFormat &format);
+
+ QWindowsEGLStaticContext *m_staticContext;
+ EGLContext m_eglContext;
+ EGLContext m_shareContext;
+ EGLDisplay m_eglDisplay;
+ EGLConfig m_eglConfig;
+ QSurfaceFormat m_format;
+ EGLenum m_api;
+ int m_swapInterval;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
index 696dc06cee..363d8b2d5c 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
@@ -164,25 +164,24 @@ namespace {
{
Q_ASSERT(tagName.size() == 4);
quint32 tagId = *(reinterpret_cast<const quint32 *>(tagName.constData()));
- if (Q_UNLIKELY(m_fontData.size() < sizeof(OffsetSubTable)))
+ const size_t fontDataSize = m_fontData.size();
+ if (Q_UNLIKELY(fontDataSize < sizeof(OffsetSubTable)))
return 0;
OffsetSubTable *offsetSubTable = reinterpret_cast<OffsetSubTable *>(m_fontData.data());
TableDirectory *tableDirectory = reinterpret_cast<TableDirectory *>(offsetSubTable + 1);
- quint16 tableCount = qFromBigEndian<quint16>(offsetSubTable->numTables);
- if (Q_UNLIKELY(quint32(m_fontData.size()) < sizeof(OffsetSubTable) + sizeof(TableDirectory) * tableCount))
+ const size_t tableCount = qFromBigEndian<quint16>(offsetSubTable->numTables);
+ if (Q_UNLIKELY(fontDataSize < sizeof(OffsetSubTable) + sizeof(TableDirectory) * tableCount))
return 0;
- TableDirectory *nameTableDirectoryEntry = 0;
- for (int i = 0; i < tableCount; ++i, ++tableDirectory) {
- if (tableDirectory->identifier == tagId) {
- nameTableDirectoryEntry = tableDirectory;
- break;
- }
+ TableDirectory *tableDirectoryEnd = tableDirectory + tableCount;
+ for (TableDirectory *entry = tableDirectory; entry < tableDirectoryEnd; ++entry) {
+ if (entry->identifier == tagId)
+ return entry;
}
- return nameTableDirectoryEntry;
+ return 0;
}
QString EmbeddedFont::familyName(TableDirectory *nameTableDirectoryEntry)
@@ -1064,7 +1063,7 @@ QFontEngineMulti *QWindowsFontDatabase::fontEngineMulti(QFontEngine *fontEngine,
if (script == QChar::Script_Common)
return new QWindowsMultiFontEngine(fontEngine, script);
// ### as long as fallbacksForFamily() does not take script parameter into account,
- // prefer QFontEngineMultiQPA's loadEngine() implementation for complex scripts
+ // prefer QFontEngineMultiBasicImpl's loadEngine() implementation for complex scripts
return QPlatformFontDatabase::fontEngineMulti(fontEngine, script);
}
@@ -1613,37 +1612,36 @@ QStringList QWindowsFontDatabase::extraTryFontsForFamily(const QString &family)
return result;
}
+QString QWindowsFontDatabase::familyForStyleHint(QFont::StyleHint styleHint)
+{
+ switch (styleHint) {
+ case QFont::Times:
+ return QStringLiteral("Times New Roman");
+ case QFont::Courier:
+ return QStringLiteral("Courier New");
+ case QFont::Monospace:
+ return QStringLiteral("Courier New");
+ case QFont::Cursive:
+ return QStringLiteral("Comic Sans MS");
+ case QFont::Fantasy:
+ return QStringLiteral("Impact");
+ case QFont::Decorative:
+ return QStringLiteral("Old English");
+ case QFont::Helvetica:
+ return QStringLiteral("Arial");
+ case QFont::System:
+ default:
+ break;
+ }
+ return QStringLiteral("MS Shell Dlg 2");
+}
+
QStringList QWindowsFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
{
QStringList result = QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script);
if (!result.isEmpty())
return result;
-
- switch (styleHint) {
- case QFont::Times:
- result << QString::fromLatin1("Times New Roman");
- break;
- case QFont::Courier:
- result << QString::fromLatin1("Courier New");
- break;
- case QFont::Monospace:
- result << QString::fromLatin1("Courier New");
- break;
- case QFont::Cursive:
- result << QString::fromLatin1("Comic Sans MS");
- break;
- case QFont::Fantasy:
- result << QString::fromLatin1("Impact");
- break;
- case QFont::Decorative:
- result << QString::fromLatin1("Old English");
- break;
- case QFont::Helvetica:
- case QFont::System:
- default:
- result << QString::fromLatin1("Arial");
- }
-
+ result.append(QWindowsFontDatabase::familyForStyleHint(styleHint));
result.append(QWindowsFontDatabase::extraTryFontsForFamily(family));
qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.h b/src/plugins/platforms/windows/qwindowsfontdatabase.h
index a2324544d2..1ef346a430 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.h
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.h
@@ -77,17 +77,17 @@ public:
QWindowsFontDatabase();
~QWindowsFontDatabase();
- virtual void populateFontDatabase();
- virtual QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script);
- virtual QFontEngine *fontEngine(const QFontDef &fontDef, void *handle);
- virtual QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference);
- virtual QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const;
- virtual QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName);
- virtual void releaseHandle(void *handle);
- virtual QString fontDir() const;
-
- virtual QFont defaultFont() const { return systemDefaultFont(); }
- virtual bool fontsAlwaysScalable() const;
+ void populateFontDatabase() Q_DECL_OVERRIDE;
+ QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script) Q_DECL_OVERRIDE;
+ QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE;
+ QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) Q_DECL_OVERRIDE;
+ QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const Q_DECL_OVERRIDE;
+ QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName) Q_DECL_OVERRIDE;
+ void releaseHandle(void *handle) Q_DECL_OVERRIDE;
+ QString fontDir() const Q_DECL_OVERRIDE;
+
+ QFont defaultFont() const Q_DECL_OVERRIDE { return systemDefaultFont(); }
+ bool fontsAlwaysScalable() const Q_DECL_OVERRIDE;
void derefUniqueFont(const QString &uniqueFont);
void refUniqueFont(const QString &uniqueFont);
@@ -104,6 +104,7 @@ public:
static LOGFONT fontDefToLOGFONT(const QFontDef &fontDef);
static QStringList extraTryFontsForFamily(const QString &family);
+ static QString familyForStyleHint(QFont::StyleHint styleHint);
private:
void populate(const QString &family = QString());
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
index 734f645e65..2f038106de 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
@@ -442,30 +442,7 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QF
if (!result.isEmpty())
return result;
- switch (styleHint) {
- case QFont::Times:
- result << QString::fromLatin1("Times New Roman");
- break;
- case QFont::Courier:
- result << QString::fromLatin1("Courier New");
- break;
- case QFont::Monospace:
- result << QString::fromLatin1("Courier New");
- break;
- case QFont::Cursive:
- result << QString::fromLatin1("Comic Sans MS");
- break;
- case QFont::Fantasy:
- result << QString::fromLatin1("Impact");
- break;
- case QFont::Decorative:
- result << QString::fromLatin1("Old English");
- break;
- case QFont::Helvetica:
- case QFont::System:
- default:
- result << QString::fromLatin1("Arial");
- }
+ result.append(QWindowsFontDatabase::familyForStyleHint(styleHint));
#ifdef Q_OS_WINCE
QSettings settings(QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\FontLink\\SystemLink"), QSettings::NativeFormat);
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
index bad6c54bf4..cf6108d87a 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
@@ -57,8 +57,8 @@ public:
QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const;
- virtual QString fontDir() const;
- virtual QFont defaultFont() const;
+ QString fontDir() const Q_DECL_OVERRIDE;
+ QFont defaultFont() const Q_DECL_OVERRIDE;
private:
void populate(const QString &family = QString());
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp
index 6f97c8584b..d3cbea0b92 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp
@@ -111,11 +111,6 @@ static void resolveGetCharWidthI()
ptrGetCharWidthI = (PtrGetCharWidthI)QSystemLibrary::resolve(QStringLiteral("gdi32"), "GetCharWidthI");
}
-// defined in qtextengine_win.cpp
-typedef void *SCRIPT_CACHE;
-typedef HRESULT (WINAPI *fScriptFreeCache)(SCRIPT_CACHE *);
-extern fScriptFreeCache ScriptFreeCache;
-
static inline quint32 getUInt(unsigned char *p)
{
quint32 val;
@@ -1300,7 +1295,7 @@ void QWindowsFontEngine::initFontInfo(const QFontDef &request,
Will probably be superseded by a common Free Type font engine in Qt 5.X.
*/
QWindowsMultiFontEngine::QWindowsMultiFontEngine(QFontEngine *fe, int script)
- : QFontEngineMultiQPA(fe, script)
+ : QFontEngineMultiBasicImpl(fe, script)
{
}
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.h b/src/plugins/platforms/windows/qwindowsfontengine.h
index 0ddf778fa0..8fe063121a 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.h
+++ b/src/plugins/platforms/windows/qwindowsfontengine.h
@@ -53,7 +53,7 @@
// We mean it.
//
-#include <QtGui/private/qfontengine_qpa_p.h>
+#include <QtGui/private/qfontengine_p.h>
#include <QtGui/QImage>
#include <QtCore/QSharedPointer>
@@ -78,48 +78,48 @@ public:
void initFontInfo(const QFontDef &request,
HDC fontHdc, int dpi);
- virtual QFixed lineThickness() const;
- virtual Properties properties() const;
- virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics);
- virtual FaceId faceId() const;
- virtual bool getSfntTableData(uint tag, uchar *buffer, uint *length) const;
- virtual int synthesized() const;
- virtual QFixed emSquareSize() const;
+ QFixed lineThickness() const Q_DECL_OVERRIDE;
+ Properties properties() const Q_DECL_OVERRIDE;
+ void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) Q_DECL_OVERRIDE;
+ FaceId faceId() const Q_DECL_OVERRIDE;
+ bool getSfntTableData(uint tag, uchar *buffer, uint *length) const Q_DECL_OVERRIDE;
+ int synthesized() const Q_DECL_OVERRIDE;
+ QFixed emSquareSize() const Q_DECL_OVERRIDE;
- virtual glyph_t glyphIndex(uint ucs4) const;
- virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const;
- virtual void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const;
+ glyph_t glyphIndex(uint ucs4) const Q_DECL_OVERRIDE;
+ bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const Q_DECL_OVERRIDE;
+ void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const Q_DECL_OVERRIDE;
- virtual void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags);
+ void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE;
virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
QPainterPath *path, QTextItem::RenderFlags flags);
HGDIOBJ selectDesignFont() const;
- virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs);
- virtual glyph_metrics_t boundingBox(glyph_t g) { return boundingBox(g, QTransform()); }
- virtual glyph_metrics_t boundingBox(glyph_t g, const QTransform &t);
+ glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) Q_DECL_OVERRIDE;
+ glyph_metrics_t boundingBox(glyph_t g) Q_DECL_OVERRIDE { return boundingBox(g, QTransform()); }
+ glyph_metrics_t boundingBox(glyph_t g, const QTransform &t) Q_DECL_OVERRIDE;
- virtual QFixed ascent() const;
- virtual QFixed descent() const;
- virtual QFixed leading() const;
- virtual QFixed xHeight() const;
- virtual QFixed averageCharWidth() const;
- virtual qreal maxCharWidth() const;
- virtual qreal minLeftBearing() const;
- virtual qreal minRightBearing() const;
+ QFixed ascent() const Q_DECL_OVERRIDE;
+ QFixed descent() const Q_DECL_OVERRIDE;
+ QFixed leading() const Q_DECL_OVERRIDE;
+ QFixed xHeight() const Q_DECL_OVERRIDE;
+ QFixed averageCharWidth() const Q_DECL_OVERRIDE;
+ qreal maxCharWidth() const Q_DECL_OVERRIDE;
+ qreal minLeftBearing() const Q_DECL_OVERRIDE;
+ qreal minRightBearing() const Q_DECL_OVERRIDE;
- virtual QImage alphaMapForGlyph(glyph_t t) { return alphaMapForGlyph(t, QTransform()); }
- virtual QImage alphaMapForGlyph(glyph_t, const QTransform &xform);
- virtual QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform);
- virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, const QTransform &matrix, GlyphFormat);
+ QImage alphaMapForGlyph(glyph_t t) Q_DECL_OVERRIDE { return alphaMapForGlyph(t, QTransform()); }
+ QImage alphaMapForGlyph(glyph_t, const QTransform &xform) Q_DECL_OVERRIDE;
+ QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform) Q_DECL_OVERRIDE;
+ glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, const QTransform &matrix, GlyphFormat) Q_DECL_OVERRIDE;
- virtual QFontEngine *cloneWithSize(qreal pixelSize) const;
- virtual bool supportsTransformation(const QTransform &transform) const;
+ QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE;
+ bool supportsTransformation(const QTransform &transform) const Q_DECL_OVERRIDE;
#ifndef Q_CC_MINGW
- virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0);
+ void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0) Q_DECL_OVERRIDE;
#endif
bool hasUnreliableGlyphOutline() const Q_DECL_OVERRIDE;
@@ -172,7 +172,7 @@ private:
};
-class QWindowsMultiFontEngine : public QFontEngineMultiQPA
+class QWindowsMultiFontEngine : public QFontEngineMultiBasicImpl
{
public:
explicit QWindowsMultiFontEngine(QFontEngine *fe, int script);
diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
index 2da014ddc3..9ee074b33e 100644
--- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
+++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
@@ -74,7 +74,7 @@ public:
bool getSfntTableData(uint tag, uchar *buffer, uint *length) const;
QFixed emSquareSize() const;
- virtual glyph_t glyphIndex(uint ucs4) const;
+ glyph_t glyphIndex(uint ucs4) const Q_DECL_OVERRIDE;
bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const;
void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const;
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index eaa4eca84e..e336c6414e 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -48,6 +48,7 @@
#include <QtCore/QSysInfo>
#include <QtGui/QGuiApplication>
#include <qpa/qplatformnativeinterface.h>
+#include <QtPlatformHeaders/QWGLNativeContext>
#include <algorithm>
@@ -144,6 +145,131 @@
QT_BEGIN_NAMESPACE
+QWindowsOpengl32DLL QOpenGLStaticContext::opengl32;
+
+void *QWindowsOpengl32DLL::resolve(const char *name)
+{
+#ifndef Q_OS_WINCE
+ void *proc = m_lib ? (void *) ::GetProcAddress(m_lib, name) : 0;
+#else
+ void *proc = m_lib ? (void *) ::GetProcAddress(m_lib, (const wchar_t *) QString::fromLatin1(name).utf16()) : 0;
+#endif
+ if (!proc)
+ qErrnoWarning(::GetLastError(), "Failed to resolve OpenGL function %s", name);
+
+ return proc;
+}
+
+bool QWindowsOpengl32DLL::init(bool softwareRendering)
+{
+ const QByteArray opengl32 = QByteArrayLiteral("opengl32.dll");
+ const QByteArray swopengl = QByteArrayLiteral("QtSoftwareOpenGL.dll");
+
+ QByteArray openglDll = qgetenv("QT_OPENGL_DLL");
+ if (openglDll.isEmpty())
+ openglDll = softwareRendering ? swopengl : opengl32;
+
+ openglDll = openglDll.toLower();
+ m_nonOpengl32 = openglDll != opengl32;
+
+ qCDebug(lcQpaGl) << "Qt: Using WGL and OpenGL from" << openglDll;
+
+ m_lib = ::LoadLibraryA(openglDll.constData());
+ if (!m_lib) {
+ qErrnoWarning(::GetLastError(), "Failed to load %s", openglDll.constData());
+ return false;
+ }
+
+ if (moduleIsNotOpengl32()) {
+ // Load opengl32.dll always. GDI functions like ChoosePixelFormat do
+ // GetModuleHandle for opengl32.dll and behave differently (and call back into
+ // opengl32) when the module is present. This is fine for dummy contexts and windows.
+ ::LoadLibraryA("opengl32.dll");
+ }
+
+ wglCreateContext = reinterpret_cast<HGLRC (WINAPI *)(HDC)>(resolve("wglCreateContext"));
+ wglDeleteContext = reinterpret_cast<BOOL (WINAPI *)(HGLRC)>(resolve("wglDeleteContext"));
+ wglGetCurrentContext = reinterpret_cast<HGLRC (WINAPI *)()>(resolve("wglGetCurrentContext"));
+ wglGetCurrentDC = reinterpret_cast<HDC (WINAPI *)()>(resolve("wglGetCurrentDC"));
+ wglGetProcAddress = reinterpret_cast<PROC (WINAPI *)(LPCSTR)>(resolve("wglGetProcAddress"));
+ wglMakeCurrent = reinterpret_cast<BOOL (WINAPI *)(HDC, HGLRC)>(resolve("wglMakeCurrent"));
+ wglShareLists = reinterpret_cast<BOOL (WINAPI *)(HGLRC, HGLRC)>(resolve("wglShareLists"));
+ wglSwapBuffers = reinterpret_cast<BOOL (WINAPI *)(HDC)>(resolve("wglSwapBuffers"));
+ wglSetPixelFormat = reinterpret_cast<BOOL (WINAPI *)(HDC, int, const PIXELFORMATDESCRIPTOR *)>(resolve("wglSetPixelFormat"));
+
+ glBindTexture = reinterpret_cast<void (APIENTRY *)(GLenum , GLuint )>(resolve("glBindTexture"));
+ glBlendFunc = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum )>(resolve("glBlendFunc"));
+ glClear = reinterpret_cast<void (APIENTRY *)(GLbitfield )>(resolve("glClear"));
+ glClearColor = reinterpret_cast<void (APIENTRY *)(GLfloat , GLfloat , GLfloat , GLfloat )>(resolve("glClearColor"));
+ glClearStencil = reinterpret_cast<void (APIENTRY *)(GLint )>(resolve("glClearStencil"));
+ glColorMask = reinterpret_cast<void (APIENTRY *)(GLboolean , GLboolean , GLboolean , GLboolean )>(resolve("glColorMask"));
+ glCopyTexImage2D = reinterpret_cast<void (APIENTRY *)(GLenum , GLint , GLenum , GLint , GLint , GLsizei , GLsizei , GLint )>(resolve("glCopyTexImage2D"));
+ glCopyTexSubImage2D = reinterpret_cast<void (APIENTRY *)(GLenum , GLint , GLint , GLint , GLint , GLint , GLsizei , GLsizei )>(resolve("glCopyTexSubImage2D"));
+ glCullFace = reinterpret_cast<void (APIENTRY *)(GLenum )>(resolve("glCullFace"));
+ glDeleteTextures = reinterpret_cast<void (APIENTRY *)(GLsizei , const GLuint *)>(resolve("glDeleteTextures"));
+ glDepthFunc = reinterpret_cast<void (APIENTRY *)(GLenum )>(resolve("glDepthFunc"));
+ glDepthMask = reinterpret_cast<void (APIENTRY *)(GLboolean )>(resolve("glDepthMask"));
+ glDisable = reinterpret_cast<void (APIENTRY *)(GLenum )>(resolve("glDisable"));
+ glDrawArrays = reinterpret_cast<void (APIENTRY *)(GLenum , GLint , GLsizei )>(resolve("glDrawArrays"));
+ glDrawElements = reinterpret_cast<void (APIENTRY *)(GLenum , GLsizei , GLenum , const GLvoid *)>(resolve("glDrawElements"));
+ glEnable = reinterpret_cast<void (APIENTRY *)(GLenum )>(resolve("glEnable"));
+ glFinish = reinterpret_cast<void (APIENTRY *)()>(resolve("glFinish"));
+ glFlush = reinterpret_cast<void (APIENTRY *)()>(resolve("glFlush"));
+ glFrontFace = reinterpret_cast<void (APIENTRY *)(GLenum )>(resolve("glFrontFace"));
+ glGenTextures = reinterpret_cast<void (APIENTRY *)(GLsizei , GLuint *)>(resolve("glGenTextures"));
+ glGetBooleanv = reinterpret_cast<void (APIENTRY *)(GLenum , GLboolean *)>(resolve("glGetBooleanv"));
+ glGetError = reinterpret_cast<GLenum (APIENTRY *)()>(resolve("glGetError"));
+ glGetFloatv = reinterpret_cast<void (APIENTRY *)(GLenum , GLfloat *)>(resolve("glGetFloatv"));
+ glGetIntegerv = reinterpret_cast<void (APIENTRY *)(GLenum , GLint *)>(resolve("glGetIntegerv"));
+ glGetString = reinterpret_cast<const GLubyte * (APIENTRY *)(GLenum )>(resolve("glGetString"));
+ glGetTexParameterfv = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLfloat *)>(resolve("glGetTexParameterfv"));
+ glGetTexParameteriv = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLint *)>(resolve("glGetTexParameteriv"));
+ glHint = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum )>(resolve("glHint"));
+ glIsEnabled = reinterpret_cast<GLboolean (APIENTRY *)(GLenum )>(resolve("glIsEnabled"));
+ glIsTexture = reinterpret_cast<GLboolean (APIENTRY *)(GLuint )>(resolve("glIsTexture"));
+ glLineWidth = reinterpret_cast<void (APIENTRY *)(GLfloat )>(resolve("glLineWidth"));
+ glPixelStorei = reinterpret_cast<void (APIENTRY *)(GLenum , GLint )>(resolve("glPixelStorei"));
+ glPolygonOffset = reinterpret_cast<void (APIENTRY *)(GLfloat , GLfloat )>(resolve("glPolygonOffset"));
+ glReadPixels = reinterpret_cast<void (APIENTRY *)(GLint , GLint , GLsizei , GLsizei , GLenum , GLenum , GLvoid *)>(resolve("glReadPixels"));
+ glScissor = reinterpret_cast<void (APIENTRY *)(GLint , GLint , GLsizei , GLsizei )>(resolve("glScissor"));
+ glStencilFunc = reinterpret_cast<void (APIENTRY *)(GLenum , GLint , GLuint )>(resolve("glStencilFunc"));
+ glStencilMask = reinterpret_cast<void (APIENTRY *)(GLuint )>(resolve("glStencilMask"));
+ glStencilOp = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLenum )>(resolve("glStencilOp"));
+ glTexImage2D = reinterpret_cast<void (APIENTRY *)(GLenum , GLint , GLint , GLsizei , GLsizei , GLint , GLenum , GLenum , const GLvoid *)>(resolve("glTexImage2D"));
+ glTexParameterf = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLfloat )>(resolve("glTexParameterf"));
+ glTexParameterfv = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , const GLfloat *)>(resolve("glTexParameterfv"));
+ glTexParameteri = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLint )>(resolve("glTexParameteri"));
+ glTexParameteriv = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , const GLint *)>(resolve("glTexParameteriv"));
+ glTexSubImage2D = reinterpret_cast<void (APIENTRY *)(GLenum , GLint , GLint , GLint , GLsizei , GLsizei , GLenum , GLenum , const GLvoid *)>(resolve("glTexSubImage2D"));
+ glViewport = reinterpret_cast<void (APIENTRY *)(GLint , GLint , GLsizei , GLsizei )>(resolve("glViewport"));
+
+ glClearDepth = reinterpret_cast<void (APIENTRY *)(GLdouble )>(resolve("glClearDepth"));
+ glDepthRange = reinterpret_cast<void (APIENTRY *)(GLdouble , GLdouble )>(resolve("glDepthRange"));
+
+ return wglCreateContext && glBindTexture && glClearDepth;
+}
+
+BOOL QWindowsOpengl32DLL::swapBuffers(HDC dc)
+{
+ if (moduleIsNotOpengl32())
+ return wglSwapBuffers(dc);
+ else
+ return SwapBuffers(dc);
+}
+
+BOOL QWindowsOpengl32DLL::setPixelFormat(HDC dc, int pf, const PIXELFORMATDESCRIPTOR *pfd)
+{
+ if (moduleIsNotOpengl32())
+ return wglSetPixelFormat(dc, pf, pfd);
+ else
+ return SetPixelFormat(dc, pf, pfd);
+}
+
+QWindowsOpenGLContext *QOpenGLStaticContext::createContext(QOpenGLContext *context)
+{
+ return new QWindowsGLContext(this, context);
+}
+
template <class MaskType, class FlagType> inline bool testFlag(MaskType mask, FlagType flag)
{
return (mask & MaskType(flag)) != 0;
@@ -210,10 +336,11 @@ static inline bool
bool ignoreGLSupport = false) // ARB format may not contain it.
{
const bool pixmapRequested = testFlag(additional.formatFlags, QWindowsGLRenderToPixmap);
- return (ignoreGLSupport || testFlag(pfd.dwFlags, PFD_SUPPORT_OPENGL))
- && testFlag(pfd.dwFlags, PFD_DRAW_TO_BITMAP) == pixmapRequested
- && hasGLOverlay(pfd) == testFlag(additional.formatFlags, QWindowsGLOverlay)
- && (!pixmapRequested || pfd.cColorBits == additional.pixmapDepth);
+ const bool pixmapOk = !pixmapRequested || testFlag(pfd.dwFlags, PFD_DRAW_TO_BITMAP);
+ const bool colorOk = !pixmapRequested || pfd.cColorBits == additional.pixmapDepth;
+ const bool glOk = ignoreGLSupport || testFlag(pfd.dwFlags, PFD_SUPPORT_OPENGL);
+ const bool overlayOk = hasGLOverlay(pfd) == testFlag(additional.formatFlags, QWindowsGLOverlay);
+ return pixmapOk && glOk && overlayOk && colorOk;
}
static void describeFormats(HDC hdc)
@@ -299,10 +426,23 @@ static PIXELFORMATDESCRIPTOR
// over the available formats to find the best one.
// Note: As of Windows 7, it seems direct-rendering is handled, so,
// the code might be obsolete?
+//
+// NB! When using an implementation with a name different than opengl32.dll
+// this code path should not be used since it will result in a mess due to GDI
+// relying on and possibly calling back into functions in opengl32.dll (and not
+// the one we are using). This is not a problem usually since for Mesa, which
+// we are most likely to ship with a name other than opengl32.dll, the ARB code
+// path should work. Hence the early bail out below.
+//
static int choosePixelFormat(HDC hdc, const QSurfaceFormat &format,
const QWindowsOpenGLAdditionalFormat &additional,
PIXELFORMATDESCRIPTOR *obtainedPfd)
{
+ if (QOpenGLStaticContext::opengl32.moduleIsNotOpengl32()) {
+ qWarning("%s: Attempted to use GDI functions with a non-opengl32.dll library", Q_FUNC_INFO);
+ return 0;
+ }
+
// 1) Try ChoosePixelFormat().
PIXELFORMATDESCRIPTOR requestedPfd = qPixelFormatFromSurfaceFormat(format, QWindowsGLDirectRendering);
initPixelFormatDescriptor(obtainedPfd);
@@ -352,12 +492,12 @@ static int choosePixelFormat(HDC hdc, const QSurfaceFormat &format,
static inline HGLRC createContext(HDC hdc, HGLRC shared)
{
- HGLRC result = wglCreateContext(hdc);
+ HGLRC result = QOpenGLStaticContext::opengl32.wglCreateContext(hdc);
if (!result) {
qErrnoWarning("%s: wglCreateContext failed.", __FUNCTION__);
return 0;
}
- if (shared && !wglShareLists(shared, result))
+ if (shared && !QOpenGLStaticContext::opengl32.wglShareLists(shared, result))
qErrnoWarning("%s: wglShareLists() failed.", __FUNCTION__);
return result;
}
@@ -623,7 +763,7 @@ static HGLRC createContext(const QOpenGLStaticContext &staticContext,
if (!result) {
QString message;
QDebug(&message).nospace() << __FUNCTION__ << ": wglCreateContextAttribsARB() failed (GL error code: 0x"
- << hex << glGetError() << dec << ") for format: " << format << ", shared context: " << shared;
+ << hex << staticContext.opengl32.glGetError() << dec << ") for format: " << format << ", shared context: " << shared;
qErrnoWarning("%s", qPrintable(message));
}
return result;
@@ -648,16 +788,17 @@ static inline HGLRC createDummyGLContext(HDC dc)
initPixelFormatDescriptor(&pixelFormDescriptor);
pixelFormDescriptor.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_GENERIC_FORMAT;
pixelFormDescriptor.iPixelType = PFD_TYPE_RGBA;
+ // Use the GDI variant, for the dummy this is fine, even when using something other than opengl32.dll.
const int pixelFormat = ChoosePixelFormat(dc, &pixelFormDescriptor);
if (!pixelFormat) {
qErrnoWarning("%s: ChoosePixelFormat failed.", __FUNCTION__);
return 0;
}
- if (!SetPixelFormat(dc, pixelFormat, &pixelFormDescriptor)) {
+ if (!QOpenGLStaticContext::opengl32.setPixelFormat(dc, pixelFormat, &pixelFormDescriptor)) {
qErrnoWarning("%s: SetPixelFormat failed.", __FUNCTION__);
return 0;
}
- HGLRC rc = wglCreateContext(dc);
+ HGLRC rc = QOpenGLStaticContext::opengl32.wglCreateContext(dc);
if (!rc) {
qErrnoWarning("%s: wglCreateContext failed.", __FUNCTION__);
return 0;
@@ -668,8 +809,8 @@ static inline HGLRC createDummyGLContext(HDC dc)
static inline QOpenGLContextData currentOpenGLContextData()
{
QOpenGLContextData result;
- result.hdc = wglGetCurrentDC();
- result.renderingContext = wglGetCurrentContext();
+ result.hdc = QOpenGLStaticContext::opengl32.wglGetCurrentDC();
+ result.renderingContext = QOpenGLStaticContext::opengl32.wglGetCurrentContext();
return result;
}
@@ -721,7 +862,7 @@ QWindowsOpenGLContextFormat QWindowsOpenGLContextFormat::current()
}
// v3 onwards
GLint value = 0;
- glGetIntegerv(GL_CONTEXT_FLAGS, &value);
+ QOpenGLStaticContext::opengl32.glGetIntegerv(GL_CONTEXT_FLAGS, &value);
if (!(value & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT))
result.options |= QSurfaceFormat::DeprecatedFunctions;
if (value & GL_CONTEXT_FLAG_DEBUG_BIT)
@@ -730,7 +871,7 @@ QWindowsOpenGLContextFormat QWindowsOpenGLContextFormat::current()
return result;
// v3.2 onwards: Profiles
value = 0;
- glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value);
+ QOpenGLStaticContext::opengl32.glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value);
if (value & GL_CONTEXT_CORE_PROFILE_BIT)
result.profile = QSurfaceFormat::CoreProfile;
else if (value & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
@@ -784,15 +925,15 @@ QOpenGLTemporaryContext::QOpenGLTemporaryContext() :
m_previous(currentOpenGLContextData()),
m_current(createDummyWindowOpenGLContextData())
{
- wglMakeCurrent(m_current.hdc, m_current.renderingContext);
+ QOpenGLStaticContext::opengl32.wglMakeCurrent(m_current.hdc, m_current.renderingContext);
}
QOpenGLTemporaryContext::~QOpenGLTemporaryContext()
{
- wglMakeCurrent(m_previous.hdc, m_previous.renderingContext);
+ QOpenGLStaticContext::opengl32.wglMakeCurrent(m_previous.hdc, m_previous.renderingContext);
ReleaseDC(m_current.hwnd, m_current.hdc);
DestroyWindow(m_current.hwnd);
- wglDeleteContext(m_current.renderingContext);
+ QOpenGLStaticContext::opengl32.wglDeleteContext(m_current.renderingContext);
}
/*!
@@ -807,6 +948,11 @@ QOpenGLTemporaryContext::~QOpenGLTemporaryContext()
Functions pending integration in the next version of OpenGL are post-fixed ARB.
+ No WGL or OpenGL functions are called directly from the windows plugin. Instead, the
+ static context loads opengl32.dll and resolves the necessary functions. This allows
+ building the plugin without linking to opengl32 and enables QT_OPENGL_DYNAMIC builds
+ where both the EGL and WGL (this) based implementation of the context are built.
+
\note Initialization requires an active context (see create()).
\sa QWindowsGLContext
@@ -822,11 +968,11 @@ QOpenGLStaticContext::QOpenGLStaticContext() :
extensionNames(QOpenGLStaticContext::getGlString(GL_EXTENSIONS)),
extensions(0),
defaultFormat(QWindowsOpenGLContextFormat::current()),
- wglGetPixelFormatAttribIVARB((WglGetPixelFormatAttribIVARB)wglGetProcAddress("wglGetPixelFormatAttribivARB")),
- wglChoosePixelFormatARB((WglChoosePixelFormatARB)wglGetProcAddress("wglChoosePixelFormatARB")),
- wglCreateContextAttribsARB((WglCreateContextAttribsARB)wglGetProcAddress("wglCreateContextAttribsARB")),
- wglSwapInternalExt((WglSwapInternalExt)wglGetProcAddress("wglSwapIntervalEXT")),
- wglGetSwapInternalExt((WglGetSwapInternalExt)wglGetProcAddress("wglGetSwapIntervalEXT"))
+ wglGetPixelFormatAttribIVARB((WglGetPixelFormatAttribIVARB)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetPixelFormatAttribivARB")),
+ wglChoosePixelFormatARB((WglChoosePixelFormatARB)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglChoosePixelFormatARB")),
+ wglCreateContextAttribsARB((WglCreateContextAttribsARB)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglCreateContextAttribsARB")),
+ wglSwapInternalExt((WglSwapInternalExt)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglSwapIntervalEXT")),
+ wglGetSwapInternalExt((WglGetSwapInternalExt)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetSwapIntervalEXT"))
{
if (extensionNames.startsWith(SAMPLE_BUFFER_EXTENSION " ")
|| extensionNames.indexOf(" " SAMPLE_BUFFER_EXTENSION " ") != -1)
@@ -835,16 +981,21 @@ QOpenGLStaticContext::QOpenGLStaticContext() :
QByteArray QOpenGLStaticContext::getGlString(unsigned int which)
{
- if (const GLubyte *s = glGetString(which))
+ if (const GLubyte *s = opengl32.glGetString(which))
return QByteArray((const char*)s);
return QByteArray();
}
-QOpenGLStaticContext *QOpenGLStaticContext::create()
+QOpenGLStaticContext *QOpenGLStaticContext::create(bool softwareRendering)
{
+ if (!opengl32.init(softwareRendering)) {
+ qWarning("%s: Failed to load and resolve WGL/OpenGL functions", Q_FUNC_INFO);
+ return 0;
+ }
+
// We need a current context for wglGetProcAdress()/getGLString() to work.
QScopedPointer<QOpenGLTemporaryContext> temporaryContext;
- if (!wglGetCurrentContext())
+ if (!QOpenGLStaticContext::opengl32.wglGetCurrentContext())
temporaryContext.reset(new QOpenGLTemporaryContext);
QOpenGLStaticContext *result = new QOpenGLStaticContext;
qCDebug(lcQpaGl) << __FUNCTION__ << *result;
@@ -881,15 +1032,61 @@ QDebug operator<<(QDebug d, const QOpenGLStaticContext &s)
\ingroup qt-lighthouse-win
*/
-QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContext,
+QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext,
QOpenGLContext *context) :
m_staticContext(staticContext),
m_context(context),
m_renderingContext(0),
m_pixelFormat(0),
m_extensionsUsed(false),
- m_swapInterval(-1)
+ m_swapInterval(-1),
+ m_ownsContext(true)
{
+ if (!m_staticContext) // Something went very wrong. Stop here, isValid() will return false.
+ return;
+
+ QVariant nativeHandle = context->nativeHandle();
+ if (!nativeHandle.isNull()) {
+ // Adopt and existing context.
+ if (!nativeHandle.canConvert<QWGLNativeContext>()) {
+ qWarning("QWindowsGLContext: Requires a QWGLNativeContext");
+ return;
+ }
+ QWGLNativeContext handle = nativeHandle.value<QWGLNativeContext>();
+ HGLRC wglcontext = handle.context();
+ HWND wnd = handle.window();
+ if (!wglcontext || !wnd) {
+ qWarning("QWindowsGLContext: No context and window given");
+ return;
+ }
+
+ HDC dc = GetDC(wnd);
+ // A window with an associated pixel format is mandatory.
+ // When no SetPixelFormat() call has been made, the following will fail.
+ m_pixelFormat = GetPixelFormat(dc);
+ bool ok = m_pixelFormat != 0;
+ if (!ok)
+ qWarning("QWindowsGLContext: Failed to get pixel format");
+ ok = DescribePixelFormat(dc, m_pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &m_obtainedPixelFormatDescriptor);
+ if (!ok) {
+ qWarning("QWindowsGLContext: Failed to describe pixel format");
+ } else {
+ QWindowsOpenGLAdditionalFormat obtainedAdditional;
+ m_obtainedFormat = GDI::qSurfaceFormatFromPixelFormat(m_obtainedPixelFormatDescriptor, &obtainedAdditional);
+ m_renderingContext = wglcontext;
+ ok = updateObtainedParams(dc);
+ }
+
+ ReleaseDC(wnd, dc);
+
+ if (ok)
+ m_ownsContext = false;
+ else
+ m_renderingContext = 0;
+
+ return;
+ }
+
QSurfaceFormat format = context->format();
if (format.renderableType() == QSurfaceFormat::DefaultRenderableType)
format.setRenderableType(QSurfaceFormat::OpenGL);
@@ -901,7 +1098,7 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex
static bool opengl32dll = false;
if (!opengl32dll) {
GLint params;
- glGetIntegerv(GL_DEPTH_BITS, &params);
+ staticContext->opengl32.glGetIntegerv(GL_DEPTH_BITS, &params);
opengl32dll = true;
}
@@ -912,7 +1109,7 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex
HWND dummyWindow = 0;
HDC hdc = 0;
bool tryExtensions = false;
- int obtainedSwapInternal = -1;
+ int obtainedSwapInterval = -1;
do {
dummyWindow = createDummyGLWindow();
if (!dummyWindow)
@@ -954,7 +1151,7 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex
qWarning("%s: Unable find a suitable pixel format.", __FUNCTION__);
break;
}
- if (!SetPixelFormat(hdc, m_pixelFormat, &m_obtainedPixelFormatDescriptor)) {
+ if (!QOpenGLStaticContext::opengl32.setPixelFormat(hdc, m_pixelFormat, &m_obtainedPixelFormatDescriptor)) {
qErrnoWarning("SetPixelFormat failed.");
break;
}
@@ -978,18 +1175,16 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex
}
// Query obtained parameters and apply swap interval.
- if (!wglMakeCurrent(hdc, m_renderingContext)) {
- qWarning("Failed to make context current.");
+ if (!updateObtainedParams(hdc, &obtainedSwapInterval))
break;
- }
- QWindowsOpenGLContextFormat::current().apply(&m_obtainedFormat);
+ } while (false);
- if (m_staticContext->wglGetSwapInternalExt)
- obtainedSwapInternal = m_staticContext->wglGetSwapInternalExt();
+ // Make the HGLRC retrievable via QOpenGLContext::nativeHandle().
+ // Do not provide the window since it is the dummy one and it is about to disappear.
+ if (m_renderingContext)
+ context->setNativeHandle(QVariant::fromValue<QWGLNativeContext>(QWGLNativeContext(m_renderingContext, 0)));
- wglMakeCurrent(0, 0);
- } while (false);
if (hdc)
ReleaseDC(dummyWindow, hdc);
if (dummyWindow)
@@ -998,18 +1193,34 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex
qCDebug(lcQpaGl) << __FUNCTION__ << this << (tryExtensions ? "ARB" : "GDI")
<< " requested: " << context->format()
<< "\n obtained #" << m_pixelFormat << (m_extensionsUsed ? "ARB" : "GDI") << m_obtainedFormat
- << "\n " << m_obtainedPixelFormatDescriptor << " swap interval: " << obtainedSwapInternal
+ << "\n " << m_obtainedPixelFormatDescriptor << " swap interval: " << obtainedSwapInterval
<< "\n default: " << m_staticContext->defaultFormat
<< "\n HGLRC=" << m_renderingContext;
}
QWindowsGLContext::~QWindowsGLContext()
{
- if (m_renderingContext)
- wglDeleteContext(m_renderingContext);
+ if (m_renderingContext && m_ownsContext)
+ QOpenGLStaticContext::opengl32.wglDeleteContext(m_renderingContext);
releaseDCs();
}
+bool QWindowsGLContext::updateObtainedParams(HDC hdc, int *obtainedSwapInterval)
+{
+ if (!QOpenGLStaticContext::opengl32.wglMakeCurrent(hdc, m_renderingContext)) {
+ qWarning("Failed to make context current.");
+ return false;
+ }
+
+ QWindowsOpenGLContextFormat::current().apply(&m_obtainedFormat);
+
+ if (m_staticContext->wglGetSwapInternalExt && obtainedSwapInterval)
+ *obtainedSwapInterval = m_staticContext->wglGetSwapInternalExt();
+
+ QOpenGLStaticContext::opengl32.wglMakeCurrent(0, 0);
+ return true;
+}
+
void QWindowsGLContext::releaseDCs()
{
const QOpenGLContextData *end = m_windowContexts.end();
@@ -1043,11 +1254,11 @@ void QWindowsGLContext::swapBuffers(QPlatformSurface *surface)
{
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaGl) << __FUNCTION__ << surface;
- if (const QOpenGLContextData *contextData = findByHWND(m_windowContexts, handleOf(surface))) {
- SwapBuffers(contextData->hdc);
- } else {
+
+ if (const QOpenGLContextData *contextData = findByHWND(m_windowContexts, handleOf(surface)))
+ QOpenGLStaticContext::opengl32.swapBuffers(contextData->hdc);
+ else
qWarning("%s: Cannot find window %p", __FUNCTION__, handleOf(surface));
- }
}
bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface)
@@ -1066,11 +1277,11 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface)
// Repeated calls to wglMakeCurrent when vsync is enabled in the driver will
// often result in 100% cpuload. This check is cheap and avoids the problem.
// This is reproducable on NVidia cards and Intel onboard chips.
- if (wglGetCurrentContext() == contextData->renderingContext
- && wglGetCurrentDC() == contextData->hdc) {
+ if (QOpenGLStaticContext::opengl32.wglGetCurrentContext() == contextData->renderingContext
+ && QOpenGLStaticContext::opengl32.wglGetCurrentDC() == contextData->hdc) {
return true;
}
- return wglMakeCurrent(contextData->hdc, contextData->renderingContext);
+ return QOpenGLStaticContext::opengl32.wglMakeCurrent(contextData->hdc, contextData->renderingContext);
}
// Create a new entry.
const QOpenGLContextData newContext(m_renderingContext, hwnd, GetDC(hwnd));
@@ -1079,7 +1290,7 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface)
// Initialize pixel format first time. This will apply to
// the HWND as well and must be done only once.
if (!window->testFlag(QWindowsWindow::OpenGlPixelFormatInitialized)) {
- if (!SetPixelFormat(newContext.hdc, m_pixelFormat, &m_obtainedPixelFormatDescriptor)) {
+ if (!QOpenGLStaticContext::opengl32.setPixelFormat(newContext.hdc, m_pixelFormat, &m_obtainedPixelFormatDescriptor)) {
qErrnoWarning("%s: SetPixelFormat() failed", __FUNCTION__);
ReleaseDC(newContext.hwnd, newContext.hdc);
return false;
@@ -1090,7 +1301,7 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface)
}
m_windowContexts.append(newContext);
- bool success = wglMakeCurrent(newContext.hdc, newContext.renderingContext);
+ bool success = QOpenGLStaticContext::opengl32.wglMakeCurrent(newContext.hdc, newContext.renderingContext);
// Set the swap interval
if (m_staticContext->wglSwapInternalExt) {
@@ -1110,16 +1321,82 @@ void QWindowsGLContext::doneCurrent()
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaGl) << __FUNCTION__ << this << m_windowContexts.size() << "contexts";
#endif // DEBUG_GL
- wglMakeCurrent(0, 0);
+ QOpenGLStaticContext::opengl32.wglMakeCurrent(0, 0);
releaseDCs();
}
-QWindowsGLContext::GL_Proc QWindowsGLContext::getProcAddress(const QByteArray &procName)
+QFunctionPointer QWindowsGLContext::getProcAddress(const QByteArray &procName)
{
- // TODO: Will that work with the calling conventions?
- GL_Proc procAddress = reinterpret_cast<GL_Proc>(wglGetProcAddress(procName.constData()));
+ // We support AllGLFunctionsQueryable, which means this function must be able to
+ // return a function pointer even for functions that are in GL.h and exported
+ // normally from opengl32.dll. wglGetProcAddress() is not guaranteed to work for such
+ // functions, however in QT_OPENGL_DYNAMIC builds QOpenGLFunctions will just blindly
+ // call into here for _any_ OpenGL function. Hence the need to handle these specially
+ // here. The list has to match QOpenGLFunctions. See
+ // QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *).
+ static struct StdFunc {
+ const char *name;
+ void *func;
+ } standardFuncs[] = {
+ { "glBindTexture", (void *) QOpenGLStaticContext::opengl32.glBindTexture },
+ { "glBlendFunc", (void *) QOpenGLStaticContext::opengl32.glBlendFunc },
+ { "glClear", (void *) QOpenGLStaticContext::opengl32.glClear },
+ { "glClearColor", (void *) QOpenGLStaticContext::opengl32.glClearColor },
+ { "glClearStencil", (void *) QOpenGLStaticContext::opengl32.glClearStencil },
+ { "glColorMask", (void *) QOpenGLStaticContext::opengl32.glColorMask },
+ { "glCopyTexImage2D", (void *) QOpenGLStaticContext::opengl32.glCopyTexImage2D },
+ { "glCopyTexSubImage2D", (void *) QOpenGLStaticContext::opengl32.glCopyTexSubImage2D },
+ { "glCullFace", (void *) QOpenGLStaticContext::opengl32.glCullFace },
+ { "glDeleteTextures", (void *) QOpenGLStaticContext::opengl32.glDeleteTextures },
+ { "glDepthFunc", (void *) QOpenGLStaticContext::opengl32.glDepthFunc },
+ { "glDepthMask", (void *) QOpenGLStaticContext::opengl32.glDepthMask },
+ { "glDisable", (void *) QOpenGLStaticContext::opengl32.glDisable },
+ { "glDrawArrays", (void *) QOpenGLStaticContext::opengl32.glDrawArrays },
+ { "glDrawElements", (void *) QOpenGLStaticContext::opengl32.glDrawElements },
+ { "glEnable", (void *) QOpenGLStaticContext::opengl32.glEnable },
+ { "glFinish", (void *) QOpenGLStaticContext::opengl32.glFinish },
+ { "glFlush", (void *) QOpenGLStaticContext::opengl32.glFlush },
+ { "glFrontFace", (void *) QOpenGLStaticContext::opengl32.glFrontFace },
+ { "glGenTextures", (void *) QOpenGLStaticContext::opengl32.glGenTextures },
+ { "glGetBooleanv", (void *) QOpenGLStaticContext::opengl32.glGetBooleanv },
+ { "glGetError", (void *) QOpenGLStaticContext::opengl32.glGetError },
+ { "glGetFloatv", (void *) QOpenGLStaticContext::opengl32.glGetFloatv },
+ { "glGetIntegerv", (void *) QOpenGLStaticContext::opengl32.glGetIntegerv },
+ { "glGetString", (void *) QOpenGLStaticContext::opengl32.glGetString },
+ { "glGetTexParameterfv", (void *) QOpenGLStaticContext::opengl32.glGetTexParameterfv },
+ { "glGetTexParameteriv", (void *) QOpenGLStaticContext::opengl32.glGetTexParameteriv },
+ { "glHint", (void *) QOpenGLStaticContext::opengl32.glHint },
+ { "glIsEnabled", (void *) QOpenGLStaticContext::opengl32.glIsEnabled },
+ { "glIsTexture", (void *) QOpenGLStaticContext::opengl32.glIsTexture },
+ { "glLineWidth", (void *) QOpenGLStaticContext::opengl32.glLineWidth },
+ { "glPixelStorei", (void *) QOpenGLStaticContext::opengl32.glPixelStorei },
+ { "glPolygonOffset", (void *) QOpenGLStaticContext::opengl32.glPolygonOffset },
+ { "glReadPixels", (void *) QOpenGLStaticContext::opengl32.glReadPixels },
+ { "glScissor", (void *) QOpenGLStaticContext::opengl32.glScissor },
+ { "glStencilFunc", (void *) QOpenGLStaticContext::opengl32.glStencilFunc },
+ { "glStencilMask", (void *) QOpenGLStaticContext::opengl32.glStencilMask },
+ { "glStencilOp", (void *) QOpenGLStaticContext::opengl32.glStencilOp },
+ { "glTexImage2D", (void *) QOpenGLStaticContext::opengl32.glTexImage2D },
+ { "glTexParameterf", (void *) QOpenGLStaticContext::opengl32.glTexParameterf },
+ { "glTexParameterfv", (void *) QOpenGLStaticContext::opengl32.glTexParameterfv },
+ { "glTexParameteri", (void *) QOpenGLStaticContext::opengl32.glTexParameteri },
+ { "glTexParameteriv", (void *) QOpenGLStaticContext::opengl32.glTexParameteriv },
+ { "glTexSubImage2D", (void *) QOpenGLStaticContext::opengl32.glTexSubImage2D },
+ { "glViewport", (void *) QOpenGLStaticContext::opengl32.glViewport },
+
+ { "glClearDepth", (void *) QOpenGLStaticContext::opengl32.glClearDepth },
+ { "glDepthRange", (void *) QOpenGLStaticContext::opengl32.glDepthRange },
+ };
+ for (size_t i = 0; i < sizeof(standardFuncs) / sizeof(StdFunc); ++i)
+ if (procName == standardFuncs[i].name)
+ return reinterpret_cast<QFunctionPointer>(standardFuncs[i].func);
+
+ // Even though we use QFunctionPointer, it does not mean the function can be called.
+ // It will need to be cast to the proper function type with the correct calling
+ // convention. QFunctionPointer is nothing more than a glorified void* here.
+ QFunctionPointer procAddress = reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress(procName.constData()));
if (QWindowsContext::verbose > 1)
- qCDebug(lcQpaGl) << __FUNCTION__ << procName << wglGetCurrentContext() << "returns" << procAddress;
+ qCDebug(lcQpaGl) << __FUNCTION__ << procName << QOpenGLStaticContext::opengl32.wglGetCurrentContext() << "returns" << procAddress;
if (!procAddress)
qWarning("%s: Unable to resolve '%s'", __FUNCTION__, procName.constData());
return procAddress;
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h
index c6b477128a..0afeb67a65 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.h
+++ b/src/plugins/platforms/windows/qwindowsglcontext.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -44,10 +44,9 @@
#include "array.h"
#include "qtwindows_additional.h"
+#include "qwindowsopenglcontext.h"
-#include <qpa/qplatformopenglcontext.h>
#include <QtGui/QOpenGLContext>
-#include <QtCore/QSharedPointer>
QT_BEGIN_NAMESPACE
@@ -81,6 +80,8 @@ struct QOpenGLContextData
HDC hdc;
};
+class QOpenGLStaticContext;
+
struct QWindowsOpenGLContextFormat
{
QWindowsOpenGLContextFormat();
@@ -94,7 +95,87 @@ struct QWindowsOpenGLContextFormat
QDebug operator<<(QDebug d, const QWindowsOpenGLContextFormat &);
-class QOpenGLStaticContext
+struct QWindowsOpengl32DLL
+{
+ bool init(bool softwareRendering);
+ void *moduleHandle() const { return m_lib; }
+ bool moduleIsNotOpengl32() const { return m_nonOpengl32; }
+
+ // Wrappers. Always use these instead of SwapBuffers/wglSwapBuffers/etc.
+ BOOL swapBuffers(HDC dc);
+ BOOL setPixelFormat(HDC dc, int pf, const PIXELFORMATDESCRIPTOR *pfd);
+
+ // WGL
+ HGLRC (WINAPI * wglCreateContext)(HDC dc);
+ BOOL (WINAPI * wglDeleteContext)(HGLRC context);
+ HGLRC (WINAPI * wglGetCurrentContext)();
+ HDC (WINAPI * wglGetCurrentDC)();
+ PROC (WINAPI * wglGetProcAddress)(LPCSTR name);
+ BOOL (WINAPI * wglMakeCurrent)(HDC dc, HGLRC context);
+ BOOL (WINAPI * wglShareLists)(HGLRC context1, HGLRC context2);
+
+ // GL1+GLES2 common
+ void (APIENTRY * glBindTexture)(GLenum target, GLuint texture);
+ void (APIENTRY * glBlendFunc)(GLenum sfactor, GLenum dfactor);
+ void (APIENTRY * glClear)(GLbitfield mask);
+ void (APIENTRY * glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+ void (APIENTRY * glClearStencil)(GLint s);
+ void (APIENTRY * glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+ void (APIENTRY * glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+ void (APIENTRY * glCopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+ void (APIENTRY * glCullFace)(GLenum mode);
+ void (APIENTRY * glDeleteTextures)(GLsizei n, const GLuint* textures);
+ void (APIENTRY * glDepthFunc)(GLenum func);
+ void (APIENTRY * glDepthMask)(GLboolean flag);
+ void (APIENTRY * glDisable)(GLenum cap);
+ void (APIENTRY * glDrawArrays)(GLenum mode, GLint first, GLsizei count);
+ void (APIENTRY * glDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
+ void (APIENTRY * glEnable)(GLenum cap);
+ void (APIENTRY * glFinish)();
+ void (APIENTRY * glFlush)();
+ void (APIENTRY * glFrontFace)(GLenum mode);
+ void (APIENTRY * glGenTextures)(GLsizei n, GLuint* textures);
+ void (APIENTRY * glGetBooleanv)(GLenum pname, GLboolean* params);
+ GLenum (APIENTRY * glGetError)();
+ void (APIENTRY * glGetFloatv)(GLenum pname, GLfloat* params);
+ void (APIENTRY * glGetIntegerv)(GLenum pname, GLint* params);
+ const GLubyte * (APIENTRY * glGetString)(GLenum name);
+ void (APIENTRY * glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat* params);
+ void (APIENTRY * glGetTexParameteriv)(GLenum target, GLenum pname, GLint* params);
+ void (APIENTRY * glHint)(GLenum target, GLenum mode);
+ GLboolean (APIENTRY * glIsEnabled)(GLenum cap);
+ GLboolean (APIENTRY * glIsTexture)(GLuint texture);
+ void (APIENTRY * glLineWidth)(GLfloat width);
+ void (APIENTRY * glPixelStorei)(GLenum pname, GLint param);
+ void (APIENTRY * glPolygonOffset)(GLfloat factor, GLfloat units);
+ void (APIENTRY * glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
+ void (APIENTRY * glScissor)(GLint x, GLint y, GLsizei width, GLsizei height);
+ void (APIENTRY * glStencilFunc)(GLenum func, GLint ref, GLuint mask);
+ void (APIENTRY * glStencilMask)(GLuint mask);
+ void (APIENTRY * glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass);
+ void (APIENTRY * glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+ void (APIENTRY * glTexParameterf)(GLenum target, GLenum pname, GLfloat param);
+ void (APIENTRY * glTexParameterfv)(GLenum target, GLenum pname, const GLfloat* params);
+ void (APIENTRY * glTexParameteri)(GLenum target, GLenum pname, GLint param);
+ void (APIENTRY * glTexParameteriv)(GLenum target, GLenum pname, const GLint* params);
+ void (APIENTRY * glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
+ void (APIENTRY * glViewport)(GLint x, GLint y, GLsizei width, GLsizei height);
+
+ // GL only
+ void (APIENTRY * glClearDepth)(GLdouble depth);
+ void (APIENTRY * glDepthRange)(GLdouble zNear, GLdouble zFar);
+
+private:
+ void *resolve(const char *name);
+ HMODULE m_lib;
+ bool m_nonOpengl32;
+
+ // For Mesa llvmpipe shipped with a name other than opengl32.dll
+ BOOL (WINAPI * wglSwapBuffers)(HDC dc);
+ BOOL (WINAPI * wglSetPixelFormat)(HDC dc, int pf, const PIXELFORMATDESCRIPTOR *pfd);
+};
+
+class QOpenGLStaticContext : public QWindowsStaticOpenGLContext
{
Q_DISABLE_COPY(QOpenGLStaticContext)
QOpenGLStaticContext();
@@ -125,9 +206,17 @@ public:
bool hasExtensions() const
{ return wglGetPixelFormatAttribIVARB && wglChoosePixelFormatARB && wglCreateContextAttribsARB; }
- static QOpenGLStaticContext *create();
+ static QOpenGLStaticContext *create(bool softwareRendering = false);
static QByteArray getGlString(unsigned int which);
+ QWindowsOpenGLContext *createContext(QOpenGLContext *context);
+ void *moduleHandle() const { return opengl32.moduleHandle(); }
+ QOpenGLContext::OpenGLModuleType moduleType() const { return QOpenGLContext::LibGL; }
+
+ // For a regular opengl32.dll report the ThreadedOpenGL capability.
+ // For others, which are likely to be software-only, don't.
+ bool supportsThreadedOpenGL() const { return !opengl32.moduleIsNotOpengl32(); }
+
const QByteArray vendor;
const QByteArray renderer;
const QByteArray extensionNames;
@@ -139,37 +228,39 @@ public:
WglCreateContextAttribsARB wglCreateContextAttribsARB;
WglSwapInternalExt wglSwapInternalExt;
WglGetSwapInternalExt wglGetSwapInternalExt;
+
+ static QWindowsOpengl32DLL opengl32;
};
QDebug operator<<(QDebug d, const QOpenGLStaticContext &);
-class QWindowsGLContext : public QPlatformOpenGLContext
+class QWindowsGLContext : public QWindowsOpenGLContext
{
public:
- typedef QSharedPointer<QOpenGLStaticContext> QOpenGLStaticContextPtr;
-
- explicit QWindowsGLContext(const QOpenGLStaticContextPtr &staticContext,
- QOpenGLContext *context);
- virtual ~QWindowsGLContext();
- bool isSharing() const { return m_context->shareHandle(); }
- bool isValid() const { return m_renderingContext; }
- virtual QSurfaceFormat format() const { return m_obtainedFormat; }
+ explicit QWindowsGLContext(QOpenGLStaticContext *staticContext, QOpenGLContext *context);
+ ~QWindowsGLContext();
+ bool isSharing() const Q_DECL_OVERRIDE { return m_context->shareHandle(); }
+ bool isValid() const Q_DECL_OVERRIDE { return m_renderingContext; }
+ QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_obtainedFormat; }
- virtual void swapBuffers(QPlatformSurface *surface);
+ void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE;
- virtual bool makeCurrent(QPlatformSurface *surface);
- virtual void doneCurrent();
+ bool makeCurrent(QPlatformSurface *surface) Q_DECL_OVERRIDE;
+ void doneCurrent() Q_DECL_OVERRIDE;
typedef void (*GL_Proc) ();
- virtual GL_Proc getProcAddress(const QByteArray &procName);
+ QFunctionPointer getProcAddress(const QByteArray &procName) Q_DECL_OVERRIDE;
+
+ HGLRC renderingContext() const { return m_renderingContext; }
- HGLRC renderingContext() const { return m_renderingContext; }
+ void *nativeContext() const Q_DECL_OVERRIDE { return m_renderingContext; }
private:
inline void releaseDCs();
+ bool updateObtainedParams(HDC hdc, int *obtainedSwapInterval = 0);
- const QOpenGLStaticContextPtr m_staticContext;
+ QOpenGLStaticContext *m_staticContext;
QOpenGLContext *m_context;
QSurfaceFormat m_obtainedFormat;
HGLRC m_renderingContext;
@@ -178,6 +269,7 @@ private:
int m_pixelFormat;
bool m_extensionsUsed;
int m_swapInterval;
+ bool m_ownsContext;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsguieventdispatcher.h b/src/plugins/platforms/windows/qwindowsguieventdispatcher.h
index 65ef912b43..6f67c47279 100644
--- a/src/plugins/platforms/windows/qwindowsguieventdispatcher.h
+++ b/src/plugins/platforms/windows/qwindowsguieventdispatcher.h
@@ -59,8 +59,8 @@ public:
static const char *windowsMessageName(UINT msg);
- virtual bool QT_ENSURE_STACK_ALIGNED_FOR_SSE processEvents(QEventLoop::ProcessEventsFlags flags);
- virtual void sendPostedEvents();
+ bool QT_ENSURE_STACK_ALIGNED_FOR_SSE processEvents(QEventLoop::ProcessEventsFlags flags) Q_DECL_OVERRIDE;
+ void sendPostedEvents() Q_DECL_OVERRIDE;
private:
QEventLoop::ProcessEventsFlags m_flags;
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.h b/src/plugins/platforms/windows/qwindowsinputcontext.h
index 31a076cbf8..51ea8adf1e 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.h
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.h
@@ -68,9 +68,9 @@ public:
explicit QWindowsInputContext();
~QWindowsInputContext();
- virtual void reset();
- virtual void update(Qt::InputMethodQueries);
- virtual void invokeAction(QInputMethod::Action, int cursorPosition);
+ void reset() Q_DECL_OVERRIDE;
+ void update(Qt::InputMethodQueries) Q_DECL_OVERRIDE;
+ void invokeAction(QInputMethod::Action, int cursorPosition) Q_DECL_OVERRIDE;
static QWindowsInputContext *instance();
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 78bf833526..529dd75ed5 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -43,19 +43,7 @@
#include "qwindowsintegration.h"
#include "qwindowswindow.h"
#include "qwindowscontext.h"
-
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
-# include "qwindowseglcontext.h"
-# include <QtGui/QOpenGLContext>
-#endif
-
-#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2)
-# include "qwindowsglcontext.h"
-#endif
-
-#if !defined(QT_NO_OPENGL)
-# include <QtGui/QOpenGLFunctions>
-#endif
+#include "qwindowsopenglcontext.h"
#include "qwindowsscreen.h"
#include "qwindowstheme.h"
@@ -89,6 +77,19 @@
#include <QtCore/QDebug>
#include <QtCore/QVariant>
+#include <limits.h>
+
+#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
+# include "qwindowseglcontext.h"
+#endif
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2)
+# include "qwindowsglcontext.h"
+#endif
+
+#ifndef Q_OS_WINCE
+# include "qwindowsopengltester.h"
+#endif
+
QT_BEGIN_NAMESPACE
/*!
@@ -134,15 +135,9 @@ QT_BEGIN_NAMESPACE
struct QWindowsIntegrationPrivate
{
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- typedef QSharedPointer<QWindowsEGLStaticContext> QEGLStaticContextPtr;
-#endif
-#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2)
- typedef QSharedPointer<QOpenGLStaticContext> QOpenGLStaticContextPtr;
-#endif
-
explicit QWindowsIntegrationPrivate(const QStringList &paramList);
~QWindowsIntegrationPrivate();
+ bool ensureStaticOpenGLContext();
unsigned m_options;
QWindowsContext m_context;
@@ -153,12 +148,9 @@ struct QWindowsIntegrationPrivate
QWindowsDrag m_drag;
# endif
#endif
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- QEGLStaticContextPtr m_staticEGLContext;
-#endif
-#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2)
- QOpenGLStaticContextPtr m_staticOpenGLContext;
-#endif
+#ifndef QT_NO_OPENGL
+ QSharedPointer<QWindowsStaticOpenGLContext> m_staticOpenGLContext;
+#endif // QT_NO_OPENGL
QScopedPointer<QPlatformInputContext> m_inputContext;
#ifndef QT_NO_ACCESSIBILITY
QWindowsAccessibility m_accessibility;
@@ -166,8 +158,32 @@ struct QWindowsIntegrationPrivate
QWindowsServices m_services;
};
+template <typename IntType>
+bool parseIntOption(const QString &parameter,const QLatin1String &option,
+ IntType minimumValue, IntType maximumValue, IntType *target)
+{
+ const int valueLength = parameter.size() - option.size() - 1;
+ if (valueLength < 1 || !parameter.startsWith(option) || parameter.at(option.size()) != QLatin1Char('='))
+ return false;
+ bool ok;
+ const QStringRef valueRef = parameter.rightRef(valueLength);
+ const int value = valueRef.toInt(&ok);
+ if (ok) {
+ if (value >= minimumValue && value <= maximumValue)
+ *target = static_cast<IntType>(value);
+ else {
+ qWarning() << "Value" << value << "for option" << option << "out of range"
+ << minimumValue << ".." << maximumValue;
+ }
+ } else {
+ qWarning() << "Invalid value" << valueRef << "for option" << option;
+ }
+ return true;
+}
+
static inline unsigned parseOptions(const QStringList &paramList,
- int *tabletAbsoluteRange)
+ int *tabletAbsoluteRange,
+ QtWindows::ProcessDpiAwareness *dpiAwareness)
{
unsigned options = 0;
foreach (const QString &param, paramList) {
@@ -187,10 +203,11 @@ static inline unsigned parseOptions(const QStringList &paramList,
options |= QWindowsIntegration::DisableArb;
} else if (param == QLatin1String("nomousefromtouch")) {
options |= QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch;
- } else if (param.startsWith(QLatin1String("verbose="))) {
- QWindowsContext::verbose = param.right(param.size() - 8).toInt();
- } else if (param.startsWith(QLatin1String("tabletabsoluterange="))) {
- *tabletAbsoluteRange = param.rightRef(param.size() - 20).toInt();
+ } 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 {
+ qWarning() << "Unknown option" << param;
}
}
return options;
@@ -201,9 +218,13 @@ QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList &paramL
, m_fontDatabase(0)
{
int tabletAbsoluteRange = -1;
- m_options = parseOptions(paramList, &tabletAbsoluteRange);
+ // Default to per-monitor awareness to avoid being scaled when monitors with different DPI
+ // are connected to Windows 8.1
+ QtWindows::ProcessDpiAwareness dpiAwareness = QtWindows::ProcessPerMonitorDpiAware;
+ m_options = parseOptions(paramList, &tabletAbsoluteRange, &dpiAwareness);
if (tabletAbsoluteRange >= 0)
m_context.setTabletAbsoluteRange(tabletAbsoluteRange);
+ m_context.setProcessDpiAwareness(dpiAwareness);
}
QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate()
@@ -242,12 +263,7 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co
case OpenGL:
return true;
case ThreadedOpenGL:
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- return QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL
- ? QWindowsEGLContext::hasThreadedOpenGLCapability() : true;
-# else
- return true;
-# endif // QT_OPENGL_ES_2
+ return d->ensureStaticOpenGLContext() ? d->m_staticOpenGLContext->supportsThreadedOpenGL() : false;
#endif // !QT_NO_OPENGL
case WindowMasks:
return true;
@@ -257,6 +273,8 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co
return true;
case RasterGLSurface:
return true;
+ case AllGLFunctionsQueryable:
+ return true;
default:
return QPlatformIntegration::hasCapability(cap);
}
@@ -273,8 +291,7 @@ QWindowsWindowData QWindowsIntegration::createWindowData(QWindow *window) const
if (customMarginsV.isValid())
requested.customMargins = qvariant_cast<QMargins>(customMarginsV);
- const QWindowsWindowData obtained
- = QWindowsWindowData::create(window, requested, window->title());
+ QWindowsWindowData obtained = QWindowsWindowData::create(window, requested, window->title());
qCDebug(lcQpaWindows).nospace()
<< __FUNCTION__ << '<' << window
<< "\n Requested: " << requested.geometry << "frame incl.: "
@@ -292,6 +309,11 @@ QWindowsWindowData QWindowsIntegration::createWindowData(QWindow *window) const
QWindowSystemInterface::handleGeometryChange(window, obtained.geometry);
}
+#ifndef QT_NO_OPENGL
+ d->ensureStaticOpenGLContext();
+ obtained.staticOpenGLContext = d->m_staticOpenGLContext;
+#endif // QT_NO_OPENGL
+
return obtained;
}
@@ -303,32 +325,80 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
}
#ifndef QT_NO_OPENGL
-QPlatformOpenGLContext
- *QWindowsIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
+static QWindowsStaticOpenGLContext *q_staticOpenGLContext = 0;
+
+QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::create()
{
- qCDebug(lcQpaGl) << __FUNCTION__ << context->format();
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL) {
- if (d->m_staticEGLContext.isNull()) {
- QWindowsEGLStaticContext *staticContext = QWindowsEGLStaticContext::create();
- if (!staticContext)
- return 0;
- d->m_staticEGLContext = QSharedPointer<QWindowsEGLStaticContext>(staticContext);
+ QWindowsStaticOpenGLContext *ctx = 0;
+
+#if defined(QT_OPENGL_DYNAMIC)
+ const QByteArray requested = qgetenv("QT_OPENGL"); // angle, desktop, software
+ const bool angleRequested = QCoreApplication::testAttribute(Qt::AA_UseOpenGLES) || requested == QByteArrayLiteral("angle");
+ const bool desktopRequested = QCoreApplication::testAttribute(Qt::AA_UseDesktopOpenGL) || requested == QByteArrayLiteral("desktop");
+ const bool softwareRequested = QCoreApplication::testAttribute(Qt::AA_UseSoftwareOpenGL) || requested == QByteArrayLiteral("software");
+
+ // If ANGLE is requested, use it, don't try anything else.
+ if (angleRequested) {
+ ctx = QWindowsEGLStaticContext::create();
+ } else {
+ // If opengl32.dll seems to be OpenGL 2.x capable, or desktop OpenGL is requested, use it.
+ if (!softwareRequested && (desktopRequested || QWindowsOpenGLTester::testDesktopGL()))
+ ctx = QOpenGLStaticContext::create();
+ // If failed and desktop OpenGL is not explicitly requested, try ANGLE.
+ if (!ctx && !desktopRequested && !softwareRequested)
+ ctx = QWindowsEGLStaticContext::create();
+ // Try software.
+ if (!ctx) {
+ ctx = QOpenGLStaticContext::create(true);
+ // If software was explicitly requested but failed, try the regular one.
+ if (!ctx && softwareRequested && QWindowsOpenGLTester::testDesktopGL())
+ ctx = QOpenGLStaticContext::create();
}
- return new QWindowsEGLContext(d->m_staticEGLContext, context->format(), context->shareHandle());
}
+#elif defined(QT_OPENGL_ES_2)
+ ctx = QWindowsEGLStaticContext::create();
+#elif !defined(QT_NO_OPENGL)
+ ctx = QOpenGLStaticContext::create();
#endif
-#if !defined(QT_OPENGL_ES_2)
- if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
- if (d->m_staticOpenGLContext.isNull())
- d->m_staticOpenGLContext =
- QSharedPointer<QOpenGLStaticContext>(QOpenGLStaticContext::create());
- QScopedPointer<QWindowsGLContext> result(new QWindowsGLContext(d->m_staticOpenGLContext, context));
- return result->isValid() ? result.take() : 0;
+
+ q_staticOpenGLContext = ctx;
+
+ return ctx;
+}
+
+bool QWindowsIntegrationPrivate::ensureStaticOpenGLContext()
+{
+ if (m_staticOpenGLContext.isNull())
+ m_staticOpenGLContext = QSharedPointer<QWindowsStaticOpenGLContext>(QWindowsStaticOpenGLContext::create());
+ return !m_staticOpenGLContext.isNull();
+}
+
+QPlatformOpenGLContext *QWindowsIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
+{
+ qCDebug(lcQpaGl) << __FUNCTION__ << context->format();
+ if (d->ensureStaticOpenGLContext()) {
+ QScopedPointer<QWindowsOpenGLContext> result(d->m_staticOpenGLContext->createContext(context));
+ if (result->isValid())
+ return result.take();
}
-#endif // !QT_OPENGL_ES_2
return 0;
}
+
+QOpenGLContext::OpenGLModuleType QWindowsIntegration::openGLModuleType()
+{
+#if defined(QT_OPENGL_ES_2)
+ return QOpenGLContext::LibGLES;
+#elif !defined(QT_OPENGL_DYNAMIC)
+ return QOpenGLContext::LibGL;
+#else
+ return d->ensureStaticOpenGLContext() ? d->m_staticOpenGLContext->moduleType() : QOpenGLContext::LibGL;
+#endif
+}
+
+QWindowsStaticOpenGLContext *QWindowsIntegration::staticOpenGLContext()
+{
+ return q_staticOpenGLContext;
+}
#endif // !QT_NO_OPENGL
/* Workaround for QTBUG-24205: In 'Auto', pick the FreeType engine for
diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h
index 0f417c8239..cae415ccd9 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.h
+++ b/src/plugins/platforms/windows/qwindowsintegration.h
@@ -52,6 +52,7 @@ QT_BEGIN_NAMESPACE
struct QWindowsIntegrationPrivate;
struct QWindowsWindowData;
class QWindowsWindow;
+class QWindowsStaticOpenGLContext;
class QWindowsIntegration : public QPlatformIntegration
{
@@ -73,28 +74,30 @@ public:
QWindowsWindowData createWindowData(QWindow *window) const;
QPlatformWindow *createPlatformWindow(QWindow *window) const;
#ifndef QT_NO_OPENGL
- virtual QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;
+ QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
+ QOpenGLContext::OpenGLModuleType openGLModuleType();
+ static QWindowsStaticOpenGLContext *staticOpenGLContext();
#endif
- virtual QAbstractEventDispatcher *createEventDispatcher() const;
+ QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
void initialize() Q_DECL_OVERRIDE;
#ifndef QT_NO_CLIPBOARD
- virtual QPlatformClipboard *clipboard() const;
+ QPlatformClipboard *clipboard() const Q_DECL_OVERRIDE;
# ifndef QT_NO_DRAGANDDROP
- virtual QPlatformDrag *drag() const;
+ QPlatformDrag *drag() const Q_DECL_OVERRIDE;
# endif
#endif // !QT_NO_CLIPBOARD
- virtual QPlatformInputContext *inputContext() const;
+ QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE;
#ifndef QT_NO_ACCESSIBILITY
- virtual QPlatformAccessibility *accessibility() const;
+ QPlatformAccessibility *accessibility() const Q_DECL_OVERRIDE;
#endif
- virtual QPlatformFontDatabase *fontDatabase() const;
- virtual QStringList themeNames() const;
- virtual QPlatformTheme *createPlatformTheme(const QString &name) const;
+ QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
+ QStringList themeNames() const Q_DECL_OVERRIDE;
+ QPlatformTheme *createPlatformTheme(const QString &name) const Q_DECL_OVERRIDE;
QPlatformServices *services() const;
- virtual QVariant styleHint(StyleHint hint) const;
+ QVariant styleHint(StyleHint hint) const Q_DECL_OVERRIDE;
- virtual Qt::KeyboardModifiers queryKeyboardModifiers() const;
- virtual QList<int> possibleKeys(const QKeyEvent *e) const;
+ Qt::KeyboardModifiers queryKeyboardModifiers() const Q_DECL_OVERRIDE;
+ QList<int> possibleKeys(const QKeyEvent *e) const Q_DECL_OVERRIDE;
static QWindowsIntegration *instance();
@@ -103,7 +106,7 @@ public:
unsigned options() const;
#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER)
- virtual QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const;
+ QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const Q_DECL_OVERRIDE;
#endif
private:
diff --git a/src/plugins/platforms/windows/qwindowsinternalmimedata.h b/src/plugins/platforms/windows/qwindowsinternalmimedata.h
index 0c12c662c4..08f2d09534 100644
--- a/src/plugins/platforms/windows/qwindowsinternalmimedata.h
+++ b/src/plugins/platforms/windows/qwindowsinternalmimedata.h
@@ -54,9 +54,9 @@ class QDebug;
// Implementation in qwindowsclipboard.cpp.
class QWindowsInternalMimeData : public QInternalMimeData {
public:
- virtual bool hasFormat_sys(const QString &mimetype) const;
- virtual QStringList formats_sys() const;
- virtual QVariant retrieveData_sys(const QString &mimetype, QVariant::Type preferredType) const;
+ bool hasFormat_sys(const QString &mimetype) const Q_DECL_OVERRIDE;
+ QStringList formats_sys() const Q_DECL_OVERRIDE;
+ QVariant retrieveData_sys(const QString &mimetype, QVariant::Type preferredType) const Q_DECL_OVERRIDE;
protected:
virtual IDataObject *retrieveDataObject() const = 0;
diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp
index 3af2cff9a0..37f51e85bd 100644
--- a/src/plugins/platforms/windows/qwindowsmime.cpp
+++ b/src/plugins/platforms/windows/qwindowsmime.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -1035,17 +1035,14 @@ bool QWindowsMimeImage::canConvertToMime(const QString &mimeType, IDataObject *p
bool QWindowsMimeImage::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
{
int cf = getCf(formatetc);
- if (mimeData->hasImage()) {
- if (cf == CF_DIB)
- return true;
- else if (cf == CF_DIBV5) {
- //support DIBV5 conversion only if the image has alpha channel
- QImage image = qvariant_cast<QImage>(mimeData->imageData());
- if (!image.isNull() && image.hasAlphaChannel())
- return true;
- }
- }
- return false;
+ if (!mimeData->hasImage())
+ return false;
+ const QImage image = qvariant_cast<QImage>(mimeData->imageData());
+ if (image.isNull())
+ return false;
+ // QTBUG-11463, deny CF_DIB support for images with alpha to prevent loss of
+ // transparency in conversion.
+ return cf == CF_DIBV5 || (cf == CF_DIB && !image.hasAlphaChannel());
}
bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const
@@ -1442,13 +1439,13 @@ QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const
\sa QWindowsMime
*/
-QWindowsMimeConverter::QWindowsMimeConverter()
+QWindowsMimeConverter::QWindowsMimeConverter() : m_internalMimeCount(0)
{
}
QWindowsMimeConverter::~QWindowsMimeConverter()
{
- qDeleteAll(m_mimes);
+ qDeleteAll(m_mimes.begin(), m_mimes.begin() + m_internalMimeCount);
}
QWindowsMime * QWindowsMimeConverter::converterToMime(const QString &mimeType, IDataObject *pDataObj) const
@@ -1526,6 +1523,7 @@ void QWindowsMimeConverter::ensureInitialized() const
m_mimes << new QWindowsMimeImage << new QLastResortMimes
<< new QWindowsMimeText << new QWindowsMimeURI
<< new QWindowsMimeHtml << new QBuiltInMimes;
+ m_internalMimeCount = m_mimes.size();
}
}
@@ -1552,4 +1550,10 @@ QVariant QWindowsMimeConverter::convertToMime(const QStringList &mimeTypes,
return QVariant();
}
+void QWindowsMimeConverter::registerMime(QWindowsMime *mime)
+{
+ ensureInitialized();
+ m_mimes.append(mime);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsmime.h b/src/plugins/platforms/windows/qwindowsmime.h
index cd0fb4d8b3..e2818422bf 100644
--- a/src/plugins/platforms/windows/qwindowsmime.h
+++ b/src/plugins/platforms/windows/qwindowsmime.h
@@ -89,12 +89,14 @@ public:
QVariant convertToMime(const QStringList &mimeTypes, IDataObject *pDataObj, QVariant::Type preferredType,
QString *format = 0) const;
-private:
- typedef QSharedPointer<QWindowsMime> MimePtr;
+ void registerMime(QWindowsMime *mime);
+ void unregisterMime(QWindowsMime *mime) { m_mimes.removeOne(mime); }
+private:
void ensureInitialized() const;
mutable QList<QWindowsMime *> m_mimes;
+ mutable int m_internalMimeCount;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
index 06c0122bbb..8ec1d8eb2f 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -42,21 +42,12 @@
#include "qwindowsnativeinterface.h"
#include "qwindowswindow.h"
#include "qwindowscontext.h"
-
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
-# include "qwindowseglcontext.h"
-# include <QtGui/QOpenGLContext>
-#endif
-
-#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2)
-# include "qwindowsglcontext.h"
-#endif
-
-#if !defined(QT_NO_OPENGL)
-# include <QtGui/QOpenGLFunctions>
-#endif
+#include "qwindowsopenglcontext.h"
+#include "qwindowsintegration.h"
+#include "qwindowsmime.h"
#include <QtGui/QWindow>
+#include <QtGui/QOpenGLContext>
QT_BEGIN_NAMESPACE
@@ -117,6 +108,16 @@ QVariantMap QWindowsNativeInterface::windowProperties(QPlatformWindow *window) c
return result;
}
+void *QWindowsNativeInterface::nativeResourceForIntegration(const QByteArray &resource)
+{
+#ifndef QT_NO_OPENGL
+ if (resource == QByteArrayLiteral("glhandle"))
+ return QWindowsIntegration::staticOpenGLContext()->moduleHandle();
+#endif
+
+ return 0;
+}
+
#ifndef QT_NO_OPENGL
void *QWindowsNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context)
{
@@ -124,24 +125,14 @@ void *QWindowsNativeInterface::nativeResourceForContext(const QByteArray &resour
qWarning("%s: '%s' requested for null context or context without handle.", __FUNCTION__, resource.constData());
return 0;
}
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL) {
- QWindowsEGLContext *windowsEglContext = static_cast<QWindowsEGLContext *>(context->handle());
- if (resource == QByteArrayLiteral("eglDisplay"))
- return windowsEglContext->eglDisplay();
- if (resource == QByteArrayLiteral("eglContext"))
- return windowsEglContext->eglContext();
- if (resource == QByteArrayLiteral("eglConfig"))
- return windowsEglContext->eglConfig();
- }
-#endif // QT_OPENGL_ES_2 || QT_OPENGL_DYNAMIC
-#if !defined(QT_OPENGL_ES_2)
- if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
- QWindowsGLContext *windowsContext = static_cast<QWindowsGLContext *>(context->handle());
- if (resource == QByteArrayLiteral("renderingContext"))
- return windowsContext->renderingContext();
- }
-#endif // QT_OPENGL_ES_2 || QT_OPENGL_DYNAMIC
+
+ QWindowsOpenGLContext *glcontext = static_cast<QWindowsOpenGLContext *>(context->handle());
+ if (resource == QByteArrayLiteral("renderingContext") || resource == QByteArrayLiteral("eglContext"))
+ return glcontext->nativeContext();
+ if (resource == QByteArrayLiteral("eglDisplay"))
+ return glcontext->nativeDisplay();
+ if (resource == QByteArrayLiteral("eglConfig"))
+ return glcontext->nativeConfig();
qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
return 0;
@@ -182,4 +173,19 @@ void QWindowsNativeInterface::setAsyncExpose(bool value)
QWindowsContext::instance()->setAsyncExpose(value);
}
+void QWindowsNativeInterface::registerWindowsMime(void *mimeIn)
+{
+ QWindowsContext::instance()->mimeConverter().registerMime(reinterpret_cast<QWindowsMime *>(mimeIn));
+}
+
+void QWindowsNativeInterface::unregisterWindowsMime(void *mimeIn)
+{
+ QWindowsContext::instance()->mimeConverter().unregisterMime(reinterpret_cast<QWindowsMime *>(mimeIn));
+}
+
+int QWindowsNativeInterface::registerMimeType(const QString &mimeType)
+{
+ return QWindowsMime::registerMimeType(mimeType);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.h b/src/plugins/platforms/windows/qwindowsnativeinterface.h
index 20100d0f49..1afa0571a0 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.h
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.h
@@ -66,11 +66,13 @@ class QWindowsNativeInterface : public QPlatformNativeInterface
{
Q_OBJECT
Q_PROPERTY(bool asyncExpose READ asyncExpose WRITE setAsyncExpose)
+
public:
+ void *nativeResourceForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE;
#ifndef QT_NO_OPENGL
- virtual void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context);
+ void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) Q_DECL_OVERRIDE;
#endif
- virtual void *nativeResourceForWindow(const QByteArray &resource, QWindow *window);
+ void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) Q_DECL_OVERRIDE;
Q_INVOKABLE void *createMessageWindow(const QString &classNameTemplate,
const QString &windowName,
@@ -80,13 +82,17 @@ public:
Q_INVOKABLE void beep() { MessageBeep(MB_OK); } // For QApplication
+ Q_INVOKABLE void registerWindowsMime(void *mimeIn);
+ Q_INVOKABLE void unregisterWindowsMime(void *mime);
+ Q_INVOKABLE int registerMimeType(const QString &mimeType);
+
bool asyncExpose() const;
void setAsyncExpose(bool value);
- QVariantMap windowProperties(QPlatformWindow *window) const;
- QVariant windowProperty(QPlatformWindow *window, const QString &name) const;
- QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const;
- void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value);
+ QVariantMap windowProperties(QPlatformWindow *window) const Q_DECL_OVERRIDE;
+ QVariant windowProperty(QPlatformWindow *window, const QString &name) const Q_DECL_OVERRIDE;
+ QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const Q_DECL_OVERRIDE;
+ void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value) Q_DECL_OVERRIDE;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsopenglcontext.h b/src/plugins/platforms/windows/qwindowsopenglcontext.h
new file mode 100644
index 0000000000..555af72f37
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowsopenglcontext.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSOPENGLCONTEXT_H
+#define QWINDOWSOPENGLCONTEXT_H
+
+#include <QtGui/QOpenGLContext>
+#include <qpa/qplatformopenglcontext.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_OPENGL
+
+class QWindowsOpenGLContext;
+
+class QWindowsStaticOpenGLContext
+{
+public:
+ static QWindowsStaticOpenGLContext *create();
+ virtual ~QWindowsStaticOpenGLContext() { }
+
+ virtual QWindowsOpenGLContext *createContext(QOpenGLContext *context) = 0;
+ virtual void *moduleHandle() const = 0;
+ virtual QOpenGLContext::OpenGLModuleType moduleType() const = 0;
+ virtual bool supportsThreadedOpenGL() const { return false; }
+
+ // If the windowing system interface needs explicitly created window surfaces (like EGL),
+ // reimplement these.
+ virtual void *createWindowSurface(void * /*nativeWindow*/, void * /*nativeConfig*/) { return 0; }
+ virtual void destroyWindowSurface(void * /*nativeSurface*/) { }
+};
+
+class QWindowsOpenGLContext : public QPlatformOpenGLContext
+{
+public:
+ virtual ~QWindowsOpenGLContext() { }
+
+ // Returns the native context handle (e.g. HGLRC for WGL, EGLContext for EGL).
+ virtual void *nativeContext() const = 0;
+
+ // These should be implemented only for some winsys interfaces, for example EGL.
+ // For others, like WGL, they are not relevant.
+ virtual void *nativeDisplay() const { return 0; }
+ virtual void *nativeConfig() const { return 0; }
+};
+
+#endif // QT_NO_OPENGL
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSOPENGLCONTEXT_H
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp
new file mode 100644
index 0000000000..9ee62e6d56
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwindowsopengltester.h"
+#include "qt_windows.h"
+#include "qwindowscontext.h"
+
+QT_BEGIN_NAMESPACE
+
+bool QWindowsOpenGLTester::testDesktopGL()
+{
+ HMODULE lib = 0;
+ HWND wnd = 0;
+ HDC dc = 0;
+ HGLRC context = 0;
+ LPCTSTR className = L"qtopengltest";
+
+ HGLRC (WINAPI * CreateContext)(HDC dc) = 0;
+ BOOL (WINAPI * DeleteContext)(HGLRC context) = 0;
+ BOOL (WINAPI * MakeCurrent)(HDC dc, HGLRC context) = 0;
+ PROC (WINAPI * WGL_GetProcAddress)(LPCSTR name) = 0;
+
+ bool result = false;
+
+ // Test #1: Load opengl32.dll and try to resolve an OpenGL 2 function.
+ // This will typically fail on systems that do not have a real OpenGL driver.
+ lib = LoadLibraryA("opengl32.dll");
+ if (lib) {
+ CreateContext = reinterpret_cast<HGLRC (WINAPI *)(HDC)>(::GetProcAddress(lib, "wglCreateContext"));
+ if (!CreateContext)
+ goto cleanup;
+ DeleteContext = reinterpret_cast<BOOL (WINAPI *)(HGLRC)>(::GetProcAddress(lib, "wglDeleteContext"));
+ if (!DeleteContext)
+ goto cleanup;
+ MakeCurrent = reinterpret_cast<BOOL (WINAPI *)(HDC, HGLRC)>(::GetProcAddress(lib, "wglMakeCurrent"));
+ if (!MakeCurrent)
+ goto cleanup;
+ WGL_GetProcAddress = reinterpret_cast<PROC (WINAPI *)(LPCSTR)>(::GetProcAddress(lib, "wglGetProcAddress"));
+ if (!WGL_GetProcAddress)
+ goto cleanup;
+
+ WNDCLASS wclass;
+ wclass.cbClsExtra = 0;
+ wclass.cbWndExtra = 0;
+ wclass.hInstance = (HINSTANCE) GetModuleHandle(0);
+ wclass.hIcon = 0;
+ wclass.hCursor = 0;
+ wclass.hbrBackground = (HBRUSH) (COLOR_BACKGROUND);
+ wclass.lpszMenuName = 0;
+ wclass.lpfnWndProc = DefWindowProc;
+ wclass.lpszClassName = className;
+ wclass.style = CS_OWNDC;
+ if (!RegisterClass(&wclass))
+ goto cleanup;
+ wnd = CreateWindow(className, L"qtopenglproxytest", WS_OVERLAPPED,
+ 0, 0, 640, 480, 0, 0, wclass.hInstance, 0);
+ if (!wnd)
+ goto cleanup;
+ dc = GetDC(wnd);
+ if (!dc)
+ goto cleanup;
+
+ PIXELFORMATDESCRIPTOR pfd;
+ memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
+ pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
+ pfd.nVersion = 1;
+ pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_GENERIC_FORMAT;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ // Use the GDI functions. Under the hood this will call the wgl variants in opengl32.dll.
+ int pixelFormat = ChoosePixelFormat(dc, &pfd);
+ if (!pixelFormat)
+ goto cleanup;
+ if (!SetPixelFormat(dc, pixelFormat, &pfd))
+ goto cleanup;
+ context = CreateContext(dc);
+ if (!context)
+ goto cleanup;
+ if (!MakeCurrent(dc, context))
+ goto cleanup;
+
+ // Now that there is finally a context current, try doing something useful.
+ if (WGL_GetProcAddress("glCreateShader")) {
+ result = true;
+ qCDebug(lcQpaGl, "OpenGL 2.0 entry points available");
+ } else {
+ qCDebug(lcQpaGl, "OpenGL 2.0 entry points not found");
+ }
+ } else {
+ qCDebug(lcQpaGl, "Failed to load opengl32.dll");
+ }
+
+cleanup:
+ if (MakeCurrent)
+ MakeCurrent(0, 0);
+ if (context)
+ DeleteContext(context);
+ if (dc && wnd)
+ ReleaseDC(wnd, dc);
+ if (wnd) {
+ DestroyWindow(wnd);
+ UnregisterClass(className, GetModuleHandle(0));
+ }
+ // No FreeLibrary. Some implementations, Mesa in particular, deadlock when trying to unload.
+
+ return result;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.h b/src/plugins/platforms/windows/qwindowsopengltester.h
new file mode 100644
index 0000000000..f7cd7e3005
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowsopengltester.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtwindowsglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsOpenGLTester
+{
+public:
+ static bool testDesktopGL();
+};
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index a6e2aabaf0..bcdb8a2352 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -68,6 +68,21 @@ static inline QDpi deviceDPI(HDC hdc)
return QDpi(GetDeviceCaps(hdc, LOGPIXELSX), GetDeviceCaps(hdc, LOGPIXELSY));
}
+#ifndef Q_OS_WINCE
+
+static inline QDpi monitorDPI(HMONITOR hMonitor)
+{
+ if (QWindowsContext::shcoredll.isValid()) {
+ UINT dpiX;
+ UINT dpiY;
+ if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, 0, &dpiX, &dpiY)))
+ return QDpi(dpiX, dpiY);
+ }
+ return QDpi(0, 0);
+}
+
+#endif // !Q_OS_WINCE
+
static inline QSizeF deviceSizeMM(const QSize &pixels, const QDpi &dpi)
{
const qreal inchToMM = 25.4;
@@ -110,7 +125,12 @@ BOOL QT_WIN_CALLBACK monitorEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM
HDC hdc = CreateDC(info.szDevice, NULL, NULL, NULL);
#endif
if (hdc) {
+#ifndef Q_OS_WINCE
+ const QDpi dpi = monitorDPI(hMonitor);
+ data.dpi = dpi.first ? dpi : deviceDPI(hdc);
+#else
data.dpi = deviceDPI(hdc);
+#endif
data.depth = GetDeviceCaps(hdc, BITSPIXEL);
data.format = data.depth == 16 ? QImage::Format_RGB16 : QImage::Format_RGB32;
data.physicalSizeMM = QSizeF(GetDeviceCaps(hdc, HORZSIZE), GetDeviceCaps(hdc, VERTSIZE));
@@ -387,6 +407,30 @@ static inline int indexOfMonitor(const QList<QWindowsScreenData> &screenData,
return -1;
}
+void QWindowsScreenManager::removeScreen(int index)
+{
+ qCDebug(lcQpaWindows) << "Removing Monitor:" << m_screens.at(index)->data();
+ QScreen *screen = m_screens.at(index)->screen();
+ QScreen *primaryScreen = QGuiApplication::primaryScreen();
+ // QTBUG-38650: When a screen is disconnected, Windows will automatically
+ // move the Window to another screen. This will trigger a geometry change
+ // event, but unfortunately after the screen destruction signal. To prevent
+ // QtGui from automatically hiding the QWindow, pretend all Windows move to
+ // the primary screen first (which is likely the correct, final screen).
+ if (screen != primaryScreen) {
+ unsigned movedWindowCount = 0;
+ foreach (QWindow *w, QGuiApplication::topLevelWindows()) {
+ if (w->screen() == screen && w->handle() && w->type() != Qt::Desktop) {
+ QWindowSystemInterface::handleWindowScreenChanged(w, primaryScreen);
+ ++movedWindowCount;
+ }
+ }
+ if (movedWindowCount)
+ QWindowSystemInterface::flushWindowSystemEvents();
+ }
+ delete m_screens.takeAt(index);
+}
+
/*!
\brief Synchronizes the screen list, adds new screens, removes deleted
ones and propagates resolution changes to QWindowSystemInterface.
@@ -412,10 +456,8 @@ bool QWindowsScreenManager::handleScreenChanges()
// temporary lock screen to avoid window recreation (QTBUG-33062).
if (!lockScreen) {
for (int i = m_screens.size() - 1; i >= 0; --i) {
- if (indexOfMonitor(newDataList, m_screens.at(i)->data().name) == -1) {
- qCDebug(lcQpaWindows) << "Removing Monitor: " << m_screens.at(i) ->data();
- delete m_screens.takeAt(i);
- } // not found
+ if (indexOfMonitor(newDataList, m_screens.at(i)->data().name) == -1)
+ removeScreen(i);
} // for existing screens
} // not lock screen
return true;
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index 930814a17d..c9d8a5662c 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.h
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -88,24 +88,24 @@ public:
static QWindowsScreen *screenOf(const QWindow *w = 0);
- virtual QRect geometry() const { return m_data.geometry; }
- virtual QRect availableGeometry() const { return m_data.availableGeometry; }
- virtual int depth() const { return m_data.depth; }
- virtual QImage::Format format() const { return m_data.format; }
- virtual QSizeF physicalSize() const { return m_data.physicalSizeMM; }
- virtual QDpi logicalDpi() const { return m_data.dpi; }
- virtual qreal refreshRate() const { return m_data.refreshRateHz; }
- virtual QString name() const { return m_data.name; }
- virtual Qt::ScreenOrientation primaryOrientation() { return m_data.orientation; }
- virtual QList<QPlatformScreen *> virtualSiblings() const;
- virtual QWindow *topLevelAt(const QPoint &point) const
+ QRect geometry() const Q_DECL_OVERRIDE { return m_data.geometry; }
+ QRect availableGeometry() const Q_DECL_OVERRIDE { return m_data.availableGeometry; }
+ int depth() const Q_DECL_OVERRIDE { return m_data.depth; }
+ QImage::Format format() const Q_DECL_OVERRIDE { return m_data.format; }
+ QSizeF physicalSize() const Q_DECL_OVERRIDE { return m_data.physicalSizeMM; }
+ QDpi logicalDpi() const Q_DECL_OVERRIDE { return m_data.dpi; }
+ qreal refreshRate() const Q_DECL_OVERRIDE { return m_data.refreshRateHz; }
+ QString name() const Q_DECL_OVERRIDE { return m_data.name; }
+ Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE { return m_data.orientation; }
+ QList<QPlatformScreen *> virtualSiblings() const Q_DECL_OVERRIDE;
+ QWindow *topLevelAt(const QPoint &point) const Q_DECL_OVERRIDE
{ return QWindowsScreen::findTopLevelAt(point, CWP_SKIPINVISIBLE); }
static QWindow *findTopLevelAt(const QPoint &point, unsigned flags);
static QWindow *windowAt(const QPoint &point, unsigned flags = CWP_SKIPINVISIBLE);
static QWindow *windowUnderMouse(unsigned flags = CWP_SKIPINVISIBLE);
- virtual QPixmap grabWindow(WId window, int x, int y, int width, int height) const;
+ QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
inline void handleChanges(const QWindowsScreenData &newData);
@@ -143,6 +143,8 @@ public:
const WindowsScreenList &screens() const { return m_screens; }
private:
+ void removeScreen(int index);
+
WindowsScreenList m_screens;
int m_lastDepth;
WORD m_lastHorizontalResolution;
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
index 8ceab02311..d1737de907 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
@@ -465,7 +465,9 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
const double degY = atan(cos(radAzim) / tanAlt);
tiltX = int(degX * (180 / M_PI));
tiltY = int(-degY * (180 / M_PI));
- rotation = packet.pkOrientation.orTwist;
+ rotation = 360.0 - (packet.pkOrientation.orTwist / 10.0);
+ if (rotation > 180.0)
+ rotation -= 360.0;
}
if (QWindowsContext::verbose > 1) {
@@ -477,8 +479,9 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
<< tiltY << "tanP:" << tangentialPressure << "rotation:" << rotation;
}
- QWindowSystemInterface::handleTabletEvent(target, packet.pkButtons, localPos, globalPosF,
+ QWindowSystemInterface::handleTabletEvent(target, QPointF(localPos), globalPosF,
currentDevice, currentPointer,
+ static_cast<Qt::MouseButtons>(packet.pkButtons),
pressureNew, tiltX, tiltY,
tangentialPressure, rotation, z,
m_devices.at(m_currentDevice).uniqueId,
diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h
index 9346621d59..4414c71bc0 100644
--- a/src/plugins/platforms/windows/qwindowstheme.h
+++ b/src/plugins/platforms/windows/qwindowstheme.h
@@ -59,17 +59,17 @@ public:
static QWindowsTheme *instance() { return m_instance; }
- virtual bool usePlatformNativeDialog(DialogType type) const;
- virtual QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const;
- virtual QVariant themeHint(ThemeHint) const;
+ bool usePlatformNativeDialog(DialogType type) const Q_DECL_OVERRIDE;
+ QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const Q_DECL_OVERRIDE;
+ QVariant themeHint(ThemeHint) const Q_DECL_OVERRIDE;
virtual const QPalette *palette(Palette type = SystemPalette) const
{ return m_palettes[type]; }
virtual const QFont *font(Font type = SystemFont) const
{ return m_fonts[type]; }
- virtual QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const;
- virtual QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size,
- QPlatformTheme::IconOptions iconOptions = 0) const;
+ QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const Q_DECL_OVERRIDE;
+ QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size,
+ QPlatformTheme::IconOptions iconOptions = 0) const Q_DECL_OVERRIDE;
void windowsThemeChanged(QWindow *window);
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 7d04c99d16..c5978c125c 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -48,15 +48,11 @@
# include "qwindowscursor.h"
#endif
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
-# include "qwindowseglcontext.h"
-# include <QtGui/QOpenGLFunctions>
-#endif
-
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
#include <QtGui/QWindow>
#include <QtGui/QRegion>
+#include <QtGui/QOpenGLContext>
#include <private/qsystemlibrary_p.h>
#include <private/qwindow_p.h>
#include <private/qguiapplication_p.h>
@@ -110,6 +106,8 @@ static QByteArray debugWinExStyle(DWORD exStyle)
rc += " WS_EX_CONTEXTHELP";
if (exStyle & WS_EX_LAYERED)
rc += " WS_EX_LAYERED";
+ if (exStyle & WS_EX_DLGMODALFRAME)
+ rc += " WS_EX_DLGMODALFRAME";
return rc;
}
@@ -183,6 +181,14 @@ QDebug operator<<(QDebug d, const NCCALCSIZE_PARAMS &p)
static inline QRect frameGeometry(HWND hwnd, bool topLevel)
{
RECT rect = { 0, 0, 0, 0 };
+#ifndef Q_OS_WINCE
+ if (topLevel) {
+ WINDOWPLACEMENT windowPlacement;
+ GetWindowPlacement(hwnd, &windowPlacement);
+ if (windowPlacement.showCmd == SW_SHOWMINIMIZED)
+ return qrectFromRECT(windowPlacement.rcNormalPosition);
+ }
+#endif // !Q_OS_WINCE
GetWindowRect(hwnd, &rect); // Screen coordinates.
const HWND parent = GetParent(hwnd);
if (parent && !topLevel) {
@@ -513,6 +519,10 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
}
if (flags & Qt::WindowSystemMenuHint)
style |= WS_SYSMENU;
+ else if (dialog) {
+ style |= WS_SYSMENU | WS_BORDER; // QTBUG-2027, dialogs without system menu.
+ exStyle |= WS_EX_DLGMODALFRAME;
+ }
if (flags & Qt::WindowMinimizeButtonHint)
style |= WS_MINIMIZEBOX;
if (shouldShowMaximizeButton(w, flags))
@@ -861,15 +871,13 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
m_opacity(1.0),
m_dropTarget(0),
m_savedStyle(0),
- m_format(aWindow->format()),
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- m_eglSurface(0),
-#endif
+ m_format(aWindow->requestedFormat()),
#ifdef Q_OS_WINCE
m_previouslyHidden(false),
#endif
m_iconSmall(0),
- m_iconBig(0)
+ m_iconBig(0),
+ m_surface(0)
{
// Clear the creation context as the window can be found in QWindowsContext's map.
QWindowsContext::instance()->setWindowCreationContext(QSharedPointer<QWindowCreationContext>());
@@ -877,13 +885,14 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
const Qt::WindowType type = aWindow->type();
if (type == Qt::Desktop)
return; // No further handling for Qt::Desktop
+#ifndef QT_NO_OPENGL
if (aWindow->surfaceType() == QWindow::OpenGLSurface) {
- setFlag(OpenGLSurface);
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL)
+ if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL)
+ setFlag(OpenGLSurface);
+ else
setFlag(OpenGL_ES2);
-#endif
}
+#endif // QT_NO_OPENGL
updateDropSite();
#ifndef Q_OS_WINCE
@@ -947,11 +956,10 @@ void QWindowsWindow::destroyWindow()
if (hasMouseCapture())
setMouseGrabEnabled(false);
setDropSiteEnabled(false);
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- if (m_eglSurface) {
- qCDebug(lcQpaGl) << __FUNCTION__ << "Freeing EGL surface " << m_eglSurface << window();
- eglDestroySurface(m_staticEglContext->display(), m_eglSurface);
- m_eglSurface = 0;
+#ifndef QT_NO_OPENGL
+ if (m_surface) {
+ m_data.staticOpenGLContext->destroyWindowSurface(m_surface);
+ m_surface = 0;
}
#endif
#ifdef Q_OS_WINCE
@@ -1383,6 +1391,11 @@ void QWindowsWindow::handleGeometryChange()
&& !(m_data.geometry.width() > previousGeometry.width() || m_data.geometry.height() > previousGeometry.height())) {
fireExpose(QRegion(m_data.geometry), true);
}
+ if (previousGeometry.topLeft() != m_data.geometry.topLeft()) {
+ QPlatformScreen *newScreen = screenForGeometry(m_data.geometry);
+ if (newScreen != screen())
+ QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
+ }
if (testFlag(SynchronousGeometryChangeEvent))
QWindowSystemInterface::flushWindowSystemEvents();
@@ -1399,15 +1412,29 @@ void QWindowsWindow::setGeometry_sys(const QRect &rect) const
<< margins << " to " <<rect
<< " new frame: " << frameGeometry;
- const bool rc = MoveWindow(m_data.hwnd, frameGeometry.x(), frameGeometry.y(),
- frameGeometry.width(), frameGeometry.height(), true);
+ bool result = false;
+#ifndef Q_OS_WINCE
+ WINDOWPLACEMENT windowPlacement;
+ GetWindowPlacement(m_data.hwnd, &windowPlacement);
+ // If the window is hidden and in maximized state or minimized, instead of moving the
+ // window, set the normal position of the window.
+ if ((windowPlacement.showCmd == SW_MAXIMIZE && !IsWindowVisible(m_data.hwnd))
+ || windowPlacement.showCmd == SW_SHOWMINIMIZED) {
+ windowPlacement.rcNormalPosition = RECTfromQRect(frameGeometry);
+ windowPlacement.showCmd = windowPlacement.showCmd == SW_SHOWMINIMIZED ? SW_SHOWMINIMIZED : SW_HIDE;
+ result = SetWindowPlacement(m_data.hwnd, &windowPlacement);
+ } else
+#endif // !Q_OS_WINCE
+ {
+ result = MoveWindow(m_data.hwnd, frameGeometry.x(), frameGeometry.y(),
+ frameGeometry.width(), frameGeometry.height(), true);
+ }
qCDebug(lcQpaWindows) << '<' << __FUNCTION__ << this << window()
- << " \n resulting " << rc << geometry_sys();
+ << " \n resulting " << result << geometry_sys();
}
QRect QWindowsWindow::frameGeometry_sys() const
{
- // Warning: Returns bogus values when minimized.
bool isRealTopLevel = window()->isTopLevel() && !m_data.embedded;
return frameGeometry(m_data.hwnd, isRealTopLevel);
}
@@ -1573,23 +1600,9 @@ void QWindowsWindow::setWindowState(Qt::WindowState state)
}
}
-// Return the effective screen for full screen mode in a virtual desktop.
-static const QScreen *effectiveScreen(const QWindow *w)
-{
- QPoint center = w->geometry().center();
- if (!w->isTopLevel())
- center = w->mapToGlobal(center);
- const QScreen *screen = w->screen();
- if (!screen->geometry().contains(center))
- foreach (const QScreen *sibling, screen->virtualSiblings())
- if (sibling->geometry().contains(center))
- return sibling;
- return screen;
-}
-
bool QWindowsWindow::isFullScreen_sys() const
{
- return window()->isTopLevel() && geometry_sys() == effectiveScreen(window())->geometry();
+ return window()->isTopLevel() && geometry_sys() == window()->screen()->geometry();
}
/*!
@@ -1669,7 +1682,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
setStyle(newStyle);
// Use geometry of QWindow::screen() within creation or the virtual screen the
// window is in (QTBUG-31166, QTBUG-30724).
- const QScreen *screen = testFlag(WithinCreate) ? window()->screen() : effectiveScreen(window());
+ const QScreen *screen = window()->screen();
const QRect r = screen->geometry();
const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
@@ -1939,7 +1952,7 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
&& (m_data.flags & Qt::FramelessWindowHint)) {
// This block fixes QTBUG-8361: Frameless windows shouldn't cover the
// taskbar when maximized
- const QScreen *screen = effectiveScreen(window());
+ const QScreen *screen = window()->screen();
// Documentation of MINMAXINFO states that it will only work for the primary screen
if (screen && screen == QGuiApplication::primaryScreen()) {
@@ -2144,23 +2157,6 @@ void QWindowsWindow::setEnabled(bool enabled)
setStyle(newStyle);
}
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
-EGLSurface QWindowsWindow::ensureEglSurfaceHandle(const QWindowsWindow::QWindowsEGLStaticContextPtr &staticContext, EGLConfig config)
-{
- if (!m_eglSurface) {
- m_staticEglContext = staticContext;
- m_eglSurface = eglCreateWindowSurface(staticContext->display(), config, (EGLNativeWindowType)m_data.hwnd, NULL);
- if (m_eglSurface == EGL_NO_SURFACE)
- qWarning("%s: Could not create the egl surface for %s/'%s' (eglCreateWindowSurface failed): error = 0x%x\n",
- Q_FUNC_INFO, window()->metaObject()->className(),
- qPrintable(window()->objectName()), eglGetError());
-
- qCDebug(lcQpaGl) << __FUNCTION__<<"Created EGL surface "<< m_eglSurface <<window();
- }
- return m_eglSurface;
-}
-#endif // QT_OPENGL_ES_2
-
QByteArray QWindowsWindow::debugWindowFlags(Qt::WindowFlags wf)
{
const int iwf = int(wf);
@@ -2272,4 +2268,16 @@ void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins)
}
}
+void *QWindowsWindow::surface(void *nativeConfig)
+{
+#ifdef QT_NO_OPENGL
+ return 0;
+#else
+ if (!m_surface)
+ m_surface = m_data.staticOpenGLContext->createWindowSurface(m_data.hwnd, nativeConfig);
+
+ return m_surface;
+#endif
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index cb437b76d0..19d2236688 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -47,23 +47,15 @@
# include "qplatformfunctions_wince.h"
#endif
#include "qwindowscursor.h"
+#include "qwindowsopenglcontext.h"
#include <qpa/qplatformwindow.h>
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
-# include <QtCore/QSharedPointer>
-# include <EGL/egl.h>
-#endif
-
QT_BEGIN_NAMESPACE
class QWindowsOleDropTarget;
class QDebug;
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
-class QWindowsEGLStaticContext;
-#endif
-
struct QWindowsGeometryHint
{
QWindowsGeometryHint() {}
@@ -121,6 +113,9 @@ struct QWindowsWindowData
QMargins customMargins; // User-defined, additional frame for NCCALCSIZE
HWND hwnd;
bool embedded;
+#ifndef QT_NO_OPENGL
+ QSharedPointer<QWindowsStaticOpenGLContext> staticOpenGLContext;
+#endif // QT_NO_OPENGL
static QWindowsWindowData create(const QWindow *w,
const QWindowsWindowData &parameters,
@@ -130,10 +125,6 @@ struct QWindowsWindowData
class QWindowsWindow : public QPlatformWindow
{
public:
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- typedef QSharedPointer<QWindowsEGLStaticContext> QWindowsEGLStaticContextPtr;
-#endif
-
enum Flags
{
AutoMouseCapture = 0x1, //! Automatic mouse capture on button press.
@@ -160,46 +151,46 @@ public:
QWindowsWindow(QWindow *window, const QWindowsWindowData &data);
~QWindowsWindow();
- virtual QSurfaceFormat format() const { return m_format; }
- virtual void setGeometry(const QRect &rect);
- virtual QRect geometry() const { return m_data.geometry; }
+ QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; }
+ void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
+ QRect geometry() const Q_DECL_OVERRIDE { return m_data.geometry; }
QRect normalGeometry() const Q_DECL_OVERRIDE;
- virtual void setVisible(bool visible);
+ void setVisible(bool visible) Q_DECL_OVERRIDE;
bool isVisible() const;
- virtual bool isExposed() const { return testFlag(Exposed); }
- virtual bool isActive() const;
- virtual bool isEmbedded(const QPlatformWindow *parentWindow) const;
- virtual QPoint mapToGlobal(const QPoint &pos) const;
- virtual QPoint mapFromGlobal(const QPoint &pos) const;
+ bool isExposed() const Q_DECL_OVERRIDE { return testFlag(Exposed); }
+ bool isActive() const Q_DECL_OVERRIDE;
+ bool isEmbedded(const QPlatformWindow *parentWindow) const Q_DECL_OVERRIDE;
+ QPoint mapToGlobal(const QPoint &pos) const Q_DECL_OVERRIDE;
+ QPoint mapFromGlobal(const QPoint &pos) const Q_DECL_OVERRIDE;
- virtual void setWindowFlags(Qt::WindowFlags flags);
- virtual void setWindowState(Qt::WindowState state);
+ void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE;
+ void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE;
HWND handle() const { return m_data.hwnd; }
- virtual WId winId() const { return WId(m_data.hwnd); }
- virtual void setParent(const QPlatformWindow *window);
+ WId winId() const Q_DECL_OVERRIDE { return WId(m_data.hwnd); }
+ void setParent(const QPlatformWindow *window) Q_DECL_OVERRIDE;
- virtual void setWindowTitle(const QString &title);
- virtual void raise();
- virtual void lower();
+ void setWindowTitle(const QString &title) Q_DECL_OVERRIDE;
+ void raise() Q_DECL_OVERRIDE;
+ void lower() Q_DECL_OVERRIDE;
void windowEvent(QEvent *event);
- virtual void propagateSizeHints();
- virtual QMargins frameMargins() const;
+ void propagateSizeHints() Q_DECL_OVERRIDE;
+ QMargins frameMargins() const Q_DECL_OVERRIDE;
- virtual void setOpacity(qreal level);
- virtual void setMask(const QRegion &region);
+ void setOpacity(qreal level) Q_DECL_OVERRIDE;
+ void setMask(const QRegion &region) Q_DECL_OVERRIDE;
qreal opacity() const { return m_opacity; }
- virtual void requestActivateWindow();
+ void requestActivateWindow() Q_DECL_OVERRIDE;
- virtual bool setKeyboardGrabEnabled(bool grab);
- virtual bool setMouseGrabEnabled(bool grab);
+ bool setKeyboardGrabEnabled(bool grab) Q_DECL_OVERRIDE;
+ bool setMouseGrabEnabled(bool grab) Q_DECL_OVERRIDE;
inline bool hasMouseCapture() const { return GetCapture() == m_data.hwnd; }
- virtual bool startSystemResize(const QPoint &pos, Qt::Corner corner);
+ bool startSystemResize(const QPoint &pos, Qt::Corner corner) Q_DECL_OVERRIDE;
void setFrameStrutEventsEnabled(bool enabled);
bool frameStrutEventsEnabled() const { return testFlag(FrameStrutEventsEnabled); }
@@ -207,11 +198,6 @@ public:
QMargins customMargins() const { return m_data.customMargins; }
void setCustomMargins(const QMargins &m);
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- EGLSurface eglSurfaceHandle() const { return m_eglSurface;}
- EGLSurface ensureEglSurfaceHandle(const QWindowsEGLStaticContextPtr &staticContext, EGLConfig config);
-#endif
-
inline unsigned style() const
{ return GetWindowLongPtr(m_data.hwnd, GWL_STYLE); }
void setStyle(unsigned s) const;
@@ -263,6 +249,8 @@ public:
bool isEnabled() const;
void setWindowIcon(const QIcon &icon);
+ void *surface(void *nativeConfig);
+
#ifndef Q_OS_WINCE
void setAlertState(bool enabled);
bool isAlertState() const { return testFlag(AlertState); }
@@ -302,15 +290,12 @@ private:
unsigned m_savedStyle;
QRect m_savedFrameGeometry;
const QSurfaceFormat m_format;
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- EGLSurface m_eglSurface;
- QSharedPointer<QWindowsEGLStaticContext> m_staticEglContext;
-#endif
#ifdef Q_OS_WINCE
bool m_previouslyHidden;
#endif
HICON m_iconSmall;
HICON m_iconBig;
+ void *m_surface;
};
// Debug
diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri
index 13799ba1ba..104d882fba 100644
--- a/src/plugins/platforms/windows/windows.pri
+++ b/src/plugins/platforms/windows/windows.pri
@@ -66,8 +66,12 @@ HEADERS += \
$$PWD/qwindowsnativeimage.h \
$$PWD/qwindowsnativeinterface.h
+!wince: HEADERS += $$PWD/qwindowsopengltester.h
+
INCLUDEPATH += $$PWD
+contains(QT_CONFIG,opengl): HEADERS += $$PWD/qwindowsopenglcontext.h
+
contains(QT_CONFIG, opengles2) {
SOURCES += $$PWD/qwindowseglcontext.cpp
HEADERS += $$PWD/qwindowseglcontext.h
@@ -78,7 +82,8 @@ contains(QT_CONFIG, opengles2) {
# Dynamic GL needs both WGL and EGL
contains(QT_CONFIG,dynamicgl) {
- SOURCES += $$PWD/qwindowseglcontext.cpp
+ SOURCES += $$PWD/qwindowseglcontext.cpp \
+ $$PWD/qwindowsopengltester.cpp
HEADERS += $$PWD/qwindowseglcontext.h
}
@@ -108,6 +113,10 @@ contains(QT_CONFIG,dynamicgl) {
HEADERS += $$PWD/qwindowssessionmanager.h
}
+!wince*:!contains( DEFINES, QT_NO_IMAGEFORMAT_PNG ) {
+ RESOURCES += $$PWD/cursors.qrc
+}
+
contains(QT_CONFIG, freetype) {
DEFINES *= QT_NO_FONTCONFIG
QT_FREETYPE_DIR = $$QT_SOURCE_TREE/src/3rdparty/freetype
diff --git a/src/plugins/platforms/winrt/qwinrtcursor.cpp b/src/plugins/platforms/winrt/qwinrtcursor.cpp
index f09454ebc3..d2d87bde0b 100644
--- a/src/plugins/platforms/winrt/qwinrtcursor.cpp
+++ b/src/plugins/platforms/winrt/qwinrtcursor.cpp
@@ -40,40 +40,54 @@
****************************************************************************/
#include "qwinrtcursor.h"
+#include "qwinrtscreen.h"
+
+#include <QtCore/qfunctions_winrt.h>
+#include <QtGui/QGuiApplication>
+#include <QtGui/QScreen>
#include <wrl.h>
#include <windows.ui.core.h>
#include <windows.foundation.h>
+using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::UI::Core;
using namespace ABI::Windows::Foundation;
-QT_BEGIN_NAMESPACE
+QT_USE_NAMESPACE
+
+class QWinRTCursorPrivate
+{
+public:
+ ComPtr<ICoreCursorFactory> cursorFactory;
+};
-QWinRTCursor::QWinRTCursor(ICoreWindow *window) : m_window(window), m_cursorFactory(nullptr)
+QWinRTCursor::QWinRTCursor()
+ : d_ptr(new QWinRTCursorPrivate)
{
-#ifndef Q_OS_WINPHONE
- GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Core_CoreCursor).Get(), &m_cursorFactory);
-#endif
+ Q_D(QWinRTCursor);
+
+ HRESULT hr;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Core_CoreCursor).Get(),
+ IID_PPV_ARGS(&d->cursorFactory));
+ Q_ASSERT_SUCCEEDED(hr);
}
QWinRTCursor::~QWinRTCursor()
{
- if (m_cursorFactory)
- m_cursorFactory->Release();
}
#ifndef QT_NO_CURSOR
-void QWinRTCursor::changeCursor(QCursor *windowCursor, QWindow *)
+void QWinRTCursor::changeCursor(QCursor *windowCursor, QWindow *window)
{
-#ifndef Q_OS_WINPHONE
- if (!m_cursorFactory)
- return;
+ Q_D(QWinRTCursor);
+
+ ICoreWindow *coreWindow = static_cast<QWinRTScreen *>(window->screen()->handle())->coreWindow();
CoreCursorType type;
switch (windowCursor ? windowCursor->shape() : Qt::ArrowCursor) {
case Qt::BlankCursor:
- m_window->put_PointerCursor(nullptr);
+ coreWindow->put_PointerCursor(Q_NULLPTR);
return;
default:
case Qt::OpenHandCursor:
@@ -132,24 +146,20 @@ void QWinRTCursor::changeCursor(QCursor *windowCursor, QWindow *)
break;
}
- ICoreCursor *cursor;
- if (SUCCEEDED(m_cursorFactory->CreateCursor(type, 0, &cursor)))
- m_window->put_PointerCursor(cursor);
-#else // Q_OS_WINPHONE
- Q_UNUSED(windowCursor)
-#endif // Q_OS_WINPHONE
+ ComPtr<ICoreCursor> cursor;
+ HRESULT hr = d->cursorFactory->CreateCursor(type, 0, &cursor);
+ RETURN_VOID_IF_FAILED("Failed to create native cursor.");
+
+ hr = coreWindow->put_PointerCursor(cursor.Get());
+ RETURN_VOID_IF_FAILED("Failed to set native cursor.");
}
#endif // QT_NO_CURSOR
QPoint QWinRTCursor::pos() const
{
-#ifdef Q_OS_WINPHONE
- return QPlatformCursor::pos();
-#else
+ ICoreWindow *coreWindow =
+ static_cast<QWinRTScreen *>(QGuiApplication::primaryScreen()->handle())->coreWindow();
Point point;
- m_window->get_PointerPosition(&point);
+ coreWindow->get_PointerPosition(&point);
return QPoint(point.X, point.Y);
-#endif
}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtcursor.h b/src/plugins/platforms/winrt/qwinrtcursor.h
index f7b301a98b..a08002f34c 100644
--- a/src/plugins/platforms/winrt/qwinrtcursor.h
+++ b/src/plugins/platforms/winrt/qwinrtcursor.h
@@ -44,34 +44,22 @@
#include <qpa/qplatformcursor.h>
-namespace ABI {
- namespace Windows {
- namespace UI {
- namespace Core {
- struct ICoreWindow;
- struct ICoreCursorFactory;
- }
- }
- }
-}
-
-QT_BEGIN_NAMESPACE
+QT_USE_NAMESPACE
+class QWinRTCursorPrivate;
class QWinRTCursor : public QPlatformCursor
{
public:
- explicit QWinRTCursor(ABI::Windows::UI::Core::ICoreWindow *window);
+ explicit QWinRTCursor();
~QWinRTCursor();
#ifndef QT_NO_CURSOR
- void changeCursor(QCursor * windowCursor, QWindow *);
+ void changeCursor(QCursor * windowCursor, QWindow *window);
#endif
QPoint pos() const;
private:
- ABI::Windows::UI::Core::ICoreWindow *m_window;
- ABI::Windows::UI::Core::ICoreCursorFactory *m_cursorFactory;
+ QScopedPointer<QWinRTCursorPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTCursor)
};
-QT_END_NAMESPACE
-
#endif // QWINRTCURSOR_H
diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp
index b3a2cafa2e..53d52a430c 100644
--- a/src/plugins/platforms/winrt/qwinrtintegration.cpp
+++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp
@@ -48,7 +48,7 @@
#include "qwinrtservices.h"
#include "qwinrteglcontext.h"
#include "qwinrtfontdatabase.h"
-#include "qwinrtplatformtheme.h"
+#include "qwinrttheme.h"
#include <QtGui/QOpenGLContext>
@@ -63,18 +63,6 @@ using namespace ABI::Windows::UI::Core;
using namespace ABI::Windows::UI::ViewManagement;
using namespace ABI::Windows::ApplicationModel::Core;
-static IUISettings *getSettings()
-{
- static IUISettings *settings = 0;
- if (!settings) {
- if (FAILED(RoActivateInstance(Wrappers::HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_UISettings).Get(),
- reinterpret_cast<IInspectable **>(&settings)))) {
- qWarning("Could not activate UISettings.");
- }
- }
- return settings;
-}
-
QT_BEGIN_NAMESPACE
QWinRTIntegration::QWinRTIntegration()
@@ -82,26 +70,7 @@ QWinRTIntegration::QWinRTIntegration()
, m_fontDatabase(new QWinRTFontDatabase)
, m_services(new QWinRTServices)
{
- // Obtain the WinRT Application, view, and window
- ICoreApplication *application;
- if (FAILED(RoGetActivationFactory(Wrappers::HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
- IID_PPV_ARGS(&application))))
- qCritical("Could not attach to the application factory.");
-
- ICoreApplicationView *view;
- if (FAILED(application->GetCurrentView(&view))) {
- qCritical("Could not obtain the application view - have you started outside of WinRT?");
- return;
- }
-
- // Get core window (will act as our screen)
- ICoreWindow *window;
- if (FAILED(view->get_CoreWindow(&window))) {
- qCritical("Could not obtain the application window - have you started outside of WinRT?");
- return;
- }
- window->Activate();
- m_screen = new QWinRTScreen(window);
+ m_screen = new QWinRTScreen;
screenAdded(m_screen);
m_success = true;
@@ -133,26 +102,7 @@ bool QWinRTIntegration::hasCapability(QPlatformIntegration::Capability cap) cons
QVariant QWinRTIntegration::styleHint(StyleHint hint) const
{
- switch (hint) {
- case CursorFlashTime:
- if (IUISettings *settings = getSettings()) {
- quint32 blinkRate;
- settings->get_CaretBlinkRate(&blinkRate);
- return blinkRate;
- }
- break;
- case MouseDoubleClickInterval:
- if (IUISettings *settings = getSettings()) {
- quint32 doubleClickTime;
- settings->get_DoubleClickTime(&doubleClickTime);
- return doubleClickTime;
- }
- case ShowIsFullScreen:
- return true;
- default:
- break;
- }
- return QPlatformIntegration::styleHint(hint);
+ return QWinRTTheme::styleHint(hint);
}
QPlatformWindow *QWinRTIntegration::createPlatformWindow(QWindow *window) const
@@ -200,7 +150,7 @@ QPlatformTheme *QWinRTIntegration::createPlatformTheme(const QString &
name) const
{
if (name == QLatin1String("winrt"))
- return new QWinRTPlatformTheme();
+ return new QWinRTTheme();
return 0;
}
diff --git a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp
new file mode 100644
index 0000000000..6de90ba1ec
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp
@@ -0,0 +1,232 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrtmessagedialoghelper.h"
+#include "qwinrttheme.h"
+
+#include <QtCore/qfunctions_winrt.h>
+
+#include <windows.ui.popups.h>
+#include <windows.foundation.h>
+#include <windows.foundation.collections.h>
+#include <wrl.h>
+
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+using namespace ABI::Windows::UI::Popups;
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+
+typedef IAsyncOperationCompletedHandler<IUICommand *> DialogCompletedHandler;
+
+QT_BEGIN_NAMESPACE
+
+class CommandId : public RuntimeClass<IInspectable>
+{
+public:
+ CommandId(QPlatformDialogHelper::StandardButton button)
+ : button(button) { }
+ QPlatformDialogHelper::StandardButton button;
+};
+
+class QWinRTMessageDialogHelperPrivate
+{
+public:
+ const QWinRTTheme *theme;
+ bool shown;
+ ComPtr<IAsyncInfo> info;
+ QEventLoop loop;
+};
+
+QWinRTMessageDialogHelper::QWinRTMessageDialogHelper(const QWinRTTheme *theme)
+ : QPlatformMessageDialogHelper(), d_ptr(new QWinRTMessageDialogHelperPrivate)
+{
+ Q_D(QWinRTMessageDialogHelper);
+
+ d->theme = theme;
+ d->shown = false;
+}
+
+QWinRTMessageDialogHelper::~QWinRTMessageDialogHelper()
+{
+ Q_D(QWinRTMessageDialogHelper);
+
+ if (d->shown)
+ hide();
+}
+
+void QWinRTMessageDialogHelper::exec()
+{
+ Q_D(QWinRTMessageDialogHelper);
+
+ if (!d->shown)
+ show(Qt::Dialog, Qt::ApplicationModal, 0);
+ d->loop.exec();
+}
+
+bool QWinRTMessageDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent)
+{
+ Q_UNUSED(windowFlags)
+ Q_UNUSED(windowModality)
+ Q_UNUSED(parent)
+ Q_D(QWinRTMessageDialogHelper);
+
+ QSharedPointer<QMessageDialogOptions> options = this->options();
+ const QString informativeText = options->informativeText();
+ const QString title = options->windowTitle();
+ const QString text = informativeText.isEmpty() ? options->text() : (options->text() + QLatin1Char('\n') + informativeText);
+
+ HRESULT hr;
+ ComPtr<IMessageDialogFactory> dialogFactory;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Popups_MessageDialog).Get(),
+ IID_PPV_ARGS(&dialogFactory));
+ RETURN_FALSE_IF_FAILED("Failed to create dialog factory");
+
+ ComPtr<IUICommandFactory> commandFactory;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Popups_UICommand).Get(),
+ IID_PPV_ARGS(&commandFactory));
+ RETURN_FALSE_IF_FAILED("Failed to create command factory");
+
+ ComPtr<IMessageDialog> dialog;
+ HStringReference nativeText(reinterpret_cast<LPCWSTR>(text.utf16()), text.size());
+ if (!title.isEmpty()) {
+ HStringReference nativeTitle(reinterpret_cast<LPCWSTR>(title.utf16()), title.size());
+ hr = dialogFactory->CreateWithTitle(nativeText.Get(), nativeTitle.Get(), &dialog);
+ RETURN_FALSE_IF_FAILED("Failed to create dialog with title");
+ } else {
+ hr = dialogFactory->Create(nativeText.Get(), &dialog);
+ RETURN_FALSE_IF_FAILED("Failed to create dialog");
+ }
+
+ // Add Buttons
+ ComPtr<IVector<IUICommand *>> dialogCommands;
+ hr = dialog->get_Commands(&dialogCommands);
+ RETURN_FALSE_IF_FAILED("Failed to get dialog commands");
+
+ // If no button is specified we need to create one to get close notification
+ int buttons = options->standardButtons();
+ if (buttons == 0)
+ buttons = Ok;
+
+ for (int i = FirstButton; i < LastButton; i<<=1) {
+ if (!(buttons & i))
+ continue;
+ // Add native command
+ const QString label = d->theme->standardButtonText(i);
+ HStringReference nativeLabel(reinterpret_cast<LPCWSTR>(label.utf16()), label.size());
+ ComPtr<IUICommand> command;
+ hr = commandFactory->Create(nativeLabel.Get(), &command);
+ RETURN_FALSE_IF_FAILED("Failed to create message box command");
+ ComPtr<IInspectable> id = Make<CommandId>(static_cast<StandardButton>(i));
+ hr = command->put_Id(id.Get());
+ RETURN_FALSE_IF_FAILED("Failed to set command ID");
+ hr = dialogCommands->Append(command.Get());
+ if (hr == E_BOUNDS) {
+ qErrnoWarning(hr, "The WinRT message dialog supports a maximum of three buttons");
+ continue;
+ }
+ RETURN_FALSE_IF_FAILED("Failed to append message box command");
+ if (i == Abort || i == Cancel || i == Close) {
+ quint32 size;
+ hr = dialogCommands->get_Size(&size);
+ RETURN_FALSE_IF_FAILED("Failed to get command list size");
+ hr = dialog->put_CancelCommandIndex(size - 1);
+ RETURN_FALSE_IF_FAILED("Failed to set cancel index");
+ }
+ }
+
+ ComPtr<IAsyncOperation<IUICommand *>> op;
+ hr = dialog->ShowAsync(&op);
+ RETURN_FALSE_IF_FAILED("Failed to show dialog");
+ hr = op->put_Completed(Callback<DialogCompletedHandler>(this, &QWinRTMessageDialogHelper::onCompleted).Get());
+ RETURN_FALSE_IF_FAILED("Failed to set dialog callback");
+
+ d->shown = true;
+ hr = op.As(&d->info);
+ RETURN_FALSE_IF_FAILED("Failed to acquire AsyncInfo for MessageDialog");
+
+ return true;
+}
+
+void QWinRTMessageDialogHelper::hide()
+{
+ Q_D(QWinRTMessageDialogHelper);
+
+ if (!d->shown)
+ return;
+
+ HRESULT hr = d->info->Cancel();
+ if (FAILED(hr))
+ qErrnoWarning(hr, "Failed to cancel dialog operation");
+
+ d->shown = false;
+}
+
+HRESULT QWinRTMessageDialogHelper::onCompleted(IAsyncOperation<IUICommand *> *asyncInfo, AsyncStatus status)
+{
+ Q_UNUSED(status);
+ Q_D(QWinRTMessageDialogHelper);
+
+ if (d->loop.isRunning())
+ d->loop.exit();
+
+ d->shown = false;
+
+ if (status == Canceled) {
+ emit reject();
+ return S_OK;
+ }
+
+ HRESULT hr;
+ ComPtr<IUICommand> command;
+ hr = asyncInfo->GetResults(&command);
+ RETURN_OK_IF_FAILED("Failed to get command");
+
+ ComPtr<CommandId> id;
+ hr = command->get_Id(&id);
+ RETURN_OK_IF_FAILED("Failed to get command ID");
+
+ ButtonRole role = buttonRole(id->button);
+ emit clicked(id->button, role);
+ return S_OK;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtplatformmessagedialoghelper.h b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.h
index fbb21ed69c..25199e569c 100644
--- a/src/plugins/platforms/winrt/qwinrtplatformmessagedialoghelper.h
+++ b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.h
@@ -39,11 +39,10 @@
**
****************************************************************************/
-#ifndef QWINRTPLATFORMMESSAGEDIALOGHELPER_H
-#define QWINRTPLATFORMMESSAGEDIALOGHELPER_H
+#ifndef QWINRTMESSAGEDIALOGHELPER_H
+#define QWINRTMESSAGEDIALOGHELPER_H
#include <qpa/qplatformdialoghelper.h>
-#include <QtCore/QEventLoop>
#include <QtCore/qt_windows.h>
namespace ABI {
@@ -53,19 +52,24 @@ namespace ABI {
struct IUICommand;
}
}
+ namespace Foundation {
+ enum class AsyncStatus;
+ template <typename T> struct IAsyncOperation;
+ }
}
}
QT_BEGIN_NAMESPACE
-struct QWinRTPlatformMessageDialogInfo;
+class QWinRTTheme;
-class QWinRTPlatformMessageDialogHelper : public QPlatformMessageDialogHelper
+class QWinRTMessageDialogHelperPrivate;
+class QWinRTMessageDialogHelper : public QPlatformMessageDialogHelper
{
Q_OBJECT
public:
- explicit QWinRTPlatformMessageDialogHelper();
- ~QWinRTPlatformMessageDialogHelper();
+ explicit QWinRTMessageDialogHelper(const QWinRTTheme *theme);
+ ~QWinRTMessageDialogHelper();
void exec();
bool show(Qt::WindowFlags windowFlags,
@@ -73,13 +77,14 @@ public:
QWindow *parent);
void hide();
- HRESULT onInvoked(ABI::Windows::UI::Popups::IUICommand *command);
private:
- QWinRTPlatformMessageDialogInfo *m_info;
- QEventLoop m_loop;
- bool m_shown;
+ HRESULT onCompleted(ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::UI::Popups::IUICommand *> *asyncInfo,
+ ABI::Windows::Foundation::AsyncStatus status);
+
+ QScopedPointer<QWinRTMessageDialogHelperPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTMessageDialogHelper)
};
QT_END_NAMESPACE
-#endif // QWINRTPLATFORMMESSAGEDIALOGHELPER_H
+#endif // QWINRTMESSAGEDIALOGHELPER_H
diff --git a/src/plugins/platforms/winrt/qwinrtplatformmessagedialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtplatformmessagedialoghelper.cpp
deleted file mode 100644
index c2f884055d..0000000000
--- a/src/plugins/platforms/winrt/qwinrtplatformmessagedialoghelper.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qwinrtplatformmessagedialoghelper.h"
-
-#include <QtGui/QGuiApplication>
-#include <private/qguiapplication_p.h>
-#include <qpa/qplatformtheme.h>
-
-#include <asyncinfo.h>
-#include <windows.ui.popups.h>
-#include <windows.foundation.h>
-#include <windows.foundation.collections.h>
-#include <wrl.h>
-
-using namespace ABI::Windows::Foundation;
-using namespace ABI::Windows::Foundation::Collections;
-using namespace ABI::Windows::UI::Popups;
-using namespace Microsoft::WRL;
-using namespace Microsoft::WRL::Wrappers;
-
-QT_BEGIN_NAMESPACE
-
-struct QWinRTPlatformMessageDialogInfo
-{
- ComPtr<IAsyncInfo> info;
-};
-
-QWinRTPlatformMessageDialogHelper::QWinRTPlatformMessageDialogHelper() :
- QPlatformMessageDialogHelper(),
- m_info(new QWinRTPlatformMessageDialogInfo),
- m_shown(false)
-{
-}
-
-QWinRTPlatformMessageDialogHelper::~QWinRTPlatformMessageDialogHelper()
-{
- if (m_shown)
- hide();
- delete m_info;
-}
-
-void QWinRTPlatformMessageDialogHelper::exec()
-{
- if (!m_shown)
- show(Qt::Dialog, Qt::ApplicationModal, 0);
- m_loop.exec();
-}
-
-bool QWinRTPlatformMessageDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent)
-{
- Q_UNUSED(windowFlags)
- Q_UNUSED(windowModality)
- Q_UNUSED(parent)
-
- QSharedPointer<QMessageDialogOptions> options = this->options();
-
- const QString informativeText = options->informativeText();
- const QString title = options->windowTitle();
- const QString text = informativeText.isEmpty() ? options->text() : (options->text() + QLatin1Char('\n') + informativeText);
-
-
- ComPtr<IMessageDialogFactory> dialogFactory;
- if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Popups_MessageDialog).Get(), &dialogFactory)))
- return false;
-
- ComPtr<IUICommandFactory> commandFactory;
- if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Popups_UICommand).Get(), &commandFactory)))
- return false;
-
- HString nativeText;
- nativeText.Set(reinterpret_cast<LPCWSTR>(text.utf16()), text.size());
- ComPtr<IMessageDialog> dialog;
-
- if (!title.isEmpty()) {
- HString nativeTitle;
- nativeTitle.Set(reinterpret_cast<LPCWSTR>(title.utf16()), title.size());
- if (FAILED(dialogFactory->CreateWithTitle(nativeText.Get(), nativeTitle.Get(), &dialog)))
- return false;
- } else {
- if (FAILED(dialogFactory->Create(nativeText.Get(), &dialog)))
- return false;
- }
-
- // Add Buttons
- ComPtr<IVector<IUICommand*> > dialogCommands;
- if (FAILED(dialog->get_Commands(&dialogCommands)))
- return false;
-
- // If no button is specified we need to create one to get close notification
- int buttons = options->standardButtons();
- if (buttons == 0)
- buttons = QPlatformDialogHelper::Ok;
-
- for (int i = QPlatformDialogHelper::FirstButton; i < QPlatformDialogHelper::LastButton; i<<=1) {
- if (buttons & i) {
- // Add native command
- const QString label = QGuiApplicationPrivate::platformTheme()->standardButtonText(i);
-
- HString hLabel;
- hLabel.Set(reinterpret_cast<LPCWSTR>(label.utf16()), label.size());
-
- ABI::Windows::UI::Popups::IUICommand *command;
- if (FAILED(commandFactory->CreateWithHandler(hLabel.Get(),
- Callback<IUICommandInvokedHandler>(this, &QWinRTPlatformMessageDialogHelper::onInvoked).Get(),
- &command)))
- return false;
- dialogCommands->Append(command);
- }
- }
-
- ComPtr<IAsyncOperation<IUICommand*> > op;
- if (FAILED(dialog->ShowAsync(&op)))
- return false;
-
- m_shown = true;
- if (FAILED(op.As(&m_info->info))) {
- m_shown = false;
- // The dialog is shown already, so we cannot return false
- qWarning("Failed to acquire AsyncInfo for MessageDialog");
- }
- return true;
-}
-
-void QWinRTPlatformMessageDialogHelper::hide()
-{
- if (!m_shown)
- return;
-
- m_info->info->Cancel();
- m_shown = false;
-}
-
-HRESULT QWinRTPlatformMessageDialogHelper::onInvoked(ABI::Windows::UI::Popups::IUICommand *command)
-{
- HString hLabel;
- UINT32 labelLength;
- command->get_Label(hLabel.GetAddressOf());
- PCWSTR rawString = hLabel.GetRawBuffer(&labelLength);
- QString label = QString::fromWCharArray(rawString, labelLength);
- int buttonId = -1;
- for (int i = QPlatformDialogHelper::FirstButton; i < QPlatformDialogHelper::LastButton; i<<=1) {
- if ( options()->standardButtons() & i ) {
- if (QGuiApplicationPrivate::platformTheme()->standardButtonText(i) == label) {
- buttonId = i;
- break;
- }
- }
- }
- if (m_loop.isRunning())
- m_loop.exit();
-
- m_shown = false;
-
- if (buttonId < 0) {
- emit reject();
- return S_OK;
- }
-
- QPlatformDialogHelper::StandardButton standardButton = static_cast<QPlatformDialogHelper::StandardButton>(buttonId);
- QPlatformDialogHelper::ButtonRole role = QPlatformDialogHelper::buttonRole(standardButton);
- emit clicked(standardButton, role);
- return S_OK;
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index f948cf9924..cbc7449591 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -51,6 +51,7 @@
#include <QtPlatformSupport/private/qeglconvenience_p.h>
#include <qpa/qwindowsysteminterface.h>
#include <QtCore/qt_windows.h>
+#include <QtCore/qfunctions_winrt.h>
#include <wrl.h>
#include <windows.system.h>
@@ -93,11 +94,7 @@ typedef ITypedEventHandler<CoreWindow*, PointerEventArgs*> PointerHandler;
typedef ITypedEventHandler<CoreWindow*, WindowSizeChangedEventArgs*> SizeChangedHandler;
typedef ITypedEventHandler<CoreWindow*, VisibilityChangedEventArgs*> VisibilityChangedHandler;
typedef ITypedEventHandler<CoreWindow*, AutomationProviderRequestedEventArgs*> AutomationProviderRequestedHandler;
-#if _MSC_VER <=1700
-typedef IDisplayPropertiesEventHandler DisplayInformationHandler;
-#else
typedef ITypedEventHandler<DisplayInformation*, IInspectable*> DisplayInformationHandler;
-#endif
#ifdef Q_OS_WINPHONE
typedef IEventHandler<BackPressedEventArgs*> BackPressedHandler;
#endif
@@ -419,199 +416,272 @@ static inline Qt::Key qKeyFromCode(quint32 code, int mods)
return static_cast<Qt::Key>(code & 0xff);
}
-QWinRTScreen::QWinRTScreen(ICoreWindow *window)
- : m_coreWindow(window)
- , m_depth(32)
- , m_format(QImage::Format_ARGB32_Premultiplied)
+typedef HRESULT (__stdcall ICoreApplication::*CoreApplicationCallbackRemover)(EventRegistrationToken);
+uint qHash(CoreApplicationCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
+typedef HRESULT (__stdcall ICoreWindow::*CoreWindowCallbackRemover)(EventRegistrationToken);
+uint qHash(CoreWindowCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
+typedef HRESULT (__stdcall IDisplayInformation::*DisplayCallbackRemover)(EventRegistrationToken);
+uint qHash(DisplayCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
+#ifdef Q_OS_WINPHONE
+typedef HRESULT (__stdcall IHardwareButtonsStatics::*HardwareButtonsCallbackRemover)(EventRegistrationToken);
+uint qHash(HardwareButtonsCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
+#endif
+
+class QWinRTScreenPrivate
+{
+public:
+ ComPtr<ICoreApplication> application;
+ ComPtr<ICoreWindow> coreWindow;
+ ComPtr<IDisplayInformationStatics> displayInformationStatics;
+ ComPtr<IDisplayInformation> displayInformation;
#ifdef Q_OS_WINPHONE
- , m_inputContext(new QWinRTInputContext(m_coreWindow))
+ ComPtr<IHardwareButtonsStatics> hardwareButtons;
+#endif
+
+ QScopedPointer<QWinRTCursor> cursor;
+#ifdef Q_OS_WINPHONE
+ QScopedPointer<QWinRTInputContext> inputContext;
#else
- , m_inputContext(Make<QWinRTInputContext>(m_coreWindow).Detach())
+ ComPtr<QWinRTInputContext> inputContext;
+#endif
+
+ QRectF geometry;
+ QSurfaceFormat surfaceFormat;
+ qreal dpi;
+ qreal devicePixelRatio;
+ Qt::ScreenOrientation nativeOrientation;
+ Qt::ScreenOrientation orientation;
+ QList<QWindow *> visibleWindows;
+#ifndef Q_OS_WINPHONE
+ QHash<quint32, QPair<Qt::Key, QString>> activeKeys;
+#endif
+ QTouchDevice *touchDevice;
+ QHash<quint32, QWindowSystemInterface::TouchPoint> touchPoints;
+
+ EGLDisplay eglDisplay;
+ EGLSurface eglSurface;
+
+ QHash<CoreApplicationCallbackRemover, EventRegistrationToken> applicationTokens;
+ QHash<CoreWindowCallbackRemover, EventRegistrationToken> windowTokens;
+ QHash<DisplayCallbackRemover, EventRegistrationToken> displayTokens;
+#ifdef Q_OS_WINPHONE
+ QHash<HardwareButtonsCallbackRemover, EventRegistrationToken> buttonsTokens;
#endif
- , m_cursor(new QWinRTCursor(window))
- , m_devicePixelRatio(1.0)
- , m_orientation(Qt::PrimaryOrientation)
- , m_touchDevice(Q_NULLPTR)
+};
+
+QWinRTScreen::QWinRTScreen()
+ : d_ptr(new QWinRTScreenPrivate)
{
+ Q_D(QWinRTScreen);
+ d->orientation = Qt::PrimaryOrientation;
+ d->touchDevice = Q_NULLPTR;
+
+ // Obtain the WinRT Application, view, and window
+ HRESULT hr;
+ hr = RoGetActivationFactory(Wrappers::HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
+ IID_PPV_ARGS(&d->application));
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->application->add_Suspending(Callback<SuspendHandler>(this, &QWinRTScreen::onSuspended).Get(), &d->applicationTokens[&ICoreApplication::remove_Resuming]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->application->add_Resuming(Callback<ResumeHandler>(this, &QWinRTScreen::onResume).Get(), &d->applicationTokens[&ICoreApplication::remove_Resuming]);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr<ICoreApplicationView> view;
+ hr = d->application->GetCurrentView(&view);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = view->get_CoreWindow(&d->coreWindow);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->Activate();
+ Q_ASSERT_SUCCEEDED(hr);
+
+#ifdef Q_OS_WINPHONE
+ d->inputContext.reset(new QWinRTInputContext(d->coreWindow.Get()));
+#else
+ d->inputContext = Make<QWinRTInputContext>(d->coreWindow.Get());
+#endif
+
Rect rect;
- window->get_Bounds(&rect);
- m_geometry = QRectF(0, 0, rect.Width, rect.Height);
-
- m_surfaceFormat.setAlphaBufferSize(0);
- m_surfaceFormat.setRedBufferSize(8);
- m_surfaceFormat.setGreenBufferSize(8);
- m_surfaceFormat.setBlueBufferSize(8);
-
- m_surfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES);
- m_surfaceFormat.setSamples(1);
- m_surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
- m_surfaceFormat.setDepthBufferSize(24);
- m_surfaceFormat.setStencilBufferSize(8);
-
- m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (m_eglDisplay == EGL_NO_DISPLAY)
+ d->coreWindow->get_Bounds(&rect);
+ d->geometry = QRectF(0, 0, rect.Width, rect.Height);
+
+ d->surfaceFormat.setAlphaBufferSize(0);
+ d->surfaceFormat.setRedBufferSize(8);
+ d->surfaceFormat.setGreenBufferSize(8);
+ d->surfaceFormat.setBlueBufferSize(8);
+ d->surfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES);
+ d->surfaceFormat.setSamples(1);
+ d->surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
+ d->surfaceFormat.setDepthBufferSize(24);
+ d->surfaceFormat.setStencilBufferSize(8);
+
+ d->eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (d->eglDisplay == EGL_NO_DISPLAY)
qFatal("Qt WinRT platform plugin: failed to initialize EGL display.");
- if (!eglInitialize(m_eglDisplay, NULL, NULL))
+ if (!eglInitialize(d->eglDisplay, NULL, NULL))
qFatal("Qt WinRT platform plugin: failed to initialize EGL. This can happen if you haven't included the D3D compiler DLL in your application package.");
// TODO: move this to Window
- m_eglSurface = eglCreateWindowSurface(m_eglDisplay, q_configFromGLFormat(m_eglDisplay, m_surfaceFormat), window, NULL);
- if (m_eglSurface == EGL_NO_SURFACE)
+ d->eglSurface = eglCreateWindowSurface(d->eglDisplay, q_configFromGLFormat(d->eglDisplay, d->surfaceFormat), d->coreWindow.Get(), NULL);
+ if (d->eglSurface == EGL_NO_SURFACE)
qFatal("Could not create EGL surface, error 0x%X", eglGetError());
- // Event handlers mapped to QEvents
- m_coreWindow->add_KeyDown(Callback<KeyHandler>(this, &QWinRTScreen::onKeyDown).Get(), &m_tokens[QEvent::KeyPress]);
- m_coreWindow->add_KeyUp(Callback<KeyHandler>(this, &QWinRTScreen::onKeyUp).Get(), &m_tokens[QEvent::KeyRelease]);
- m_coreWindow->add_CharacterReceived(Callback<CharacterReceivedHandler>(this, &QWinRTScreen::onCharacterReceived).Get(), &m_tokens[QEvent::User]);
- m_coreWindow->add_PointerEntered(Callback<PointerHandler>(this, &QWinRTScreen::onPointerEntered).Get(), &m_tokens[QEvent::Enter]);
- m_coreWindow->add_PointerExited(Callback<PointerHandler>(this, &QWinRTScreen::onPointerExited).Get(), &m_tokens[QEvent::Leave]);
- m_coreWindow->add_PointerMoved(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &m_tokens[QEvent::MouseMove]);
- m_coreWindow->add_PointerPressed(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &m_tokens[QEvent::MouseButtonPress]);
- m_coreWindow->add_PointerReleased(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &m_tokens[QEvent::MouseButtonRelease]);
- m_coreWindow->add_PointerWheelChanged(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &m_tokens[QEvent::Wheel]);
- m_coreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &QWinRTScreen::onSizeChanged).Get(), &m_tokens[QEvent::Resize]);
+ hr = d->coreWindow->add_KeyDown(Callback<KeyHandler>(this, &QWinRTScreen::onKeyDown).Get(), &d->windowTokens[&ICoreWindow::remove_KeyDown]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_KeyUp(Callback<KeyHandler>(this, &QWinRTScreen::onKeyUp).Get(), &d->windowTokens[&ICoreWindow::remove_KeyUp]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_CharacterReceived(Callback<CharacterReceivedHandler>(this, &QWinRTScreen::onCharacterReceived).Get(), &d->windowTokens[&ICoreWindow::remove_CharacterReceived]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_PointerEntered(Callback<PointerHandler>(this, &QWinRTScreen::onPointerEntered).Get(), &d->windowTokens[&ICoreWindow::remove_PointerEntered]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_PointerExited(Callback<PointerHandler>(this, &QWinRTScreen::onPointerExited).Get(), &d->windowTokens[&ICoreWindow::remove_PointerExited]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_PointerMoved(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerMoved]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_PointerPressed(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerPressed]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_PointerReleased(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerReleased]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_PointerWheelChanged(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerWheelChanged]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &QWinRTScreen::onSizeChanged).Get(), &d->windowTokens[&ICoreWindow::remove_SizeChanged]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_Activated(Callback<ActivatedHandler>(this, &QWinRTScreen::onActivated).Get(), &d->windowTokens[&ICoreWindow::remove_Activated]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_Closed(Callback<ClosedHandler>(this, &QWinRTScreen::onClosed).Get(), &d->windowTokens[&ICoreWindow::remove_Closed]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_VisibilityChanged(Callback<VisibilityChangedHandler>(this, &QWinRTScreen::onVisibilityChanged).Get(), &d->windowTokens[&ICoreWindow::remove_VisibilityChanged]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_AutomationProviderRequested(Callback<AutomationProviderRequestedHandler>(this, &QWinRTScreen::onAutomationProviderRequested).Get(), &d->windowTokens[&ICoreWindow::remove_AutomationProviderRequested]);
+ Q_ASSERT_SUCCEEDED(hr);
#ifdef Q_OS_WINPHONE
- ComPtr<IHardwareButtonsStatics> hardwareButtons;
- if (SUCCEEDED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(), &hardwareButtons)))
- hardwareButtons->add_BackPressed(Callback<BackPressedHandler>(this, &QWinRTScreen::onBackButtonPressed).Get(), &m_tokens[QEvent::User]);
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(), IID_PPV_ARGS(&d->hardwareButtons));
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->hardwareButtons->add_BackPressed(Callback<BackPressedHandler>(this, &QWinRTScreen::onBackButtonPressed).Get(), &d->buttonsTokens[&IHardwareButtonsStatics::remove_BackPressed]);
+ Q_ASSERT_SUCCEEDED(hr);
#endif // Q_OS_WINPHONE
- // Window event handlers
- m_coreWindow->add_Activated(Callback<ActivatedHandler>(this, &QWinRTScreen::onActivated).Get(), &m_tokens[QEvent::WindowActivate]);
- m_coreWindow->add_Closed(Callback<ClosedHandler>(this, &QWinRTScreen::onClosed).Get(), &m_tokens[QEvent::WindowDeactivate]);
- m_coreWindow->add_VisibilityChanged(Callback<VisibilityChangedHandler>(this, &QWinRTScreen::onVisibilityChanged).Get(), &m_tokens[QEvent::Show]);
- m_coreWindow->add_AutomationProviderRequested(Callback<AutomationProviderRequestedHandler>(this, &QWinRTScreen::onAutomationProviderRequested).Get(), &m_tokens[QEvent::InputMethodQuery]);
-
// Orientation handling
-#if _MSC_VER<=1700
- HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(),
- &m_displayInformation);
-#else
- HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Display_DisplayInformation).Get(),
- &m_displayInformationFactory);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get display information factory.");
- return;
- }
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Display_DisplayInformation).Get(),
+ IID_PPV_ARGS(&d->displayInformationStatics));
+ Q_ASSERT_SUCCEEDED(hr);
- hr = m_displayInformationFactory->GetForCurrentView(&m_displayInformation);
-#endif
-
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get display information for the current view.");
- return;
- }
+ hr = d->displayInformationStatics->GetForCurrentView(&d->displayInformation);
+ Q_ASSERT_SUCCEEDED(hr);
// Set native orientation
DisplayOrientations displayOrientation;
- hr = m_displayInformation->get_NativeOrientation(&displayOrientation);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get native orientation.");
- return;
- }
+ hr = d->displayInformation->get_NativeOrientation(&displayOrientation);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->nativeOrientation = static_cast<Qt::ScreenOrientation>(static_cast<int>(qtOrientationsFromNative(displayOrientation)));
- m_nativeOrientation = static_cast<Qt::ScreenOrientation>(static_cast<int>(qtOrientationsFromNative(displayOrientation)));
+ hr = d->displayInformation->add_OrientationChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onOrientationChanged).Get(), &d->displayTokens[&IDisplayInformation::remove_OrientationChanged]);
+ Q_ASSERT_SUCCEEDED(hr);
- hr = m_displayInformation->add_OrientationChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onOrientationChanged).Get(),
- &m_tokens[QEvent::OrientationChange]);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to add orientation change callback.");
- return;
- }
-
-#if _MSC_VER<=1700
- hr = m_displayInformation->add_LogicalDpiChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onDpiChanged).Get(),
- &m_tokens[QEvent::Type(QEvent::User + 1)]);
-#else
- hr = m_displayInformation->add_DpiChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onDpiChanged).Get(),
- &m_tokens[QEvent::Type(QEvent::User + 1)]);
-#endif
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to add logical dpi change callback.");
- return;
- }
+ hr = d->displayInformation->add_DpiChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onDpiChanged).Get(), &d->displayTokens[&IDisplayInformation::remove_DpiChanged]);
+ Q_ASSERT_SUCCEEDED(hr);
// Set initial orientation & pixel density
-#if _MSC_VER<=1700
- onOrientationChanged(Q_NULLPTR);
- onDpiChanged(Q_NULLPTR);
-#else
onOrientationChanged(Q_NULLPTR, Q_NULLPTR);
onDpiChanged(Q_NULLPTR, Q_NULLPTR);
-#endif
- setOrientationUpdateMask(m_nativeOrientation);
+ setOrientationUpdateMask(d->nativeOrientation);
+}
- if (SUCCEEDED(RoGetActivationFactory(Wrappers::HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
- IID_PPV_ARGS(&m_application)))) {
- m_application->add_Suspending(Callback<SuspendHandler>(this, &QWinRTScreen::onSuspended).Get(), &m_suspendTokens[Qt::ApplicationSuspended]);
- m_application->add_Resuming(Callback<ResumeHandler>(this, &QWinRTScreen::onResume).Get(), &m_suspendTokens[Qt::ApplicationHidden]);
- }
+QWinRTScreen::~QWinRTScreen()
+{
+ Q_D(QWinRTScreen);
+
+ // Unregister callbacks
+ for (QHash<CoreApplicationCallbackRemover, EventRegistrationToken>::const_iterator i = d->applicationTokens.begin(); i != d->applicationTokens.end(); ++i)
+ (d->application.Get()->*i.key())(i.value());
+ for (QHash<CoreWindowCallbackRemover, EventRegistrationToken>::const_iterator i = d->windowTokens.begin(); i != d->windowTokens.end(); ++i)
+ (d->coreWindow.Get()->*i.key())(i.value());
+ for (QHash<DisplayCallbackRemover, EventRegistrationToken>::const_iterator i = d->displayTokens.begin(); i != d->displayTokens.end(); ++i)
+ (d->displayInformation.Get()->*i.key())(i.value());
+#ifdef Q_OS_WINPHONE
+ for (QHash<HardwareButtonsCallbackRemover, EventRegistrationToken>::const_iterator i = d->buttonsTokens.begin(); i != d->buttonsTokens.end(); ++i)
+ (d->hardwareButtons.Get()->*i.key())(i.value());
+#endif
}
QRect QWinRTScreen::geometry() const
{
- return m_geometry.toRect();
+ Q_D(const QWinRTScreen);
+ return d->geometry.toRect();
}
int QWinRTScreen::depth() const
{
- return m_depth;
+ return 32;
}
QImage::Format QWinRTScreen::format() const
{
- return m_format;
+ return QImage::Format_ARGB32_Premultiplied;
}
QSurfaceFormat QWinRTScreen::surfaceFormat() const
{
- return m_surfaceFormat;
+ Q_D(const QWinRTScreen);
+ return d->surfaceFormat;
}
QSizeF QWinRTScreen::physicalSize() const
{
- return m_geometry.size() / m_dpi * qreal(25.4);
+ Q_D(const QWinRTScreen);
+ return d->geometry.size() / d->dpi * qreal(25.4);
}
QDpi QWinRTScreen::logicalDpi() const
{
- return QDpi(m_dpi, m_dpi);
+ Q_D(const QWinRTScreen);
+ return QDpi(d->dpi, d->dpi);
}
qreal QWinRTScreen::devicePixelRatio() const
{
- return m_devicePixelRatio;
+ Q_D(const QWinRTScreen);
+ return d->devicePixelRatio;
}
QWinRTInputContext *QWinRTScreen::inputContext() const
{
- return m_inputContext;
+ Q_D(const QWinRTScreen);
+#ifdef Q_OS_WINPHONE
+ return d->inputContext.data();
+#else
+ return d->inputContext.Get();
+#endif
}
QPlatformCursor *QWinRTScreen::cursor() const
{
- return m_cursor;
+ Q_D(const QWinRTScreen);
+ if (!d->cursor)
+ const_cast<QWinRTScreenPrivate *>(d)->cursor.reset(new QWinRTCursor);
+ return d->cursor.data();
}
Qt::KeyboardModifiers QWinRTScreen::keyboardModifiers() const
{
+ Q_D(const QWinRTScreen);
+
Qt::KeyboardModifiers mods;
CoreVirtualKeyStates mod;
- m_coreWindow->GetAsyncKeyState(VirtualKey_Shift, &mod);
+ d->coreWindow->GetAsyncKeyState(VirtualKey_Shift, &mod);
if (mod == CoreVirtualKeyStates_Down)
mods |= Qt::ShiftModifier;
- m_coreWindow->GetAsyncKeyState(VirtualKey_Menu, &mod);
+ d->coreWindow->GetAsyncKeyState(VirtualKey_Menu, &mod);
if (mod == CoreVirtualKeyStates_Down)
mods |= Qt::AltModifier;
- m_coreWindow->GetAsyncKeyState(VirtualKey_Control, &mod);
+ d->coreWindow->GetAsyncKeyState(VirtualKey_Control, &mod);
if (mod == CoreVirtualKeyStates_Down)
mods |= Qt::ControlModifier;
- m_coreWindow->GetAsyncKeyState(VirtualKey_LeftWindows, &mod);
+ d->coreWindow->GetAsyncKeyState(VirtualKey_LeftWindows, &mod);
if (mod == CoreVirtualKeyStates_Down) {
mods |= Qt::MetaModifier;
} else {
- m_coreWindow->GetAsyncKeyState(VirtualKey_RightWindows, &mod);
+ d->coreWindow->GetAsyncKeyState(VirtualKey_RightWindows, &mod);
if (mod == CoreVirtualKeyStates_Down)
mods |= Qt::MetaModifier;
}
@@ -620,56 +690,63 @@ Qt::KeyboardModifiers QWinRTScreen::keyboardModifiers() const
Qt::ScreenOrientation QWinRTScreen::nativeOrientation() const
{
- return m_nativeOrientation;
+ Q_D(const QWinRTScreen);
+ return d->nativeOrientation;
}
Qt::ScreenOrientation QWinRTScreen::orientation() const
{
- return m_orientation;
+ Q_D(const QWinRTScreen);
+ return d->orientation;
}
void QWinRTScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask)
{
-#if _MSC_VER<=1700
- m_displayInformation->put_AutoRotationPreferences(nativeOrientationsFromQt(mask));
-#else
- m_displayInformationFactory->put_AutoRotationPreferences(nativeOrientationsFromQt(mask));
-#endif
+ Q_D(QWinRTScreen);
+
+ HRESULT hr = d->displayInformationStatics->put_AutoRotationPreferences(nativeOrientationsFromQt(mask));
+ RETURN_VOID_IF_FAILED("Failed to set display auto rotation preferences.");
}
ICoreWindow *QWinRTScreen::coreWindow() const
{
- return m_coreWindow;
+ Q_D(const QWinRTScreen);
+ return d->coreWindow.Get();
}
EGLDisplay QWinRTScreen::eglDisplay() const
{
- return m_eglDisplay;
+ Q_D(const QWinRTScreen);
+ return d->eglDisplay;
}
EGLSurface QWinRTScreen::eglSurface() const
{
- return m_eglSurface;
+ Q_D(const QWinRTScreen);
+ return d->eglSurface;
}
QWindow *QWinRTScreen::topWindow() const
{
- return m_visibleWindows.isEmpty() ? 0 : m_visibleWindows.first();
+ Q_D(const QWinRTScreen);
+ return d->visibleWindows.isEmpty() ? 0 : d->visibleWindows.first();
}
void QWinRTScreen::addWindow(QWindow *window)
{
+ Q_D(QWinRTScreen);
if (window == topWindow())
return;
- m_visibleWindows.prepend(window);
+ d->visibleWindows.prepend(window);
QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason);
handleExpose();
}
void QWinRTScreen::removeWindow(QWindow *window)
{
+ Q_D(QWinRTScreen);
const bool wasTopWindow = window == topWindow();
- if (!m_visibleWindows.removeAll(window))
+ if (!d->visibleWindows.removeAll(window))
return;
if (wasTopWindow)
QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason);
@@ -678,17 +755,19 @@ void QWinRTScreen::removeWindow(QWindow *window)
void QWinRTScreen::raise(QWindow *window)
{
- m_visibleWindows.removeAll(window);
+ Q_D(QWinRTScreen);
+ d->visibleWindows.removeAll(window);
addWindow(window);
}
void QWinRTScreen::lower(QWindow *window)
{
+ Q_D(QWinRTScreen);
const bool wasTopWindow = window == topWindow();
- if (wasTopWindow && m_visibleWindows.size() == 1)
+ if (wasTopWindow && d->visibleWindows.size() == 1)
return;
- m_visibleWindows.removeAll(window);
- m_visibleWindows.append(window);
+ d->visibleWindows.removeAll(window);
+ d->visibleWindows.append(window);
if (wasTopWindow)
QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason);
handleExpose();
@@ -696,18 +775,18 @@ void QWinRTScreen::lower(QWindow *window)
void QWinRTScreen::handleExpose()
{
- if (m_visibleWindows.isEmpty())
+ Q_D(QWinRTScreen);
+ if (d->visibleWindows.isEmpty())
return;
- QList<QWindow *>::const_iterator it = m_visibleWindows.constBegin();
- QWindowSystemInterface::handleExposeEvent(*it, m_geometry.toRect());
- while (++it != m_visibleWindows.constEnd())
+ QList<QWindow *>::const_iterator it = d->visibleWindows.constBegin();
+ QWindowSystemInterface::handleExposeEvent(*it, d->geometry.toRect());
+ while (++it != d->visibleWindows.constEnd())
QWindowSystemInterface::handleExposeEvent(*it, QRegion());
QWindowSystemInterface::flushWindowSystemEvents();
}
-HRESULT QWinRTScreen::onKeyDown(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IKeyEventArgs *args)
+HRESULT QWinRTScreen::onKeyDown(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IKeyEventArgs *args)
{
- Q_UNUSED(window);
VirtualKey virtualKey;
args->get_VirtualKey(&virtualKey);
Qt::Key key = qKeyFromVirtual(virtualKey);
@@ -718,14 +797,14 @@ HRESULT QWinRTScreen::onKeyDown(ABI::Windows::UI::Core::ICoreWindow *window, ABI
return S_OK;
}
-HRESULT QWinRTScreen::onKeyUp(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IKeyEventArgs *args)
+HRESULT QWinRTScreen::onKeyUp(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IKeyEventArgs *args)
{
- Q_UNUSED(window);
Qt::KeyboardModifiers mods = keyboardModifiers();
#ifndef Q_OS_WINPHONE
+ Q_D(QWinRTScreen);
CorePhysicalKeyStatus status; // Look for a pressed character key
- if (SUCCEEDED(args->get_KeyStatus(&status)) && m_activeKeys.contains(status.ScanCode)) {
- QPair<Qt::Key, QString> keyStatus = m_activeKeys.take(status.ScanCode);
+ if (SUCCEEDED(args->get_KeyStatus(&status)) && d->activeKeys.contains(status.ScanCode)) {
+ QPair<Qt::Key, QString> keyStatus = d->activeKeys.take(status.ScanCode);
QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease,
keyStatus.first, mods, keyStatus.second);
return S_OK;
@@ -738,10 +817,8 @@ HRESULT QWinRTScreen::onKeyUp(ABI::Windows::UI::Core::ICoreWindow *window, ABI::
return S_OK;
}
-HRESULT QWinRTScreen::onCharacterReceived(ICoreWindow *window, ICharacterReceivedEventArgs *args)
+HRESULT QWinRTScreen::onCharacterReceived(ICoreWindow *, ICharacterReceivedEventArgs *args)
{
- Q_UNUSED(window);
-
quint32 keyCode;
args->get_KeyCode(&keyCode);
// Don't generate character events for non-printables; the meta key stage is enough
@@ -753,9 +830,10 @@ HRESULT QWinRTScreen::onCharacterReceived(ICoreWindow *window, ICharacterReceive
QString text = QChar(keyCode);
QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyPress, key, mods, text);
#ifndef Q_OS_WINPHONE
+ Q_D(QWinRTScreen);
CorePhysicalKeyStatus status; // Defer release to onKeyUp for physical keys
if (SUCCEEDED(args->get_KeyStatus(&status)) && !status.IsKeyReleased) {
- m_activeKeys.insert(status.ScanCode, qMakePair(key, text));
+ d->activeKeys.insert(status.ScanCode, qMakePair(key, text));
return S_OK;
}
#endif // !Q_OS_WINPHONE
@@ -763,10 +841,9 @@ HRESULT QWinRTScreen::onCharacterReceived(ICoreWindow *window, ICharacterReceive
return S_OK;
}
-HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *window, IPointerEventArgs *args)
+HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *, IPointerEventArgs *args)
{
- Q_UNUSED(window);
- IPointerPoint *pointerPoint;
+ ComPtr<IPointerPoint> pointerPoint;
if (SUCCEEDED(args->get_CurrentPoint(&pointerPoint))) {
// Assumes full-screen window
Point point;
@@ -774,24 +851,20 @@ HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *window, IPointerEventArgs *a
QPoint pos(point.X, point.Y);
QWindowSystemInterface::handleEnterEvent(topWindow(), pos, pos);
- pointerPoint->Release();
}
return S_OK;
}
-HRESULT QWinRTScreen::onPointerExited(ICoreWindow *window, IPointerEventArgs *args)
+HRESULT QWinRTScreen::onPointerExited(ICoreWindow *, IPointerEventArgs *)
{
- Q_UNUSED(window);
- Q_UNUSED(args);
QWindowSystemInterface::handleLeaveEvent(0);
return S_OK;
}
-HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *args)
+HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
{
- Q_UNUSED(window);
-
- IPointerPoint *pointerPoint;
+ Q_D(QWinRTScreen);
+ ComPtr<IPointerPoint> pointerPoint;
if (FAILED(args->get_CurrentPoint(&pointerPoint)))
return E_INVALIDARG;
@@ -812,27 +885,18 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a
if (modifiers & VirtualKeyModifiers_Windows)
mods |= Qt::MetaModifier;
- IPointerPointProperties *properties;
+ ComPtr<IPointerPointProperties> properties;
if (FAILED(pointerPoint->get_Properties(&properties)))
return E_INVALIDARG;
- PointerDeviceType pointerDeviceType;
-#if defined(Q_OS_WINPHONE) && _MSC_VER <= 1700
- pointerDeviceType = PointerDeviceType_Touch;
-#else
ComPtr<IPointerDevice> pointerDevice;
HRESULT hr = pointerPoint->get_PointerDevice(&pointerDevice);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get pointer device.");
- return S_OK;
- }
+ RETURN_OK_IF_FAILED("Failed to get pointer device.");
+ PointerDeviceType pointerDeviceType;
hr = pointerDevice->get_PointerDeviceType(&pointerDeviceType);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get pointer device type.");
- return S_OK;
- }
-#endif
+ RETURN_OK_IF_FAILED("Failed to get pointer device type.");
+
switch (pointerDeviceType) {
case PointerDeviceType_Mouse: {
qint32 delta;
@@ -872,12 +936,12 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a
break;
}
case PointerDeviceType_Touch: {
- if (!m_touchDevice) {
- m_touchDevice = new QTouchDevice;
- m_touchDevice->setName(QStringLiteral("WinRTTouchScreen"));
- m_touchDevice->setType(QTouchDevice::TouchScreen);
- m_touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure | QTouchDevice::NormalizedPosition);
- QWindowSystemInterface::registerTouchDevice(m_touchDevice);
+ if (!d->touchDevice) {
+ d->touchDevice = new QTouchDevice;
+ d->touchDevice->setName(QStringLiteral("WinRTTouchScreen"));
+ d->touchDevice->setType(QTouchDevice::TouchScreen);
+ d->touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure | QTouchDevice::NormalizedPosition);
+ QWindowSystemInterface::registerTouchDevice(d->touchDevice);
}
quint32 id;
@@ -889,8 +953,8 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a
float pressure;
properties->get_Pressure(&pressure);
- QHash<quint32, QWindowSystemInterface::TouchPoint>::iterator it = m_touchPoints.find(id);
- if (it != m_touchPoints.end()) {
+ QHash<quint32, QWindowSystemInterface::TouchPoint>::iterator it = d->touchPoints.find(id);
+ if (it != d->touchPoints.end()) {
boolean isPressed;
#ifndef Q_OS_WINPHONE
pointerPoint->get_IsInContact(&isPressed);
@@ -899,20 +963,20 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a
#endif
it.value().state = isPressed ? Qt::TouchPointMoved : Qt::TouchPointReleased;
} else {
- it = m_touchPoints.insert(id, QWindowSystemInterface::TouchPoint());
+ it = d->touchPoints.insert(id, QWindowSystemInterface::TouchPoint());
it.value().state = Qt::TouchPointPressed;
it.value().id = id;
}
it.value().area = QRectF(area.X, area.Y, area.Width, area.Height);
- it.value().normalPosition = QPointF(pos.x()/m_geometry.width(), pos.y()/m_geometry.height());
+ it.value().normalPosition = QPointF(pos.x()/d->geometry.width(), pos.y()/d->geometry.height());
it.value().pressure = pressure;
- QWindowSystemInterface::handleTouchEvent(topWindow(), m_touchDevice, m_touchPoints.values(), mods);
+ QWindowSystemInterface::handleTouchEvent(topWindow(), d->touchDevice, d->touchPoints.values(), mods);
// Remove released points, station others
- for (QHash<quint32, QWindowSystemInterface::TouchPoint>::iterator i = m_touchPoints.begin(); i != m_touchPoints.end();) {
+ for (QHash<quint32, QWindowSystemInterface::TouchPoint>::iterator i = d->touchPoints.begin(); i != d->touchPoints.end();) {
if (i.value().state == Qt::TouchPointReleased)
- i = m_touchPoints.erase(i);
+ i = d->touchPoints.erase(i);
else
(i++).value().state = Qt::TouchPointStationary;
}
@@ -950,46 +1014,42 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a
}
}
- properties->Release();
- pointerPoint->Release();
-
return S_OK;
}
HRESULT QWinRTScreen::onAutomationProviderRequested(ICoreWindow *, IAutomationProviderRequestedEventArgs *args)
{
+ Q_D(const QWinRTScreen);
#ifndef Q_OS_WINPHONE
- args->put_AutomationProvider(m_inputContext);
+ args->put_AutomationProvider(d->inputContext.Get());
#else
Q_UNUSED(args)
#endif
return S_OK;
}
-HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *window, IWindowSizeChangedEventArgs *args)
+HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *args)
{
- Q_UNUSED(window);
+ Q_D(QWinRTScreen);
Size size;
- if (FAILED(args->get_Size(&size))) {
- qWarning(Q_FUNC_INFO ": failed to get size");
- return S_OK;
- }
+ HRESULT hr = args->get_Size(&size);
+ RETURN_OK_IF_FAILED("Failed to get window size.");
// Regardless of state, all top-level windows are viewport-sized - this might change if
// a more advanced compositor is written.
- m_geometry.setSize(QSizeF(size.Width, size.Height));
- QWindowSystemInterface::handleScreenGeometryChange(screen(), m_geometry.toRect());
- QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), m_geometry.toRect());
+ d->geometry.setSize(QSizeF(size.Width, size.Height));
+ QWindowSystemInterface::handleScreenGeometryChange(screen(), d->geometry.toRect());
+ QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), d->geometry.toRect());
QPlatformScreen::resizeMaximizedWindows();
handleExpose();
return S_OK;
}
-HRESULT QWinRTScreen::onActivated(ICoreWindow *window, IWindowActivatedEventArgs *args)
+HRESULT QWinRTScreen::onActivated(ICoreWindow *, IWindowActivatedEventArgs *args)
{
- Q_UNUSED(window);
+ Q_D(QWinRTScreen);
CoreWindowActivationState activationState;
args->get_WindowActivationState(&activationState);
@@ -999,7 +1059,7 @@ HRESULT QWinRTScreen::onActivated(ICoreWindow *window, IWindowActivatedEventArgs
}
// Activate topWindow
- if (!m_visibleWindows.isEmpty()) {
+ if (!d->visibleWindows.isEmpty()) {
Qt::FocusReason focusReason = activationState == CoreWindowActivationState_PointerActivated
? Qt::MouseFocusReason : Qt::ActiveWindowFocusReason;
QWindowSystemInterface::handleWindowActivated(topWindow(), focusReason);
@@ -1022,21 +1082,15 @@ HRESULT QWinRTScreen::onResume(IInspectable *, IInspectable *)
return S_OK;
}
-HRESULT QWinRTScreen::onClosed(ICoreWindow *window, ICoreWindowEventArgs *args)
+HRESULT QWinRTScreen::onClosed(ICoreWindow *, ICoreWindowEventArgs *)
{
- Q_UNUSED(window);
- Q_UNUSED(args);
-
foreach (QWindow *w, QGuiApplication::topLevelWindows())
QWindowSystemInterface::handleCloseEvent(w);
return S_OK;
}
-HRESULT QWinRTScreen::onVisibilityChanged(ICoreWindow *window, IVisibilityChangedEventArgs *args)
+HRESULT QWinRTScreen::onVisibilityChanged(ICoreWindow *, IVisibilityChangedEventArgs *args)
{
- Q_UNUSED(window);
- Q_UNUSED(args);
-
boolean visible;
args->get_Visible(&visible);
QWindowSystemInterface::handleApplicationStateChanged(visible ? Qt::ApplicationActive : Qt::ApplicationHidden);
@@ -1045,60 +1099,48 @@ HRESULT QWinRTScreen::onVisibilityChanged(ICoreWindow *window, IVisibilityChange
return S_OK;
}
-#if _MSC_VER<=1700
-HRESULT QWinRTScreen::onOrientationChanged(IInspectable *)
-#else
HRESULT QWinRTScreen::onOrientationChanged(IDisplayInformation *, IInspectable *)
-#endif
{
+ Q_D(QWinRTScreen);
+
DisplayOrientations displayOrientation;
- m_displayInformation->get_CurrentOrientation(&displayOrientation);
+ HRESULT hr = d->displayInformation->get_CurrentOrientation(&displayOrientation);
+ RETURN_OK_IF_FAILED("Failed to get current orientations.");
+
Qt::ScreenOrientation newOrientation = static_cast<Qt::ScreenOrientation>(static_cast<int>(qtOrientationsFromNative(displayOrientation)));
- if (m_orientation != newOrientation) {
- m_orientation = newOrientation;
- QWindowSystemInterface::handleScreenOrientationChange(screen(), m_orientation);
+ if (d->orientation != newOrientation) {
+ d->orientation = newOrientation;
+ QWindowSystemInterface::handleScreenOrientationChange(screen(), d->orientation);
}
return S_OK;
}
-#if _MSC_VER<=1700
-HRESULT QWinRTScreen::onDpiChanged(IInspectable *)
-#else
HRESULT QWinRTScreen::onDpiChanged(IDisplayInformation *, IInspectable *)
-#endif
{
-#if defined(Q_OS_WINPHONE) && _MSC_VER>=1800 // WP 8.1
+ Q_D(QWinRTScreen);
+
+ HRESULT hr;
+#ifdef Q_OS_WINPHONE
ComPtr<IDisplayInformation2> displayInformation;
- HRESULT hr = m_displayInformation->QueryInterface(IID_IDisplayInformation2, &displayInformation);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to cast display information.");
- return S_OK;
- }
- hr = displayInformation->get_RawPixelsPerViewPixel(&m_devicePixelRatio);
+ hr = d->displayInformation.As(&displayInformation);
+ RETURN_OK_IF_FAILED("Failed to cast display information.");
+ hr = displayInformation->get_RawPixelsPerViewPixel(&d->devicePixelRatio);
#else
ResolutionScale resolutionScale;
- HRESULT hr = m_displayInformation->get_ResolutionScale(&resolutionScale);
-#endif
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get display resolution scale.");
- return S_OK;
- }
-#if !(defined(Q_OS_WINPHONE) && _MSC_VER>=1800) // !WP8.1
- m_devicePixelRatio = qreal(resolutionScale) / 100;
+ hr = d->displayInformation->get_ResolutionScale(&resolutionScale);
+ d->devicePixelRatio = qreal(resolutionScale) / 100;
#endif
+ RETURN_OK_IF_FAILED("Failed to get resolution scale");
// Correct the scale factor for integer window size
- m_devicePixelRatio = m_devicePixelRatio * ((m_geometry.width()/qRound(m_geometry.width()) +
- m_geometry.height()/qRound(m_geometry.height())) / 2.0);
+ d->devicePixelRatio = d->devicePixelRatio * ((d->geometry.width()/qRound(d->geometry.width()) +
+ d->geometry.height()/qRound(d->geometry.height())) / 2.0);
FLOAT dpi;
- hr = m_displayInformation->get_LogicalDpi(&dpi);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get logical DPI.");
- return S_OK;
- }
- m_dpi = dpi;
+ hr = d->displayInformation->get_LogicalDpi(&dpi);
+ RETURN_OK_IF_FAILED("Failed to get logical DPI.");
+ d->dpi = dpi;
return S_OK;
}
@@ -1106,14 +1148,16 @@ HRESULT QWinRTScreen::onDpiChanged(IDisplayInformation *, IInspectable *)
#ifdef Q_OS_WINPHONE
HRESULT QWinRTScreen::onBackButtonPressed(IInspectable *, IBackPressedEventArgs *args)
{
+ Q_D(QWinRTScreen);
+
QKeyEvent backPress(QEvent::KeyPress, Qt::Key_Back, Qt::NoModifier);
QKeyEvent backRelease(QEvent::KeyRelease, Qt::Key_Back, Qt::NoModifier);
backPress.setAccepted(false);
backRelease.setAccepted(false);
- QObject *receiver = m_visibleWindows.isEmpty()
+ QObject *receiver = d->visibleWindows.isEmpty()
? static_cast<QObject *>(QGuiApplication::instance())
- : static_cast<QObject *>(m_visibleWindows.first());
+ : static_cast<QObject *>(d->visibleWindows.first());
// If the event is ignored, the app will suspend
QGuiApplication::sendEvent(receiver, &backPress);
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h
index d39683a960..18745f1017 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.h
+++ b/src/plugins/platforms/winrt/qwinrtscreen.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -45,19 +45,12 @@
#include <qpa/qplatformscreen.h>
#include <qpa/qwindowsysteminterface.h>
-#include <QtCore/QHash>
-#include <QtGui/QSurfaceFormat>
#include <EGL/egl.h>
-#include <EventToken.h>
-
namespace ABI {
namespace Windows {
namespace ApplicationModel {
struct ISuspendingEventArgs;
- namespace Core {
- struct ICoreApplication;
- }
}
namespace UI {
namespace Core {
@@ -71,14 +64,9 @@ namespace ABI {
struct IWindowActivatedEventArgs;
struct IWindowSizeChangedEventArgs;
}
- namespace ViewManagement {
- struct IApplicationViewStatics;
- }
}
namespace Graphics {
namespace Display {
- struct IDisplayPropertiesStatics;
- struct IDisplayInformationStatics;
struct IDisplayInformation;
}
}
@@ -99,14 +87,14 @@ QT_BEGIN_NAMESPACE
class QTouchDevice;
class QWinRTEGLContext;
-class QWinRTPageFlipper;
class QWinRTCursor;
class QWinRTInputContext;
-
+class QWinRTScreenPrivate;
class QWinRTScreen : public QPlatformScreen
{
public:
- explicit QWinRTScreen(ABI::Windows::UI::Core::ICoreWindow *window);
+ explicit QWinRTScreen();
+ ~QWinRTScreen();
QRect geometry() const;
int depth() const;
QImage::Format format() const;
@@ -135,69 +123,31 @@ public:
private:
void handleExpose();
- // Event handlers
- QHash<QEvent::Type, EventRegistrationToken> m_tokens;
- QHash<Qt::ApplicationState, EventRegistrationToken> m_suspendTokens;
+ HRESULT onKeyDown(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IKeyEventArgs *);
+ HRESULT onKeyUp(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IKeyEventArgs *);
+ HRESULT onCharacterReceived(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::ICharacterReceivedEventArgs *);
+ HRESULT onPointerEntered(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IPointerEventArgs *);
+ HRESULT onPointerExited(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IPointerEventArgs *);
+ HRESULT onPointerUpdated(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IPointerEventArgs *);
+ HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *);
- HRESULT onKeyDown(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IKeyEventArgs *args);
- HRESULT onKeyUp(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IKeyEventArgs *args);
- HRESULT onCharacterReceived(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::ICharacterReceivedEventArgs *args);
- HRESULT onPointerEntered(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IPointerEventArgs *args);
- HRESULT onPointerExited(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IPointerEventArgs *args);
- HRESULT onPointerUpdated(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IPointerEventArgs *args);
- HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *args);
-
- HRESULT onActivated(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowActivatedEventArgs *args);
+ HRESULT onActivated(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowActivatedEventArgs *);
HRESULT onSuspended(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *);
HRESULT onResume(IInspectable *, IInspectable *);
- HRESULT onClosed(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::ICoreWindowEventArgs *args);
- HRESULT onVisibilityChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IVisibilityChangedEventArgs *args);
- HRESULT onAutomationProviderRequested(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IAutomationProviderRequestedEventArgs *args);
+ HRESULT onClosed(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::ICoreWindowEventArgs *);
+ HRESULT onVisibilityChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IVisibilityChangedEventArgs *);
+ HRESULT onAutomationProviderRequested(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IAutomationProviderRequestedEventArgs *);
-#if _MSC_VER<=1700
- HRESULT onOrientationChanged(IInspectable *);
- HRESULT onDpiChanged(IInspectable *);
-#else
HRESULT onOrientationChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *);
HRESULT onDpiChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *);
-#endif
#ifdef Q_OS_WINPHONE
HRESULT onBackButtonPressed(IInspectable *, ABI::Windows::Phone::UI::Input::IBackPressedEventArgs *args);
#endif
- ABI::Windows::UI::Core::ICoreWindow *m_coreWindow;
- ABI::Windows::UI::ViewManagement::IApplicationViewStatics *m_applicationView;
- ABI::Windows::ApplicationModel::Core::ICoreApplication *m_application;
-
- QRectF m_geometry;
- QImage::Format m_format;
- QSurfaceFormat m_surfaceFormat;
- qreal m_dpi;
- int m_depth;
- QWinRTInputContext *m_inputContext;
- QWinRTCursor *m_cursor;
- QList<QWindow *> m_visibleWindows;
-
- EGLDisplay m_eglDisplay;
- EGLSurface m_eglSurface;
-
-#if _MSC_VER<=1700
- ABI::Windows::Graphics::Display::IDisplayPropertiesStatics *m_displayInformation;
-#else
- ABI::Windows::Graphics::Display::IDisplayInformationStatics *m_displayInformationFactory;
- ABI::Windows::Graphics::Display::IDisplayInformation *m_displayInformation;
-#endif
- qreal m_devicePixelRatio;
- Qt::ScreenOrientation m_nativeOrientation;
- Qt::ScreenOrientation m_orientation;
-
-#ifndef Q_OS_WINPHONE
- QHash<quint32, QPair<Qt::Key, QString> > m_activeKeys;
-#endif
- QTouchDevice *m_touchDevice;
- QHash<quint32, QWindowSystemInterface::TouchPoint> m_touchPoints;
+ QScopedPointer<QWinRTScreenPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTScreen)
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtservices.cpp b/src/plugins/platforms/winrt/qwinrtservices.cpp
index b0f9247d36..6272b46f44 100644
--- a/src/plugins/platforms/winrt/qwinrtservices.cpp
+++ b/src/plugins/platforms/winrt/qwinrtservices.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -43,6 +43,7 @@
#include <QtCore/QUrl>
#include <QtCore/QDir>
#include <QtCore/QCoreApplication>
+#include <QtCore/qfunctions_winrt.h>
#include <wrl.h>
#include <windows.foundation.h>
@@ -56,83 +57,84 @@ using namespace ABI::Windows::System;
QT_BEGIN_NAMESPACE
+class QWinRTServicesPrivate
+{
+public:
+ ComPtr<IUriRuntimeClassFactory> uriFactory;
+ ComPtr<IStorageFileStatics> fileFactory;
+ ComPtr<ILauncherStatics> launcher;
+};
+
QWinRTServices::QWinRTServices()
+ : d_ptr(new QWinRTServicesPrivate)
{
- GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_Uri).Get(), &m_uriFactory);
- GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_StorageFile).Get(), &m_fileFactory);
- GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_System_Launcher).Get(), &m_launcher);
+ Q_D(QWinRTServices);
+
+ HRESULT hr;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_Uri).Get(),
+ IID_PPV_ARGS(&d->uriFactory));
+ Q_ASSERT_X(SUCCEEDED(hr), Q_FUNC_INFO, qPrintable(qt_error_string(hr)));
+
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_StorageFile).Get(),
+ IID_PPV_ARGS(&d->fileFactory));
+ Q_ASSERT_X(SUCCEEDED(hr), Q_FUNC_INFO, qPrintable(qt_error_string(hr)));
+
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_System_Launcher).Get(),
+ IID_PPV_ARGS(&d->launcher));
+ Q_ASSERT_X(SUCCEEDED(hr), Q_FUNC_INFO, qPrintable(qt_error_string(hr)));
}
QWinRTServices::~QWinRTServices()
{
- if (m_uriFactory)
- m_uriFactory->Release();
-
- if (m_fileFactory)
- m_fileFactory->Release();
-
- if (m_launcher)
- m_launcher->Release();
}
bool QWinRTServices::openUrl(const QUrl &url)
{
- if (!(m_uriFactory && m_launcher))
- return QPlatformServices::openUrl(url);
+ Q_D(QWinRTServices);
- IUriRuntimeClass *uri;
+ ComPtr<IUriRuntimeClass> uri;
QString urlString = url.toString();
- // ### TODO: Replace with HStringReference when WP8.0 support is removed
- HString uriString;
- uriString.Set((const wchar_t*)urlString.utf16(), urlString.length());
- m_uriFactory->CreateUri(uriString.Get(), &uri);
- if (!uri)
- return false;
-
- IAsyncOperation<bool> *launchOp;
- m_launcher->LaunchUriAsync(uri, &launchOp);
- uri->Release();
- if (!launchOp)
- return false;
-
- boolean result = false;
- while (launchOp->GetResults(&result) == E_ILLEGAL_METHOD_CALL)
- QCoreApplication::processEvents();
- launchOp->Release();
+ HStringReference uriString(reinterpret_cast<LPCWSTR>(urlString.utf16()), urlString.length());
+ HRESULT hr = d->uriFactory->CreateUri(uriString.Get(), &uri);
+ RETURN_FALSE_IF_FAILED("Failed to create URI from QUrl.");
+
+ ComPtr<IAsyncOperation<bool>> op;
+ hr = d->launcher->LaunchUriAsync(uri.Get(), &op);
+ RETURN_FALSE_IF_FAILED("Failed to start URI launch.");
+
+ boolean result;
+ hr = QWinRTFunctions::await(op, &result);
+ RETURN_FALSE_IF_FAILED("Failed to launch URI.");
return result;
}
bool QWinRTServices::openDocument(const QUrl &url)
{
- if (!(m_fileFactory && m_launcher))
- return QPlatformServices::openDocument(url);
-
- const QString pathString = QDir::toNativeSeparators(url.toLocalFile());
- // ### TODO: Replace with HStringReference when WP8.0 support is removed
- HString path;
- path.Set((const wchar_t*)pathString.utf16(), pathString.length());
- IAsyncOperation<StorageFile*> *fileOp;
- m_fileFactory->GetFileFromPathAsync(path.Get(), &fileOp);
- if (!fileOp)
- return false;
-
- IStorageFile *file = nullptr;
- while (fileOp->GetResults(&file) == E_ILLEGAL_METHOD_CALL)
- QCoreApplication::processEvents();
- fileOp->Release();
- if (!file)
- return false;
-
- IAsyncOperation<bool> *launchOp;
- m_launcher->LaunchFileAsync(file, &launchOp);
- if (!launchOp)
- return false;
-
- boolean result = false;
- while (launchOp->GetResults(&result) == E_ILLEGAL_METHOD_CALL)
- QCoreApplication::processEvents();
- launchOp->Release();
+ Q_D(QWinRTServices);
+
+ HRESULT hr;
+ ComPtr<IStorageFile> file;
+ {
+ const QString pathString = QDir::toNativeSeparators(url.toLocalFile());
+ HStringReference path(reinterpret_cast<LPCWSTR>(pathString.utf16()), pathString.length());
+ ComPtr<IAsyncOperation<StorageFile *>> op;
+ hr = d->fileFactory->GetFileFromPathAsync(path.Get(), &op);
+ RETURN_FALSE_IF_FAILED("Failed to initialize file URI.");
+
+ hr = QWinRTFunctions::await(op, file.GetAddressOf());
+ RETURN_FALSE_IF_FAILED("Failed to get file URI.");
+ }
+
+ boolean result;
+ {
+ ComPtr<IAsyncOperation<bool>> op;
+ hr = d->launcher->LaunchFileAsync(file.Get(), &op);
+ RETURN_FALSE_IF_FAILED("Failed to start file launch.");
+
+ hr = QWinRTFunctions::await(op, &result);
+ RETURN_FALSE_IF_FAILED("Failed to launch file.");
+ }
return result;
}
diff --git a/src/plugins/platforms/winrt/qwinrtservices.h b/src/plugins/platforms/winrt/qwinrtservices.h
index 9cc917030a..d3abe6f2bd 100644
--- a/src/plugins/platforms/winrt/qwinrtservices.h
+++ b/src/plugins/platforms/winrt/qwinrtservices.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -43,23 +43,11 @@
#define QWINRTSERVICES_H
#include <qpa/qplatformservices.h>
+#include <QtCore/QScopedPointer>
-namespace ABI {
- namespace Windows {
- namespace Foundation {
- struct IUriRuntimeClassFactory;
- }
- namespace Storage {
- struct IStorageFileStatics;
- }
- namespace System {
- struct ILauncherStatics;
- }
- }
-}
-
-QT_BEGIN_NAMESPACE
+QT_USE_NAMESPACE
+class QWinRTServicesPrivate;
class QWinRTServices : public QPlatformServices
{
public:
@@ -70,11 +58,8 @@ public:
bool openDocument(const QUrl &url);
private:
- ABI::Windows::Foundation::IUriRuntimeClassFactory *m_uriFactory;
- ABI::Windows::Storage::IStorageFileStatics *m_fileFactory;
- ABI::Windows::System::ILauncherStatics *m_launcher;
+ QScopedPointer<QWinRTServicesPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTServices)
};
-QT_END_NAMESPACE
-
#endif // QWINRTSERVICES_H
diff --git a/src/plugins/platforms/winrt/qwinrttheme.cpp b/src/plugins/platforms/winrt/qwinrttheme.cpp
new file mode 100644
index 0000000000..f9c2e21676
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrttheme.cpp
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrttheme.h"
+#include "qwinrtmessagedialoghelper.h"
+
+#include <QtCore/qfunctions_winrt.h>
+#include <QtGui/QPalette>
+
+#include <wrl.h>
+#include <windows.ui.h>
+#include <windows.ui.viewmanagement.h>
+using namespace Microsoft::WRL;
+using namespace ABI::Windows::UI;
+using namespace ABI::Windows::UI::ViewManagement;
+
+QT_BEGIN_NAMESPACE
+
+static IUISettings *uiSettings()
+{
+ static ComPtr<IUISettings> settings;
+ if (!settings) {
+ HRESULT hr;
+ hr = RoActivateInstance(Wrappers::HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_UISettings).Get(),
+ &settings);
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+ return settings.Get();
+}
+
+class QWinRTThemePrivate
+{
+public:
+ QPalette palette;
+};
+
+QWinRTTheme::QWinRTTheme()
+ : d_ptr(new QWinRTThemePrivate)
+{
+ Q_D(QWinRTTheme);
+
+ HRESULT hr;
+ union { Color ui; QRgb qt; } color;
+
+ hr = uiSettings()->UIElementColor(UIElementType_ActiveCaption, &color.ui);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->palette.setColor(QPalette::ToolTipBase, color.qt);
+
+ hr = uiSettings()->UIElementColor(UIElementType_Background, &color.ui);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->palette.setColor(QPalette::AlternateBase, color.qt);
+
+ hr = uiSettings()->UIElementColor(UIElementType_ButtonFace, &color.ui);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->palette.setColor(QPalette::Button, color.qt);
+ d->palette.setColor(QPalette::Midlight, QColor(color.qt).lighter(110));
+ d->palette.setColor(QPalette::Light, QColor(color.qt).lighter(150));
+ d->palette.setColor(QPalette::Mid, QColor(color.qt).dark(130));
+ d->palette.setColor(QPalette::Dark, QColor(color.qt).dark(150));
+
+ hr = uiSettings()->UIElementColor(UIElementType_ButtonText, &color.ui);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->palette.setColor(QPalette::ButtonText, color.qt);
+ d->palette.setColor(QPalette::Text, color.qt);
+
+ hr = uiSettings()->UIElementColor(UIElementType_CaptionText, &color.ui);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->palette.setColor(QPalette::ToolTipText, color.qt);
+
+ hr = uiSettings()->UIElementColor(UIElementType_Highlight, &color.ui);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->palette.setColor(QPalette::Highlight, color.qt);
+
+ hr = uiSettings()->UIElementColor(UIElementType_HighlightText, &color.ui);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->palette.setColor(QPalette::HighlightedText, color.qt);
+
+ hr = uiSettings()->UIElementColor(UIElementType_Window, &color.ui);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->palette.setColor(QPalette::Window, color.qt);
+ d->palette.setColor(QPalette::Base, color.qt);
+
+#ifdef Q_OS_WINPHONE
+ hr = uiSettings()->UIElementColor(UIElementType_TextHigh, &color.ui);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->palette.setColor(QPalette::BrightText, color.qt);
+#else
+ hr = uiSettings()->UIElementColor(UIElementType_Hotlight, &color.ui);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->palette.setColor(QPalette::BrightText, color.qt);
+#endif
+}
+
+bool QWinRTTheme::usePlatformNativeDialog(DialogType type) const
+{
+ static bool useNativeDialogs = qEnvironmentVariableIsSet("QT_USE_WINRT_NATIVE_DIALOGS")
+ ? qgetenv("QT_USE_WINRT_NATIVE_DIALOGS").toInt() : true;
+
+ if (type == MessageDialog)
+ return useNativeDialogs;
+ return false;
+}
+
+QPlatformDialogHelper *QWinRTTheme::createPlatformDialogHelper(DialogType type) const
+{
+ switch (type) {
+ case MessageDialog:
+ return new QWinRTMessageDialogHelper(this);
+ default:
+ break;
+ }
+ return QPlatformTheme::createPlatformDialogHelper(type);
+}
+
+QVariant QWinRTTheme::styleHint(QPlatformIntegration::StyleHint hint)
+{
+ HRESULT hr;
+ switch (hint) {
+ case QPlatformIntegration::CursorFlashTime: {
+ quint32 blinkRate;
+ hr = uiSettings()->get_CaretBlinkRate(&blinkRate);
+ RETURN_IF_FAILED("Failed to get caret blink rate", return defaultThemeHint(CursorFlashTime));
+ return blinkRate;
+ }
+ case QPlatformIntegration::KeyboardInputInterval:
+ return defaultThemeHint(KeyboardInputInterval);
+ case QPlatformIntegration::MouseDoubleClickInterval: {
+ quint32 doubleClickTime;
+ hr = uiSettings()->get_DoubleClickTime(&doubleClickTime);
+ RETURN_IF_FAILED("Failed to get double click time", return defaultThemeHint(MouseDoubleClickInterval));
+ return doubleClickTime;
+ }
+ case QPlatformIntegration::StartDragDistance:
+ return defaultThemeHint(StartDragDistance);
+ case QPlatformIntegration::StartDragTime:
+ return defaultThemeHint(StartDragTime);
+ case QPlatformIntegration::KeyboardAutoRepeatRate:
+ return defaultThemeHint(KeyboardAutoRepeatRate);
+ case QPlatformIntegration::ShowIsFullScreen:
+ return true;
+ case QPlatformIntegration::PasswordMaskDelay:
+ return defaultThemeHint(PasswordMaskDelay);
+ case QPlatformIntegration::FontSmoothingGamma:
+ return qreal(1.7);
+ case QPlatformIntegration::StartDragVelocity:
+ return defaultThemeHint(StartDragVelocity);
+ case QPlatformIntegration::UseRtlExtensions:
+ return false;
+ case QPlatformIntegration::SynthesizeMouseFromTouchEvents:
+ return true;
+ case QPlatformIntegration::PasswordMaskCharacter:
+ return defaultThemeHint(PasswordMaskCharacter);
+ case QPlatformIntegration::SetFocusOnTouchRelease:
+ return false;
+ case QPlatformIntegration::ShowIsMaximized:
+ return false;
+ case MousePressAndHoldInterval:
+ return defaultThemeHint(MousePressAndHoldInterval);
+ default:
+ break;
+ }
+ return QVariant();
+}
+
+const QPalette *QWinRTTheme::palette(Palette type) const
+{
+ Q_D(const QWinRTTheme);
+ if (type == SystemPalette)
+ return &d->palette;
+ return QPlatformTheme::palette(type);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrttheme.h b/src/plugins/platforms/winrt/qwinrttheme.h
new file mode 100644
index 0000000000..f7fd07c70d
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrttheme.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTTHEME_H
+#define QWINRTTHEME_H
+
+#include <qpa/qplatformtheme.h>
+#include <qpa/qplatformintegration.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTThemePrivate;
+class QWinRTTheme : public QPlatformTheme
+{
+public:
+ QWinRTTheme();
+
+ bool usePlatformNativeDialog(DialogType type) const;
+ QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const;
+
+ const QPalette *palette(Palette type = SystemPalette) const Q_DECL_OVERRIDE;
+
+ static QVariant styleHint(QPlatformIntegration::StyleHint hint);
+
+private:
+ QScopedPointer<QWinRTThemePrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTTheme)
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINRTTHEME_H
diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro
index 349cdf11c9..427920a670 100644
--- a/src/plugins/platforms/winrt/winrt.pro
+++ b/src/plugins/platforms/winrt/winrt.pro
@@ -35,12 +35,13 @@ SOURCES = \
qwinrtfontdatabase.cpp \
qwinrtinputcontext.cpp \
qwinrtintegration.cpp \
- qwinrtplatformmessagedialoghelper.cpp \
- qwinrtplatformtheme.cpp \
+ qwinrtmessagedialoghelper.cpp \
qwinrtscreen.cpp \
qwinrtservices.cpp \
+ qwinrttheme.cpp \
qwinrtwindow.cpp
+
HEADERS = \
qwinrtbackingstore.h \
qwinrtcursor.h \
@@ -49,12 +50,13 @@ HEADERS = \
qwinrtfontdatabase.h \
qwinrtinputcontext.h \
qwinrtintegration.h \
- qwinrtplatformmessagedialoghelper.h \
- qwinrtplatformtheme.h \
+ qwinrtmessagedialoghelper.h \
qwinrtscreen.h \
qwinrtservices.h \
+ qwinrttheme.h \
qwinrtwindow.h
+
BLIT_INPUT = $$PWD/blit.hlsl
fxc_blitps.commands = fxc.exe /nologo /T ps_4_0_level_9_1 /E blitps /Vn q_blitps /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
fxc_blitps.output = $$OUT_PWD/blitps.h
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp
index 9a56455940..45ccd9929e 100644
--- a/src/plugins/platforms/xcb/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/qglxintegration.cpp
@@ -54,6 +54,7 @@
#include "qglxintegration.h"
#include <QtPlatformSupport/private/qglxconvenience_p.h>
+#include <QtPlatformHeaders/QGLXNativeContext>
#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
#include <dlfcn.h>
@@ -83,31 +84,32 @@ typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXC
#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
#endif
-static Window createDummyWindow(QXcbScreen *screen, XVisualInfo *visualInfo)
+static Window createDummyWindow(Display *dpy, XVisualInfo *visualInfo, int screenNumber, Window rootWin)
{
- Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(screen), screen->root(), visualInfo->visual, AllocNone);
+ Colormap cmap = XCreateColormap(dpy, rootWin, visualInfo->visual, AllocNone);
XSetWindowAttributes a;
- a.background_pixel = WhitePixel(DISPLAY_FROM_XCB(screen), screen->screenNumber());
- a.border_pixel = BlackPixel(DISPLAY_FROM_XCB(screen), screen->screenNumber());
+ a.background_pixel = WhitePixel(dpy, screenNumber);
+ a.border_pixel = BlackPixel(dpy, screenNumber);
a.colormap = cmap;
+ a.override_redirect = true;
- Window window = XCreateWindow(DISPLAY_FROM_XCB(screen), screen->root(),
+ Window window = XCreateWindow(dpy, rootWin,
0, 0, 100, 100,
0, visualInfo->depth, InputOutput, visualInfo->visual,
- CWBackPixel|CWBorderPixel|CWColormap, &a);
+ CWBackPixel|CWBorderPixel|CWColormap|CWOverrideRedirect, &a);
#ifndef QT_NO_DEBUG
- XStoreName(DISPLAY_FROM_XCB(screen), window, "Qt GLX dummy window");
+ XStoreName(dpy, window, "Qt GLX dummy window");
#endif
- XFreeColormap(DISPLAY_FROM_XCB(screen), cmap);
+ XFreeColormap(dpy, cmap);
return window;
}
-static Window createDummyWindow(QXcbScreen *screen, GLXFBConfig config)
+static Window createDummyWindow(Display *dpy, GLXFBConfig config, int screenNumber, Window rootWin)
{
- XVisualInfo *visualInfo = glXGetVisualFromFBConfig(DISPLAY_FROM_XCB(screen), config);
+ XVisualInfo *visualInfo = glXGetVisualFromFBConfig(dpy, config);
if (!visualInfo)
qFatal("Could not initialize GLX");
- Window window = createDummyWindow(screen, visualInfo);
+ Window window = createDummyWindow(dpy, visualInfo, screenNumber, rootWin);
XFree(visualInfo);
return window;
}
@@ -160,14 +162,25 @@ static void updateFormatFromContext(QSurfaceFormat &format)
}
}
-QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share)
+QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share,
+ const QVariant &nativeHandle)
: QPlatformOpenGLContext()
, m_screen(screen)
+ , m_config(0)
, m_context(0)
, m_shareContext(0)
, m_format(format)
, m_isPBufferCurrent(false)
, m_swapInterval(-1)
+ , m_ownsContext(nativeHandle.isNull())
+{
+ if (nativeHandle.isNull())
+ init(screen, share);
+ else
+ init(screen, share, nativeHandle);
+}
+
+void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
{
if (m_format.renderableType() == QSurfaceFormat::DefaultRenderableType)
m_format.setRenderableType(QSurfaceFormat::OpenGL);
@@ -178,6 +191,7 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
m_shareContext = static_cast<const QGLXContext*>(share)->glxContext();
GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(screen),screen->screenNumber(),m_format);
+ m_config = config;
XVisualInfo *visualInfo = 0;
Window window = 0; // Temporary window used to query OpenGL context
@@ -195,7 +209,7 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
&& (m_format.renderableType() != QSurfaceFormat::OpenGLES || (supportsProfiles && glxExt.contains("GLX_EXT_create_context_es2_profile")))) {
// Try to create an OpenGL context for each known OpenGL version in descending
// order from the requested version.
- const int requestedVersion = format.majorVersion() * 10 + qMin(format.minorVersion(), 9);
+ const int requestedVersion = m_format.majorVersion() * 10 + qMin(m_format.minorVersion(), 9);
QVector<int> glVersions;
if (m_format.renderableType() == QSurfaceFormat::OpenGL) {
@@ -282,10 +296,10 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
// Get the basic surface format details
if (m_context)
- qglx_surfaceFormatFromGLXFBConfig(&m_format, DISPLAY_FROM_XCB(screen), config, m_context);
+ qglx_surfaceFormatFromGLXFBConfig(&m_format, DISPLAY_FROM_XCB(screen), config);
// Create a temporary window so that we can make the new context current
- window = createDummyWindow(screen, config);
+ window = createDummyWindow(DISPLAY_FROM_XCB(screen), config, screen->screenNumber(), screen->root());
} else {
// requesting an OpenGL ES context requires glXCreateContextAttribsARB, so bail out
if (m_format.renderableType() == QSurfaceFormat::OpenGLES)
@@ -303,7 +317,7 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
}
// Create a temporary window so that we can make the new context current
- window = createDummyWindow(screen, visualInfo);
+ window = createDummyWindow(DISPLAY_FROM_XCB(screen), visualInfo, screen->screenNumber(), screen->root());
XFree(visualInfo);
}
@@ -320,9 +334,125 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
XDestroyWindow(DISPLAY_FROM_XCB(screen), window);
}
+void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const QVariant &nativeHandle)
+{
+ if (!nativeHandle.canConvert<QGLXNativeContext>()) {
+ qWarning("QGLXContext: Requires a QGLXNativeContext");
+ return;
+ }
+ QGLXNativeContext handle = nativeHandle.value<QGLXNativeContext>();
+ GLXContext context = handle.context();
+ if (!context) {
+ qWarning("QGLXContext: No GLXContext given");
+ return;
+ }
+
+ // 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);
+
+ // Legacy contexts created using glXCreateContext are created using a visual
+ // and the FBConfig cannot be queried. The only way to adapt these contexts
+ // is to figure out the visual id.
+ XVisualInfo *vinfo = 0;
+ // If the VisualID is provided use it.
+ VisualID vid = handle.visualId();
+ if (!vid) {
+ // In the absence of the VisualID figure it out from the window.
+ Window wnd = handle.window();
+ if (wnd) {
+ XWindowAttributes attrs;
+ XGetWindowAttributes(dpy, wnd, &attrs);
+ vid = XVisualIDFromVisual(attrs.visual);
+ }
+ }
+ if (vid) {
+ XVisualInfo v;
+ v.screen = screen->screenNumber();
+ v.visualid = vid;
+ int n = 0;
+ vinfo = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask, &v, &n);
+ if (n < 1) {
+ XFree(vinfo);
+ vinfo = 0;
+ }
+ }
+
+ // For contexts created with an FBConfig using the modern functions providing the
+ // visual or window is not mandatory. Just query the config from the context.
+ GLXFBConfig config = 0;
+ if (!vinfo) {
+ int configId = 0;
+ if (glXQueryContext(dpy, context, GLX_FBCONFIG_ID, &configId) != Success) {
+ qWarning("QGLXContext: Failed to query config from the provided context");
+ return;
+ }
+
+ GLXFBConfig *configs;
+ int numConfigs = 0;
+ static const int attribs[] = { GLX_FBCONFIG_ID, configId, None };
+ configs = glXChooseFBConfig(dpy, screen->screenNumber(), attribs, &numConfigs);
+ if (!configs || numConfigs < 1) {
+ qWarning("QGLXContext: Failed to find config");
+ return;
+ }
+ if (configs && numConfigs > 1) // this is suspicious so warn but let it continue
+ qWarning("QGLXContext: Multiple configs for FBConfig ID %d", configId);
+
+ config = configs[0];
+ // Store the config.
+ m_config = config;
+ }
+
+ Q_ASSERT(vinfo || config);
+
+ int screenNumber = DefaultScreen(dpy);
+ Window window;
+ if (vinfo)
+ window = createDummyWindow(dpy, vinfo, screenNumber, RootWindow(dpy, screenNumber));
+ else
+ window = createDummyWindow(dpy, config, screenNumber, RootWindow(dpy, screenNumber));
+ if (!window) {
+ qWarning("QGLXContext: Failed to create dummy window");
+ return;
+ }
+
+ // Update OpenGL version and buffer sizes in our format.
+ if (!glXMakeCurrent(dpy, window, context)) {
+ qWarning("QGLXContext: Failed to make provided context current");
+ return;
+ }
+ m_format = QSurfaceFormat();
+ m_format.setRenderableType(QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL
+ ? QSurfaceFormat::OpenGL : QSurfaceFormat::OpenGLES);
+ updateFormatFromContext(m_format);
+ if (vinfo)
+ qglx_surfaceFormatFromVisualInfo(&m_format, dpy, vinfo);
+ else
+ qglx_surfaceFormatFromGLXFBConfig(&m_format, dpy, config);
+ glXMakeCurrent(dpy, 0, 0);
+ XDestroyWindow(dpy, window);
+
+ if (vinfo)
+ XFree(vinfo);
+
+ // Success. Store the context. From this point on isValid() is true.
+ m_context = context;
+
+ if (share)
+ m_shareContext = static_cast<const QGLXContext*>(share)->glxContext();
+}
+
QGLXContext::~QGLXContext()
{
- glXDestroyContext(DISPLAY_FROM_XCB(m_screen), m_context);
+ if (m_ownsContext)
+ glXDestroyContext(DISPLAY_FROM_XCB(m_screen), m_context);
+}
+
+QVariant QGLXContext::nativeHandle() const
+{
+ return QVariant::fromValue<QGLXNativeContext>(QGLXNativeContext(m_context));
}
bool QGLXContext::makeCurrent(QPlatformSurface *surface)
diff --git a/src/plugins/platforms/xcb/qglxintegration.h b/src/plugins/platforms/xcb/qglxintegration.h
index 00bba94ab3..abe3216ad7 100644
--- a/src/plugins/platforms/xcb/qglxintegration.h
+++ b/src/plugins/platforms/xcb/qglxintegration.h
@@ -58,7 +58,8 @@ QT_BEGIN_NAMESPACE
class QGLXContext : public QPlatformOpenGLContext
{
public:
- QGLXContext(QXcbScreen *xd, const QSurfaceFormat &format, QPlatformOpenGLContext *share);
+ QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share,
+ const QVariant &nativeHandle);
~QGLXContext();
bool makeCurrent(QPlatformSurface *surface);
@@ -71,17 +72,25 @@ public:
bool isValid() const;
GLXContext glxContext() const { return m_context; }
+ GLXFBConfig glxConfig() const { return m_config; }
+
+ QVariant nativeHandle() const;
static bool supportsThreading();
static void queryDummyContext();
private:
+ void init(QXcbScreen *screen, QPlatformOpenGLContext *share);
+ void init(QXcbScreen *screen, QPlatformOpenGLContext *share, const QVariant &nativeHandle);
+
QXcbScreen *m_screen;
+ GLXFBConfig m_config;
GLXContext m_context;
GLXContext m_shareContext;
QSurfaceFormat m_format;
bool m_isPBufferCurrent;
int m_swapInterval;
+ bool m_ownsContext;
static bool m_queriedDummyContext;
static bool m_supportsThreading;
};
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
index e7f8510706..3b30274f25 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
@@ -135,9 +135,10 @@ protected:
(void)formats(); // trigger update of format list
- QList<xcb_atom_t> atoms;
+ QVector<xcb_atom_t> atoms;
xcb_atom_t *targets = (xcb_atom_t *) format_atoms.data();
int size = format_atoms.size() / sizeof(xcb_atom_t);
+ atoms.reserve(size);
for (int i = 0; i < size; ++i)
atoms.append(targets[i]);
@@ -524,7 +525,7 @@ xcb_atom_t QXcbClipboard::sendTargetsSelection(QMimeData *d, xcb_window_t window
QVector<xcb_atom_t> types;
QStringList formats = QInternalMimeData::formatsHelper(d);
for (int i = 0; i < formats.size(); ++i) {
- QList<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), formats.at(i));
+ QVector<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), formats.at(i));
for (int j = 0; j < atoms.size(); ++j) {
if (!types.contains(atoms.at(j)))
types.append(atoms.at(j));
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 60a4efff4e..354ba54e70 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -452,6 +452,7 @@ public:
void setFocusWindow(QXcbWindow *);
QByteArray startupId() const { return m_startupId; }
+ void setStartupId(const QByteArray &nextId) { m_startupId = nextId; }
void clearStartupId() { m_startupId.clear(); }
void grabServer();
@@ -508,11 +509,11 @@ private:
#ifndef QT_NO_TABLETEVENT
struct TabletData {
TabletData() : deviceId(0), pointerType(QTabletEvent::UnknownPointer),
- tool(QTabletEvent::Stylus), down(false), serialId(0), inProximity(false) { }
+ tool(QTabletEvent::Stylus), buttons(0), serialId(0), inProximity(false) { }
int deviceId;
QTabletEvent::PointerType pointerType;
QTabletEvent::TabletDevice tool;
- bool down;
+ Qt::MouseButtons buttons;
qint64 serialId;
bool inProximity;
struct ValuatorClassInfo {
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index e21db89a20..512e574859 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -685,6 +685,19 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin
#endif // XCB_USE_XINPUT21
}
+static Qt::MouseButton xiToQtMouseButton(uint32_t b) {
+ switch (b) {
+ case 1: return Qt::LeftButton;
+ case 2: return Qt::MiddleButton;
+ case 3: return Qt::RightButton;
+ // 4-7 are for scrolling
+ default: break;
+ }
+ if (b >= 8 && b <= Qt::MaxMouseButton)
+ return static_cast<Qt::MouseButton>(Qt::BackButton << (b - 8));
+ return Qt::NoButton;
+}
+
static QTabletEvent::TabletDevice toolIdToTabletDevice(quint32 toolId) {
// keep in sync with wacom_intuos_inout() in Linux kernel driver wacom_wac.c
switch (toolId) {
@@ -725,24 +738,22 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData)
Display *xDisplay = static_cast<Display *>(m_xlib_display);
xXIGenericDeviceEvent *xiEvent = static_cast<xXIGenericDeviceEvent *>(event);
switch (xiEvent->evtype) {
- case XI_ButtonPress: // stylus down
- if (reinterpret_cast<xXIDeviceEvent *>(event)->detail == 1) { // ignore the physical buttons on the stylus
- tabletData->down = true;
- xi2ReportTabletEvent(*tabletData, xiEvent);
- } else
- handled = false;
+ case XI_ButtonPress: {
+ Qt::MouseButton b = xiToQtMouseButton(reinterpret_cast<xXIDeviceEvent *>(event)->detail);
+ tabletData->buttons |= b;
+ xi2ReportTabletEvent(*tabletData, xiEvent);
break;
- case XI_ButtonRelease: // stylus up
- if (reinterpret_cast<xXIDeviceEvent *>(event)->detail == 1) {
- tabletData->down = false;
- xi2ReportTabletEvent(*tabletData, xiEvent);
- } else
- handled = false;
+ }
+ case XI_ButtonRelease: {
+ Qt::MouseButton b = xiToQtMouseButton(reinterpret_cast<xXIDeviceEvent *>(event)->detail);
+ tabletData->buttons ^= b;
+ xi2ReportTabletEvent(*tabletData, xiEvent);
break;
+ }
case XI_Motion:
- // Report TabletMove only when the stylus is touching the tablet.
- // No possibility to report proximity motion (no suitable Qt event exists yet).
- if (tabletData->down)
+ // Report TabletMove only when the stylus is touching the tablet or any button is pressed.
+ // TODO: report proximity (hover) motion (no suitable Qt event exists yet).
+ if (tabletData->buttons != Qt::NoButton)
xi2ReportTabletEvent(*tabletData, xiEvent);
break;
case XI_PropertyEvent: {
@@ -862,15 +873,16 @@ void QXcbConnection::xi2ReportTabletEvent(TabletData &tabletData, void *event)
}
if (Q_UNLIKELY(debug_xinput))
- qDebug("XI2 event on tablet %d with tool %d type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f pressure %4.2lf tilt %d, %d rotation %6.2lf",
- ev->deviceid, tabletData.tool, ev->type, ev->sequenceNumber, ev->detail,
+ qDebug("XI2 event on tablet %d with tool %d type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotation %6.2lf",
+ ev->deviceid, tabletData.tool, ev->evtype, ev->sequenceNumber, ev->detail,
fixed1616ToReal(ev->event_x), fixed1616ToReal(ev->event_y),
fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y),
- pressure, xTilt, yTilt, rotation);
+ (int)tabletData.buttons, pressure, xTilt, yTilt, rotation);
- QWindowSystemInterface::handleTabletEvent(window, tabletData.down, local, global,
+ QWindowSystemInterface::handleTabletEvent(window, local, global,
tabletData.tool, tabletData.pointerType,
- pressure, xTilt, yTilt, tangentialPressure,
+ tabletData.buttons, pressure,
+ xTilt, yTilt, tangentialPressure,
rotation, 0, tabletData.serialId);
}
#endif // QT_NO_TABLETEVENT
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp
index 4f0f57c375..bd28548cba 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -183,7 +183,7 @@ void QXcbDrag::startDrag()
QStringList fmts = QXcbMime::formatsHelper(drag()->mimeData());
for (int i = 0; i < fmts.size(); ++i) {
- QList<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), fmts.at(i));
+ QVector<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), fmts.at(i));
for (int j = 0; j < atoms.size(); ++j) {
if (!drag_types.contains(atoms.at(j)))
drag_types.append(atoms.at(j));
@@ -1010,9 +1010,6 @@ void QXcbDrag::handleFinished(const xcb_client_message_event_t *event)
// current_target = 0;
// current_proxy_target = 0;
- if (t.drag)
- t.drag->deleteLater();
-
// current_target = target;
// current_proxy_target = proxy_target;
// current_embedding_widget = embedding_widget;
@@ -1211,7 +1208,7 @@ QVariant QXcbDropData::xdndObtainData(const QByteArray &format, QVariant::Type r
return result;
}
- QList<xcb_atom_t> atoms = drag->xdnd_types;
+ QVector<xcb_atom_t> atoms = drag->xdnd_types;
QByteArray encoding;
xcb_atom_t a = mimeAtomForFormat(c, QLatin1String(format), requestedType, atoms, &encoding);
if (a == XCB_NONE)
diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h
index d94c42696f..7b0d337e7c 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.h
+++ b/src/plugins/platforms/xcb/qxcbdrag.h
@@ -46,7 +46,6 @@
#include <private/qsimpledrag_p.h>
#include <qxcbobject.h>
#include <xcb/xcb.h>
-#include <qlist.h>
#include <qpoint.h>
#include <qrect.h>
#include <qsharedpointer.h>
@@ -127,7 +126,7 @@ private:
// the types in this drop. 100 is no good, but at least it's big.
enum { xdnd_max_type = 100 };
- QList<xcb_atom_t> xdnd_types;
+ QVector<xcb_atom_t> xdnd_types;
// timestamp from XdndPosition and XdndDroptime for retrieving the data
xcb_timestamp_t target_time;
@@ -160,7 +159,7 @@ private:
QPointer<QDrag> drag;
QTime time;
};
- QList<Transaction> transactions;
+ QVector<Transaction> transactions;
int transaction_expiry_timer;
void restartDropExpiryTimer();
diff --git a/src/plugins/platforms/xcb/qxcbimage.cpp b/src/plugins/platforms/xcb/qxcbimage.cpp
index 181d99e85b..bc800524ef 100644
--- a/src/plugins/platforms/xcb/qxcbimage.cpp
+++ b/src/plugins/platforms/xcb/qxcbimage.cpp
@@ -68,6 +68,14 @@ QImage::Format qt_xcb_imageFormatForVisual(QXcbConnection *connection, uint8_t d
&& visual->green_mask == 0xff00 && visual->blue_mask == 0xff)
return QImage::Format_ARGB32_Premultiplied;
+ if (depth == 30 && format->bits_per_pixel == 32 && visual->red_mask == 0x3ff
+ && visual->green_mask == 0x0ffc00 && visual->blue_mask == 0x3ff00000)
+ return QImage::Format_BGR30;
+
+ if (depth == 30 && format->bits_per_pixel == 32 && visual->blue_mask == 0x3ff
+ && visual->green_mask == 0x0ffc00 && visual->red_mask == 0x3ff00000)
+ return QImage::Format_RGB30;
+
if (depth == 24 && format->bits_per_pixel == 32 && visual->red_mask == 0xff0000
&& visual->green_mask == 0xff00 && visual->blue_mask == 0xff)
return QImage::Format_RGB32;
@@ -147,6 +155,13 @@ QPixmap qt_xcb_pixmapFromXPixmap(QXcbConnection *connection, xcb_pixmap_t pixmap
p[x] |= 0xff000000;
p += bytes_per_line / 4;
}
+ } else if (format == QImage::Format_BGR30 || format == QImage::Format_RGB30) {
+ QRgb *p = (QRgb *)image.bits();
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; ++x)
+ p[x] |= 0xc0000000;
+ p += bytes_per_line / 4;
+ }
}
result = QPixmap::fromImage(image.copy());
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index 1b1c20f02c..f537a38962 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -83,6 +83,7 @@
#include "qxcbeglsurface.h"
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
#include <QtPlatformSupport/private/qeglpbuffer_p.h>
+#include <QtPlatformHeaders/QEGLNativeContext>
#endif
#include <QtGui/QOpenGLContext>
@@ -187,8 +188,8 @@ class QEGLXcbPlatformContext : public QEGLPlatformContext
{
public:
QEGLXcbPlatformContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share,
- EGLDisplay display, QXcbConnection *c)
- : QEGLPlatformContext(glFormat, share, display)
+ EGLDisplay display, QXcbConnection *c, const QVariant &nativeHandle)
+ : QEGLPlatformContext(glFormat, share, display, 0, nativeHandle)
, m_connection(c)
{
Q_XCB_NOOP(m_connection);
@@ -224,6 +225,10 @@ public:
return static_cast<QEGLPbuffer *>(surface)->pbuffer();
}
+ QVariant nativeHandle() const {
+ return QVariant::fromValue<QEGLNativeContext>(QEGLNativeContext(eglContext(), eglDisplay()));
+ }
+
private:
QXcbConnection *m_connection;
};
@@ -234,10 +239,18 @@ QPlatformOpenGLContext *QXcbIntegration::createPlatformOpenGLContext(QOpenGLCont
{
QXcbScreen *screen = static_cast<QXcbScreen *>(context->screen()->handle());
#if defined(XCB_USE_GLX)
- return new QGLXContext(screen, context->format(), context->shareHandle());
+ QGLXContext *platformContext = new QGLXContext(screen, context->format(),
+ context->shareHandle(), context->nativeHandle());
+ context->setNativeHandle(platformContext->nativeHandle());
+ return platformContext;
#elif defined(XCB_USE_EGL)
- return new QEGLXcbPlatformContext(context->format(), context->shareHandle(),
- screen->connection()->egl_display(), screen->connection());
+ QEGLXcbPlatformContext *platformContext = new QEGLXcbPlatformContext(context->format(),
+ context->shareHandle(),
+ screen->connection()->egl_display(),
+ screen->connection(),
+ context->nativeHandle());
+ context->setNativeHandle(platformContext->nativeHandle());
+ return platformContext;
#else
Q_UNUSED(screen);
qWarning("QXcbIntegration: Cannot create platform OpenGL context, neither GLX nor EGL are enabled");
diff --git a/src/plugins/platforms/xcb/qxcbmime.cpp b/src/plugins/platforms/xcb/qxcbmime.cpp
index b205a63267..c0f6745e7f 100644
--- a/src/plugins/platforms/xcb/qxcbmime.cpp
+++ b/src/plugins/platforms/xcb/qxcbmime.cpp
@@ -136,9 +136,10 @@ bool QXcbMime::mimeDataForAtom(QXcbConnection *connection, xcb_atom_t a, QMimeDa
return ret;
}
-QList<xcb_atom_t> QXcbMime::mimeAtomsForFormat(QXcbConnection *connection, const QString &format)
+QVector<xcb_atom_t> QXcbMime::mimeAtomsForFormat(QXcbConnection *connection, const QString &format)
{
- QList<xcb_atom_t> atoms;
+ QVector<xcb_atom_t> atoms;
+ atoms.reserve(7);
atoms.append(connection->internAtom(format.toLatin1()));
// special cases for strings
@@ -240,7 +241,7 @@ QVariant QXcbMime::mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a,
}
xcb_atom_t QXcbMime::mimeAtomForFormat(QXcbConnection *connection, const QString &format, QVariant::Type requestedType,
- const QList<xcb_atom_t> &atoms, QByteArray *requestedEncoding)
+ const QVector<xcb_atom_t> &atoms, QByteArray *requestedEncoding)
{
requestedEncoding->clear();
diff --git a/src/plugins/platforms/xcb/qxcbmime.h b/src/plugins/platforms/xcb/qxcbmime.h
index 4a69a35ced..563716a75b 100644
--- a/src/plugins/platforms/xcb/qxcbmime.h
+++ b/src/plugins/platforms/xcb/qxcbmime.h
@@ -59,14 +59,14 @@ public:
QXcbMime();
~QXcbMime();
- static QList<xcb_atom_t> mimeAtomsForFormat(QXcbConnection *connection, const QString &format);
+ static QVector<xcb_atom_t> mimeAtomsForFormat(QXcbConnection *connection, const QString &format);
static QString mimeAtomToString(QXcbConnection *connection, xcb_atom_t a);
static bool mimeDataForAtom(QXcbConnection *connection, xcb_atom_t a, QMimeData *mimeData, QByteArray *data,
xcb_atom_t *atomFormat, int *dataFormat);
static QVariant mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a, const QByteArray &data, const QString &format,
QVariant::Type requestedType, const QByteArray &encoding);
static xcb_atom_t mimeAtomForFormat(QXcbConnection *connection, const QString &format, QVariant::Type requestedType,
- const QList<xcb_atom_t> &atoms, QByteArray *requestedEncoding);
+ const QVector<xcb_atom_t> &atoms, QByteArray *requestedEncoding);
};
#endif // !(defined(QT_NO_DRAGANDDROP) && defined(QT_NO_CLIPBOARD))
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index b45bd6a82e..5673d41811 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -60,6 +60,8 @@
#include "qglxintegration.h"
#endif
+#include <QtPlatformHeaders/qxcbwindowfunctions.h>
+
#ifdef XCB_USE_XLIB
# include <X11/Xlib.h>
#else
@@ -77,6 +79,8 @@ static int resourceType(const QByteArray &key)
QByteArrayLiteral("display"), QByteArrayLiteral("egldisplay"),
QByteArrayLiteral("connection"), QByteArrayLiteral("screen"),
QByteArrayLiteral("eglcontext"),
+ QByteArrayLiteral("eglconfig"),
+ QByteArrayLiteral("glxconfig"),
QByteArrayLiteral("glxcontext"), QByteArrayLiteral("apptime"),
QByteArrayLiteral("appusertime"), QByteArrayLiteral("hintstyle"),
QByteArrayLiteral("startupid"), QByteArrayLiteral("traywindow"),
@@ -91,7 +95,9 @@ static int resourceType(const QByteArray &key)
}
QXcbNativeInterface::QXcbNativeInterface() :
- m_genericEventFilterType(QByteArrayLiteral("xcb_generic_event_t"))
+ m_genericEventFilterType(QByteArrayLiteral("xcb_generic_event_t")),
+ m_sysTraySelectionAtom(XCB_ATOM_NONE),
+ m_systrayVisualId(XCB_NONE)
{
}
@@ -133,6 +139,82 @@ QRect QXcbNativeInterface::systemTrayWindowGlobalGeometry(const QWindow *window)
return QRect();
}
+xcb_window_t QXcbNativeInterface::locateSystemTray(xcb_connection_t *conn, const QXcbScreen *screen)
+{
+ 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);
+
+ 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);
+
+ if (!sel_owner_r)
+ return XCB_WINDOW_NONE;
+
+ xcb_window_t selection_window = sel_owner_r->owner;
+ free(sel_owner_r);
+
+ return selection_window;
+}
+
+bool QXcbNativeInterface::systrayVisualHasAlphaChannel() {
+ const QXcbScreen *screen = static_cast<QXcbScreen *>(QGuiApplication::primaryScreen()->handle());
+
+ if (m_systrayVisualId == XCB_NONE) {
+ xcb_connection_t *xcb_conn = screen->xcb_connection();
+ xcb_atom_t tray_atom = screen->atom(QXcbAtom::_NET_SYSTEM_TRAY_VISUAL);
+
+ xcb_window_t systray_window = locateSystemTray(xcb_conn, screen);
+ if (systray_window == XCB_WINDOW_NONE)
+ return false;
+
+ // 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(xcb_conn, false, systray_window,
+ tray_atom, XCB_ATOM_VISUALID, 0, 1);
+ systray_atom_reply = xcb_get_property_reply(xcb_conn, systray_atom_cookie, 0);
+
+ if (!systray_atom_reply)
+ return false;
+
+ 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);
+ m_systrayVisualId = vids[0];
+ }
+
+ free(systray_atom_reply);
+ }
+
+ if (m_systrayVisualId != XCB_NONE) {
+ quint8 depth = screen->depthOfVisual(m_systrayVisualId);
+ return depth == 32;
+ } else {
+ return false;
+ }
+}
+
+void QXcbNativeInterface::clearRegion(const QWindow *qwindow, const QRect& rect)
+{
+ if (const QPlatformWindow *platformWindow = qwindow->handle()) {
+ const QXcbWindow *qxwindow = static_cast<const QXcbWindow *>(platformWindow);
+ xcb_connection_t *xcb_conn = qxwindow->xcb_connection();
+
+ xcb_clear_area(xcb_conn, false, qxwindow->xcb_window(), rect.x(), rect.y(), rect.width(), rect.height());
+ }
+}
+
void *QXcbNativeInterface::nativeResourceForIntegration(const QByteArray &resourceString)
{
void *result = 0;
@@ -160,6 +242,12 @@ void *QXcbNativeInterface::nativeResourceForContext(const QByteArray &resourceSt
case EglContext:
result = eglContextForContext(context);
break;
+ case EglConfig:
+ result = eglConfigForContext(context);
+ break;
+ case GLXConfig:
+ result = glxConfigForContext(context);
+ break;
case GLXContext:
result = glxContextForContext(context);
break;
@@ -225,6 +313,14 @@ void *QXcbNativeInterface::nativeResourceForWindow(const QByteArray &resourceStr
return result;
}
+QPlatformNativeInterface::NativeResourceForIntegrationFunction QXcbNativeInterface::nativeResourceFunctionForIntegration(const QByteArray &resource)
+{
+ QByteArray lowerCaseResource = resource.toLower();
+ if (lowerCaseResource == "setstartupid")
+ return NativeResourceForIntegrationFunction(setStartupId);
+ return 0;
+}
+
QPlatformNativeInterface::NativeResourceForScreenFunction QXcbNativeInterface::nativeResourceFunctionForScreen(const QByteArray &resource)
{
const QByteArray lowerCaseResource = resource.toLower();
@@ -235,6 +331,14 @@ QPlatformNativeInterface::NativeResourceForScreenFunction QXcbNativeInterface::n
return 0;
}
+QFunctionPointer QXcbNativeInterface::platformFunction(const QByteArray &function) const
+{
+ if (function == QXcbWindowFunctions::setWmWindowTypeIdentifier()) {
+ return QFunctionPointer(QXcbWindow::setWmWindowTypeStatic);
+ }
+ return Q_NULLPTR;
+}
+
void *QXcbNativeInterface::appTime(const QXcbScreen *screen)
{
return reinterpret_cast<void *>(quintptr(screen->connection()->time()));
@@ -287,6 +391,15 @@ void QXcbNativeInterface::setAppUserTime(QScreen* screen, xcb_timestamp_t time)
static_cast<QXcbScreen *>(screen->handle())->connection()->setNetWmUserTime(time);
}
+void QXcbNativeInterface::setStartupId(const char *data)
+{
+ QByteArray startupId(data);
+ QXcbIntegration *integration = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration());
+ QXcbConnection *defaultConnection = integration->defaultConnection();
+ if (defaultConnection)
+ defaultConnection->setStartupId(startupId);
+}
+
QPlatformNativeInterface::NativeResourceForContextFunction QXcbNativeInterface::nativeResourceFunctionForContext(const QByteArray &resource)
{
QByteArray lowerCaseResource = resource.toLower();
@@ -353,6 +466,18 @@ void * QXcbNativeInterface::eglContextForContext(QOpenGLContext *context)
#endif
}
+void * QXcbNativeInterface::eglConfigForContext(QOpenGLContext *context)
+{
+ Q_ASSERT(context);
+#if defined(XCB_USE_EGL)
+ QEGLPlatformContext *eglPlatformContext = static_cast<QEGLPlatformContext *>(context->handle());
+ return eglPlatformContext->eglConfig();
+#else
+ Q_UNUSED(context);
+ return 0;
+#endif
+}
+
void *QXcbNativeInterface::glxContextForContext(QOpenGLContext *context)
{
Q_ASSERT(context);
@@ -366,4 +491,17 @@ void *QXcbNativeInterface::glxContextForContext(QOpenGLContext *context)
}
+void *QXcbNativeInterface::glxConfigForContext(QOpenGLContext *context)
+{
+ Q_ASSERT(context);
+#if defined(XCB_USE_GLX)
+ QGLXContext *glxPlatformContext = static_cast<QGLXContext *>(context->handle());
+ return glxPlatformContext->glxConfig();
+#else
+ Q_UNUSED(context);
+ return 0;
+#endif
+
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h
index fb1a46014c..c63cdf0254 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.h
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h
@@ -63,6 +63,8 @@ public:
Connection,
Screen,
EglContext,
+ EglConfig,
+ GLXConfig,
GLXContext,
AppTime,
AppUserTime,
@@ -77,13 +79,16 @@ public:
QXcbNativeInterface();
void *nativeResourceForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE;
- void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context);
- void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen);
- void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window);
+ void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context) Q_DECL_OVERRIDE;
+ void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen) Q_DECL_OVERRIDE;
+ void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) Q_DECL_OVERRIDE;
- NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource);
+ NativeResourceForIntegrationFunction nativeResourceFunctionForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE;
+ NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource) Q_DECL_OVERRIDE;
NativeResourceForScreenFunction nativeResourceFunctionForScreen(const QByteArray &resource) Q_DECL_OVERRIDE;
+ QFunctionPointer platformFunction(const QByteArray &function) const Q_DECL_OVERRIDE;
+
inline const QByteArray &genericEventFilterType() const { return m_genericEventFilterType; }
void *displayForWindow(QWindow *window);
@@ -96,13 +101,18 @@ public:
void *startupId();
void *x11Screen();
void *rootWindow();
+ static void setStartupId(const char *);
static void setAppTime(QScreen *screen, xcb_timestamp_t time);
static void setAppUserTime(QScreen *screen, xcb_timestamp_t time);
static void *eglContextForContext(QOpenGLContext *context);
+ static void *eglConfigForContext(QOpenGLContext *context);
static void *glxContextForContext(QOpenGLContext *context);
+ static void *glxConfigForContext(QOpenGLContext *context);
Q_INVOKABLE void beep();
Q_INVOKABLE bool systemTrayAvailable(const QScreen *screen) const;
+ Q_INVOKABLE void clearRegion(const QWindow *qwindow, const QRect& rect);
+ Q_INVOKABLE bool systrayVisualHasAlphaChannel();
Q_INVOKABLE bool requestSystemTrayWindowDock(const QWindow *window);
Q_INVOKABLE QRect systemTrayWindowGlobalGeometry(const QWindow *window);
@@ -110,8 +120,13 @@ signals:
void systemTrayWindowChanged(QScreen *screen);
private:
+ xcb_window_t locateSystemTray(xcb_connection_t *conn, const QXcbScreen *screen);
+
const QByteArray m_genericEventFilterType;
+ xcb_atom_t m_sysTraySelectionAtom;
+ xcb_visualid_t m_systrayVisualId;
+
static QXcbScreen *qPlatformScreenForWindow(QWindow *window);
};
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 01e78465b6..85f4dfbd43 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -200,6 +200,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr,
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);
}
@@ -296,6 +297,14 @@ const xcb_visualtype_t *QXcbScreen::visualForId(xcb_visualid_t visualid) const
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;
+}
+
QImage::Format QXcbScreen::format() const
{
return QImage::Format_RGB32;
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index c36492db64..53ac65bb09 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -93,6 +93,7 @@ public:
bool syncRequestSupported() const { return m_syncRequestSupported; }
const xcb_visualtype_t *visualForId(xcb_visualid_t) const;
+ quint8 depthOfVisual(xcb_visualid_t) const;
QString name() const { return m_outputName; }
@@ -127,6 +128,7 @@ private:
bool m_syncRequestSupported;
xcb_window_t m_clientLeader;
QMap<xcb_visualid_t, xcb_visualtype_t> m_visuals;
+ QMap<xcb_visualid_t, quint8> m_visualDepths;
QXcbCursor *m_cursor;
int m_refreshRate;
int m_forcedDpi;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 586068d8d9..de39b9335c 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -166,16 +166,36 @@ static inline bool isTransient(const QWindow *w)
|| w->type() == Qt::Popup;
}
-static inline QImage::Format imageFormatForDepth(int depth)
+static inline QImage::Format imageFormatForVisual(int depth, quint32 red_mask, quint32 blue_mask)
{
switch (depth) {
- case 32: return QImage::Format_ARGB32_Premultiplied;
- case 24: return QImage::Format_RGB32;
- case 16: return QImage::Format_RGB16;
- default:
- qWarning("Unsupported screen depth: %d", depth);
- return QImage::Format_Invalid;
+ case 32:
+ if (blue_mask == 0xff)
+ return QImage::Format_ARGB32_Premultiplied;
+ if (red_mask == 0x3ff)
+ return QImage::Format_A2BGR30_Premultiplied;
+ if (blue_mask == 0x3ff)
+ return QImage::Format_A2RGB30_Premultiplied;
+ break;
+ case 30:
+ if (red_mask == 0x3ff)
+ return QImage::Format_BGR30;
+ if (blue_mask == 0x3ff)
+ return QImage::Format_RGB30;
+ break;
+ case 24:
+ if (blue_mask == 0xff)
+ return QImage::Format_RGB32;
+ break;
+ case 16:
+ if (blue_mask == 0x1f)
+ return QImage::Format_RGB16;
+ break;
+ default:
+ break;
}
+ qWarning("Unsupported screen format: depth: %d, red_mask: %x, blue_mask: %x", depth, red_mask, blue_mask);
+ return QImage::Format_Invalid;
}
static inline bool positionIncludesFrame(QWindow *w)
@@ -183,6 +203,8 @@ static inline bool positionIncludesFrame(QWindow *w)
return qt_window_private(w)->positionPolicy == QWindowPrivate::WindowFrameInclusive;
}
+static const char *wm_window_type_property_id = "_q_xcb_wm_window_type";
+
QXcbWindow::QXcbWindow(QWindow *window)
: QPlatformWindow(window)
, m_window(0)
@@ -225,7 +247,9 @@ void QXcbWindow::create()
if (type == Qt::Desktop) {
m_window = m_screen->root();
m_depth = m_screen->screen()->root_depth;
- m_imageFormat = imageFormatForDepth(m_depth);
+ m_visualId = m_screen->screen()->root_visual;
+ const xcb_visualtype_t *visual = m_screen->visualForId(m_visualId);
+ m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask);
connection()->addWindowEventListener(m_window, this);
return;
}
@@ -315,7 +339,7 @@ void QXcbWindow::create()
}
if (visualInfo) {
m_depth = visualInfo->depth;
- m_imageFormat = imageFormatForDepth(m_depth);
+ m_imageFormat = imageFormatForVisual(visualInfo->depth, visualInfo->red_mask, visualInfo->blue_mask);
Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), xcb_parent_id, visualInfo->visual, AllocNone);
XSetWindowAttributes a;
@@ -365,7 +389,8 @@ void QXcbWindow::create()
}
}
- m_imageFormat = imageFormatForDepth(m_depth);
+ const xcb_visualtype_t *visual = m_screen->visualForId(m_visualId);
+ m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask);
Q_XCB_CALL(xcb_create_window(xcb_connection(),
m_depth,
@@ -698,6 +723,11 @@ void QXcbWindow::show()
updateNetWmStateBeforeMap();
}
+ if (window()->metaObject()->indexOfProperty(wm_window_type_property_id) >= 0) {
+ QXcbWindowFunctions::WmWindowTypes wmWindowTypes(window()->property(wm_window_type_property_id).value<int>());
+ setWmWindowType(wmWindowTypes);
+ }
+
if (connection()->time() != XCB_TIME_CURRENT_TIME)
updateNetWmUserTime(connection()->time());
@@ -1535,6 +1565,133 @@ QXcbEGLSurface *QXcbWindow::eglSurface() const
}
#endif
+void QXcbWindow::setWmWindowTypeStatic(QWindow *window, QXcbWindowFunctions::WmWindowTypes windowTypes)
+{
+ if (window->handle())
+ static_cast<QXcbWindow *>(window->handle())->setWmWindowType(windowTypes);
+ else
+ window->setProperty(wm_window_type_property_id, QVariant::fromValue(static_cast<int>(windowTypes)));
+}
+
+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);
+
+ 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_end = types + reply->length;
+ for (; types != types_end; types++) {
+ QXcbAtom::Atom type = connection()->qatom(*types);
+ switch (type) {
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_NORMAL:
+ result |= QXcbWindowFunctions::Normal;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_DESKTOP:
+ result |= QXcbWindowFunctions::Desktop;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_DOCK:
+ qDebug() << "IS DOCK";
+ result |= QXcbWindowFunctions::Dock;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLBAR:
+ result |= QXcbWindowFunctions::Toolbar;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_MENU:
+ result |= QXcbWindowFunctions::Menu;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_UTILITY:
+ result |= QXcbWindowFunctions::Utility;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_SPLASH:
+ result |= QXcbWindowFunctions::Splash;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_DIALOG:
+ result |= QXcbWindowFunctions::Dialog;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_DROPDOWN_MENU:
+ result |= QXcbWindowFunctions::DropDownMenu;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_POPUP_MENU:
+ result |= QXcbWindowFunctions::PopupMenu;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLTIP:
+ result |= QXcbWindowFunctions::Tooltip;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_NOTIFICATION:
+ result |= QXcbWindowFunctions::Notification;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_COMBO:
+ result |= QXcbWindowFunctions::Combo;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_DND:
+ result |= QXcbWindowFunctions::Dnd;
+ break;
+ case QXcbAtom::_KDE_NET_WM_WINDOW_TYPE_OVERRIDE:
+ result |= QXcbWindowFunctions::KdeOverride;
+ break;
+ default:
+ break;
+ }
+ }
+ free(reply);
+ }
+ return result;
+}
+
+void QXcbWindow::setWmWindowType(QXcbWindowFunctions::WmWindowTypes types)
+{
+ QVector<xcb_atom_t> atoms;
+
+ if (types & QXcbWindowFunctions::Normal)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_NORMAL));
+ if (types & QXcbWindowFunctions::Desktop)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DESKTOP));
+ if (types & QXcbWindowFunctions::Dock) {
+ qDebug() << "setting to be dock";
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DOCK));
+ }
+ if (types & QXcbWindowFunctions::Toolbar)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLBAR));
+ if (types & QXcbWindowFunctions::Menu)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_MENU));
+ if (types & QXcbWindowFunctions::Utility)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_UTILITY));
+ if (types & QXcbWindowFunctions::Splash)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_SPLASH));
+ if (types & QXcbWindowFunctions::Dialog)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DIALOG));
+ if (types & QXcbWindowFunctions::DropDownMenu)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DROPDOWN_MENU));
+ if (types & QXcbWindowFunctions::PopupMenu)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_POPUP_MENU));
+ if (types & QXcbWindowFunctions::Tooltip)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLTIP));
+ if (types & QXcbWindowFunctions::Notification)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_NOTIFICATION));
+ if (types & QXcbWindowFunctions::Combo)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_COMBO));
+ if (types & QXcbWindowFunctions::Dnd)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DND));
+ if (types & QXcbWindowFunctions::KdeOverride)
+ atoms.append(atom(QXcbAtom::_KDE_NET_WM_WINDOW_TYPE_OVERRIDE));
+
+ if (atoms.isEmpty()) {
+ Q_XCB_CALL(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_flush(xcb_connection());
+}
+
class ExposeCompressor
{
public:
@@ -1687,14 +1844,10 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
QPlatformWindow::setGeometry(rect);
QWindowSystemInterface::handleGeometryChange(window(), rect);
- if (!m_screen->availableGeometry().intersects(rect)) {
- Q_FOREACH (QPlatformScreen* screen, m_screen->virtualSiblings()) {
- if (screen->availableGeometry().intersects(rect)) {
- m_screen = static_cast<QXcbScreen*>(screen);
- QWindowSystemInterface::handleWindowScreenChanged(window(), m_screen->QPlatformScreen::screen());
- break;
- }
- }
+ QPlatformScreen *newScreen = screenForGeometry(rect);
+ if (newScreen != m_screen) {
+ m_screen = static_cast<QXcbScreen*>(newScreen);
+ QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
}
m_configureNotifyPending = false;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index b924ee27e5..72b5c7bcc9 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -51,6 +51,8 @@
#include "qxcbobject.h"
+#include <QtPlatformHeaders/qxcbwindowfunctions.h>
+
QT_BEGIN_NAMESPACE
class QXcbScreen;
@@ -150,6 +152,11 @@ public:
QXcbEGLSurface *eglSurface() const;
#endif
+ static void setWmWindowTypeStatic(QWindow *window, QXcbWindowFunctions::WmWindowTypes windowTypes);
+
+ QXcbWindowFunctions::WmWindowTypes wmWindowTypes() const;
+ void setWmWindowType(QXcbWindowFunctions::WmWindowTypes types);
+
bool needsSync() const;
public Q_SLOTS:
diff --git a/src/plugins/platforms/xcb/qxcbxsettings.cpp b/src/plugins/platforms/xcb/qxcbxsettings.cpp
index 141a6cc0cb..17b40a45e1 100644
--- a/src/plugins/platforms/xcb/qxcbxsettings.cpp
+++ b/src/plugins/platforms/xcb/qxcbxsettings.cpp
@@ -42,6 +42,7 @@
#include "qxcbxsettings.h"
#include <QtCore/QByteArray>
+#include <QtCore/QtEndian>
#include <X11/extensions/XIproto.h>
@@ -149,47 +150,67 @@ public:
{
if (xSettings.length() < 12)
return;
- // we ignore byteorder for now
- char byteOrder = xSettings.at(1);
- Q_UNUSED(byteOrder);
- uint number_of_settings = *reinterpret_cast<const uint *>(xSettings.mid(8,4).constData());
+ char byteOrder = xSettings.at(0);
+ if (byteOrder != LSBFirst && byteOrder != MSBFirst) {
+ qWarning("%s ByteOrder byte %d not 0 or 1", Q_FUNC_INFO , byteOrder);
+ return;
+ }
+
+#define ADJUST_BO(b, t, x) \
+ ((b == LSBFirst) ? \
+ qFromLittleEndian<t>((const uchar *)(x)) : \
+ qFromBigEndian<t>((const uchar *)(x)))
+#define VALIDATE_LENGTH(x) \
+ if ((size_t)xSettings.length() < (offset + local_offset + 12 + x)) { \
+ qWarning("%s Length %d runs past end of data", Q_FUNC_INFO , x); \
+ return; \
+ }
+ uint number_of_settings = ADJUST_BO(byteOrder, quint32, xSettings.mid(8,4).constData());
const char *data = xSettings.constData() + 12;
size_t offset = 0;
for (uint i = 0; i < number_of_settings; i++) {
int local_offset = 0;
+ VALIDATE_LENGTH(2);
XSettingsType type = static_cast<XSettingsType>(*reinterpret_cast<const quint8 *>(data + offset));
local_offset += 2;
- quint16 name_len = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ VALIDATE_LENGTH(2);
+ quint16 name_len = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
local_offset += 2;
+ VALIDATE_LENGTH(name_len);
QByteArray name(data + offset + local_offset, name_len);
local_offset += round_to_nearest_multiple_of_4(name_len);
- int last_change_serial = *reinterpret_cast<const int *>(data + offset + local_offset);
+ VALIDATE_LENGTH(4);
+ int last_change_serial = ADJUST_BO(byteOrder, qint32, data + offset + local_offset);
Q_UNUSED(last_change_serial);
local_offset += 4;
QVariant value;
if (type == XSettingsTypeString) {
- int value_length = *reinterpret_cast<const int *>(data + offset + local_offset);
+ VALIDATE_LENGTH(4);
+ int value_length = ADJUST_BO(byteOrder, qint32, data + offset + local_offset);
local_offset+=4;
+ VALIDATE_LENGTH(value_length);
QByteArray value_string(data + offset + local_offset, value_length);
value.setValue(value_string);
local_offset += round_to_nearest_multiple_of_4(value_length);
} else if (type == XSettingsTypeInteger) {
- int value_length = *reinterpret_cast<const int *>(data + offset + local_offset);
+ VALIDATE_LENGTH(4);
+ int value_length = ADJUST_BO(byteOrder, qint32, data + offset + local_offset);
local_offset += 4;
value.setValue(value_length);
} else if (type == XSettingsTypeColor) {
- quint16 red = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ VALIDATE_LENGTH(2*4);
+ quint16 red = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
local_offset += 2;
- quint16 green = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ quint16 green = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
local_offset += 2;
- quint16 blue = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ quint16 blue = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
local_offset += 2;
- quint16 alpha= *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ quint16 alpha= ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
local_offset += 2;
QColor color_value(red,green,blue,alpha);
value.setValue(color_value);
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 942db329ca..d1cbff59c1 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -3,6 +3,5 @@ TEMPLATE = subdirs
SUBDIRS *= sqldrivers
!winrt:qtHaveModule(network): SUBDIRS += bearer
qtHaveModule(gui): SUBDIRS *= imageformats platforms platforminputcontexts platformthemes generic
-qtHaveModule(widgets): SUBDIRS += accessible
!winrt:!wince*:qtHaveModule(widgets):SUBDIRS += printsupport
diff --git a/src/printsupport/doc/qtprintsupport.qdocconf b/src/printsupport/doc/qtprintsupport.qdocconf
index 4d1f0c39f1..2ec33f6600 100644
--- a/src/printsupport/doc/qtprintsupport.qdocconf
+++ b/src/printsupport/doc/qtprintsupport.qdocconf
@@ -2,7 +2,6 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = QtPrintSupport
description = Qt Print Support Reference Documentation
-url = http://qt-project.org/doc/qt-$QT_VER
version = $QT_VERSION
examplesinstallpath = printsupport
diff --git a/src/printsupport/kernel/qcups.cpp b/src/printsupport/kernel/qcups.cpp
index c6e3ddb54d..3a92f9b6db 100644
--- a/src/printsupport/kernel/qcups.cpp
+++ b/src/printsupport/kernel/qcups.cpp
@@ -67,61 +67,49 @@ void QCUPSSupport::setCupsOption(QStringList &cupsOptions, const QString &option
}
}
-void QCUPSSupport::setJobHold(QPrinter *printer, const JobHoldUntil jobHold, const QTime &holdUntilTime)
+static inline QString jobHoldToString(const QCUPSSupport::JobHoldUntil jobHold, const QTime holdUntilTime)
{
- QStringList cupsOptions = cupsOptionsList(printer);
-
switch (jobHold) {
- case NoHold: //default
- break;
- case Indefinite:
- setCupsOption(cupsOptions,
- QStringLiteral("job-hold-until"),
- QStringLiteral("indefinite"));
- break;
- case DayTime:
- setCupsOption(cupsOptions,
- QStringLiteral("job-hold-until"),
- QStringLiteral("day-time"));
- break;
- case Night:
- setCupsOption(cupsOptions,
- QStringLiteral("job-hold-until"),
- QStringLiteral("night"));
- break;
- case SecondShift:
- setCupsOption(cupsOptions,
- QStringLiteral("job-hold-until"),
- QStringLiteral("second-shift"));
- break;
- case ThirdShift:
- setCupsOption(cupsOptions,
- QStringLiteral("job-hold-until"),
- QStringLiteral("third-shift"));
- break;
- case Weekend:
- setCupsOption(cupsOptions,
- QStringLiteral("job-hold-until"),
- QStringLiteral("weekend"));
- break;
- case SpecificTime:
- if (holdUntilTime.isNull()) {
- setJobHold(printer, NoHold);
- return;
+ case QCUPSSupport::Indefinite:
+ return QStringLiteral("indefinite");
+ case QCUPSSupport::DayTime:
+ return QStringLiteral("day-time");
+ case QCUPSSupport::Night:
+ return QStringLiteral("night");
+ case QCUPSSupport::SecondShift:
+ return QStringLiteral("second-shift");
+ case QCUPSSupport::ThirdShift:
+ return QStringLiteral("third-shift");
+ case QCUPSSupport::Weekend:
+ return QStringLiteral("weekend");
+ case QCUPSSupport::SpecificTime:
+ if (!holdUntilTime.isNull()) {
+ // CUPS expects the time in UTC, user has entered in local time, so get the UTS equivalent
+ QDateTime localDateTime = QDateTime::currentDateTime();
+ // Check if time is for tomorrow in case of DST change overnight
+ if (holdUntilTime < localDateTime.time())
+ localDateTime = localDateTime.addDays(1);
+ localDateTime.setTime(holdUntilTime);
+ return localDateTime.toUTC().time().toString(QStringLiteral("HH:mm"));
}
- // CUPS expects the time in UTC, user has entered in local time, so get the UTS equivalent
- QDateTime localDateTime = QDateTime::currentDateTime();
- // Check if time is for tomorrow in case of DST change overnight
- if (holdUntilTime < localDateTime.time())
- localDateTime = localDateTime.addDays(1);
- localDateTime.setTime(holdUntilTime);
+ // else fall through:
+ case QCUPSSupport::NoHold:
+ return QString();
+ }
+ Q_UNREACHABLE();
+ return QString();
+}
+
+void QCUPSSupport::setJobHold(QPrinter *printer, const JobHoldUntil jobHold, const QTime &holdUntilTime)
+{
+ const QString jobHoldUntilArgument = jobHoldToString(jobHold, holdUntilTime);
+ if (!jobHoldUntilArgument.isEmpty()) {
+ QStringList cupsOptions = cupsOptionsList(printer);
setCupsOption(cupsOptions,
QStringLiteral("job-hold-until"),
- localDateTime.toUTC().time().toString(QStringLiteral("HH:mm")));
- break;
+ jobHoldUntilArgument);
+ setCupsOptions(printer, cupsOptions);
}
-
- setCupsOptions(printer, cupsOptions);
}
void QCUPSSupport::setJobBilling(QPrinter *printer, const QString &jobBilling)
@@ -138,58 +126,26 @@ void QCUPSSupport::setJobPriority(QPrinter *printer, int priority)
setCupsOptions(printer, cupsOptions);
}
-void QCUPSSupport::setBannerPages(QPrinter *printer, const BannerPage startBannerPage, const BannerPage endBannerPage)
+static inline QString bannerPageToString(const QCUPSSupport::BannerPage bannerPage)
{
- QStringList cupsOptions = cupsOptionsList(printer);
- QString startBanner, endBanner;
-
- switch (startBannerPage) {
- case NoBanner:
- startBanner = QStringLiteral("none");
- break;
- case Standard:
- startBanner = QStringLiteral("standard");
- break;
- case Unclassified:
- startBanner = QStringLiteral("unclassified");
- break;
- case Confidential:
- startBanner = QStringLiteral("confidential");
- break;
- case Classified:
- startBanner = QStringLiteral("classified");
- break;
- case Secret:
- startBanner = QStringLiteral("secret");
- break;
- case TopSecret:
- startBanner = QStringLiteral("topsecret");
- break;
+ switch (bannerPage) {
+ case QCUPSSupport::NoBanner: return QStringLiteral("none");
+ case QCUPSSupport::Standard: return QStringLiteral("standard");
+ case QCUPSSupport::Unclassified: return QStringLiteral("unclassified");
+ case QCUPSSupport::Confidential: return QStringLiteral("confidential");
+ case QCUPSSupport::Classified: return QStringLiteral("classified");
+ case QCUPSSupport::Secret: return QStringLiteral("secret");
+ case QCUPSSupport::TopSecret: return QStringLiteral("topsecret");
}
+ Q_UNREACHABLE();
+ return QString();
+};
- switch (endBannerPage) {
- case NoBanner:
- endBanner = QStringLiteral("none");
- break;
- case Standard:
- endBanner = QStringLiteral("standard");
- break;
- case Unclassified:
- endBanner = QStringLiteral("unclassified");
- break;
- case Confidential:
- endBanner = QStringLiteral("confidential");
- break;
- case Classified:
- endBanner = QStringLiteral("classified");
- break;
- case Secret:
- endBanner = QStringLiteral("secret");
- break;
- case TopSecret:
- endBanner = QStringLiteral("topsecret");
- break;
- }
+void QCUPSSupport::setBannerPages(QPrinter *printer, const BannerPage startBannerPage, const BannerPage endBannerPage)
+{
+ QStringList cupsOptions = cupsOptionsList(printer);
+ const QString startBanner = bannerPageToString(startBannerPage);
+ const QString endBanner = bannerPageToString(endBannerPage);
setCupsOption(cupsOptions, QStringLiteral("job-sheets"), startBanner + QLatin1Char(',') + endBanner);
setCupsOptions(printer, cupsOptions);
diff --git a/src/printsupport/kernel/qpaintengine_alpha.cpp b/src/printsupport/kernel/qpaintengine_alpha.cpp
index 6d292a6a71..cdf5570979 100644
--- a/src/printsupport/kernel/qpaintengine_alpha.cpp
+++ b/src/printsupport/kernel/qpaintengine_alpha.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -166,11 +166,14 @@ void QAlphaPaintEngine::drawPath(const QPainterPath &path)
if (d->m_pass == 0) {
d->m_continueCall = false;
- if (d->m_hasalpha || d->m_advancedPen || d->m_advancedBrush
+ if (d->canSeeTroughBackground(d->m_hasalpha, tr) || d->m_advancedPen || d->m_advancedBrush
|| d->m_emulateProjectiveTransforms)
{
d->addAlphaRect(tr);
}
+
+ d->addDirtyRect(tr);
+
if (d->m_picengine)
d->m_picengine->drawPath(path);
} else {
@@ -192,12 +195,14 @@ void QAlphaPaintEngine::drawPolygon(const QPointF *points, int pointCount, Polyg
if (d->m_pass == 0) {
d->m_continueCall = false;
- if (d->m_hasalpha || d->m_advancedPen || d->m_advancedBrush
+ if (d->canSeeTroughBackground(d->m_hasalpha, tr) || d->m_advancedPen || d->m_advancedBrush
|| d->m_emulateProjectiveTransforms)
{
d->addAlphaRect(tr);
}
+ d->addDirtyRect(tr);
+
if (d->m_picengine)
d->m_picengine->drawPolygon(points, pointCount, mode);
} else {
@@ -212,10 +217,12 @@ void QAlphaPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRe
QRectF tr = d->m_transform.mapRect(r);
if (d->m_pass == 0) {
d->m_continueCall = false;
- if (pm.hasAlpha() || d->m_alphaOpacity || d->m_complexTransform || pm.isQBitmap()) {
+ if (d->canSeeTroughBackground(pm.hasAlpha() || d->m_alphaOpacity, tr) || d->m_complexTransform || pm.isQBitmap()) {
d->addAlphaRect(tr);
}
+ d->addDirtyRect(tr);
+
if (d->m_picengine)
d->m_picengine->drawPixmap(r, pm, sr);
@@ -233,9 +240,12 @@ void QAlphaPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem
if (d->m_pass == 0) {
d->m_continueCall = false;
- if (d->m_alphaPen || d->m_alphaOpacity || d->m_advancedPen) {
+ if (d->canSeeTroughBackground(d->m_alphaPen || d->m_alphaOpacity, tr) || d->m_advancedPen) {
d->addAlphaRect(tr);
}
+
+ d->addDirtyRect(tr);
+
if (d->m_picengine) {
d->m_picengine->drawTextItem(p, textItem);
}
@@ -252,9 +262,12 @@ void QAlphaPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap,
if (d->m_pass == 0) {
d->m_continueCall = false;
- if (pixmap.hasAlpha() || d->m_alphaOpacity || d->m_complexTransform || pixmap.isQBitmap()) {
+ if (d->canSeeTroughBackground(pixmap.hasAlpha() || d->m_alphaOpacity, brect) || d->m_complexTransform || pixmap.isQBitmap()) {
d->addAlphaRect(brect);
}
+
+ d->addDirtyRect(brect);
+
if (d->m_picengine)
d->m_picengine->drawTiledPixmap(r, pixmap, s);
} else {
@@ -413,19 +426,14 @@ QRectF QAlphaPaintEnginePrivate::addPenWidth(const QPainterPath &path)
return (tmp.controlPointRect() * m_transform).boundingRect();
}
-QRect QAlphaPaintEnginePrivate::toRect(const QRectF &rect) const
+void QAlphaPaintEnginePrivate::addAlphaRect(const QRectF &rect)
{
- QRect r;
- r.setLeft(int(rect.left()));
- r.setTop(int(rect.top()));
- r.setRight(int(rect.right() + 1));
- r.setBottom(int(rect.bottom() + 1));
- return r;
+ m_alphargn |= rect.toAlignedRect();
}
-void QAlphaPaintEnginePrivate::addAlphaRect(const QRectF &rect)
+bool QAlphaPaintEnginePrivate::canSeeTroughBackground(bool somethingInRectHasAlpha, const QRectF &rect) const
{
- m_alphargn |= toRect(rect);
+ return somethingInRectHasAlpha && m_dirtyrgn.intersects(rect.toAlignedRect());
}
void QAlphaPaintEnginePrivate::drawAlphaImage(const QRectF &rect)
@@ -477,7 +485,7 @@ void QAlphaPaintEnginePrivate::drawAlphaImage(const QRectF &rect)
bool QAlphaPaintEnginePrivate::fullyContained(const QRectF &rect) const
{
- QRegion r(toRect(rect));
+ QRegion r(rect.toAlignedRect());
return (m_cliprgn.intersected(r) == r);
}
diff --git a/src/printsupport/kernel/qpaintengine_alpha_p.h b/src/printsupport/kernel/qpaintengine_alpha_p.h
index 8a0781d0d3..d3b10b3d3c 100644
--- a/src/printsupport/kernel/qpaintengine_alpha_p.h
+++ b/src/printsupport/kernel/qpaintengine_alpha_p.h
@@ -107,6 +107,7 @@ public:
QRegion m_alphargn;
QRegion m_cliprgn;
+ QRegion m_dirtyrgn;
bool m_hasalpha;
bool m_alphaPen;
@@ -122,6 +123,9 @@ public:
QPen m_pen;
void addAlphaRect(const QRectF &rect);
+ void addDirtyRect(const QRectF &rect) { m_dirtyrgn |= rect.toAlignedRect(); }
+ bool canSeeTroughBackground(bool somethingInRectHasAlpha, const QRectF &rect) const;
+
QRectF addPenWidth(const QPainterPath &path);
void drawAlphaImage(const QRectF &rect);
QRect toRect(const QRectF &rect) const;
diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp
index b97dc6d2c2..bf39b9309d 100644
--- a/src/printsupport/kernel/qprintengine_win.cpp
+++ b/src/printsupport/kernel/qprintengine_win.cpp
@@ -573,7 +573,13 @@ void QWin32PrintEngine::drawPixmap(const QRectF &targetRect,
width = (tw - (x * txinc));
}
- QPixmap p = pixmap.copy(tileSize * x, tileSize * y, imgw, imgh);
+
+ QImage img(QSize(imgw, imgh), QImage::Format_RGB32);
+ img.fill(Qt::white);
+ QPainter painter(&img);
+ painter.drawPixmap(0,0, pixmap, tileSize * x, tileSize * y, imgw, imgh);
+ QPixmap p = QPixmap::fromImage(img);
+
HBITMAP hbitmap = qt_pixmapToWinHBITMAP(p, HBitmapNoAlpha);
HDC display_dc = GetDC(0);
HDC hbitmap_hdc = CreateCompatibleDC(display_dc);
diff --git a/src/sql/doc/qtsql.qdocconf b/src/sql/doc/qtsql.qdocconf
index 7f37904039..b8632c5260 100644
--- a/src/sql/doc/qtsql.qdocconf
+++ b/src/sql/doc/qtsql.qdocconf
@@ -2,7 +2,6 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = QtSql
description = Qt SQL Reference Documentation
-url = http://qt-project.org/doc/qt-$QT_VER
version = $QT_VERSION
examplesinstallpath = sql
diff --git a/src/sql/kernel/qsqlquery.cpp b/src/sql/kernel/qsqlquery.cpp
index 6b13eb02ed..2b1bd5feb1 100644
--- a/src/sql/kernel/qsqlquery.cpp
+++ b/src/sql/kernel/qsqlquery.cpp
@@ -43,6 +43,8 @@
//#define QT_DEBUG_SQL
+#include "qdebug.h"
+#include "qelapsedtimer.h"
#include "qatomic.h"
#include "qsqlrecord.h"
#include "qsqlresult.h"
@@ -370,6 +372,10 @@ bool QSqlQuery::isNull(const QString &name) const
bool QSqlQuery::exec(const QString& query)
{
+#ifdef QT_DEBUG_SQL
+ QElapsedTimer t;
+ t.start();
+#endif
if (d->ref.load() != 1) {
bool fo = isForwardOnly();
*this = QSqlQuery(driver()->createResult());
@@ -391,10 +397,14 @@ bool QSqlQuery::exec(const QString& query)
qWarning("QSqlQuery::exec: empty query");
return false;
}
+
+ bool retval = d->sqlResult->reset(query);
#ifdef QT_DEBUG_SQL
- qDebug("\n QSqlQuery: %s", query.toLocal8Bit().constData());
+ qDebug().nospace() << "Executed query (" << t.elapsed() << "ms, " << d->sqlResult->size()
+ << " results, " << d->sqlResult->numRowsAffected()
+ << " affected): " << d->sqlResult->lastQuery();
#endif
- return d->sqlResult->reset(query);
+ return retval;
}
/*!
@@ -989,12 +999,22 @@ bool QSqlQuery::prepare(const QString& query)
*/
bool QSqlQuery::exec()
{
+#ifdef QT_DEBUG_SQL
+ QElapsedTimer t;
+ t.start();
+#endif
d->sqlResult->resetBindCount();
if (d->sqlResult->lastError().isValid())
d->sqlResult->setLastError(QSqlError());
- return d->sqlResult->exec();
+ bool retval = d->sqlResult->exec();
+#ifdef QT_DEBUG_SQL
+ qDebug().nospace() << "Executed prepared query (" << t.elapsed() << "ms, "
+ << d->sqlResult->size() << " results, " << d->sqlResult->numRowsAffected()
+ << " affected): " << d->sqlResult->lastQuery();
+#endif
+ return retval;
}
/*! \enum QSqlQuery::BatchExecutionMode
diff --git a/src/src.pro b/src/src.pro
index 6a805a6a06..13f62137ec 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -91,9 +91,13 @@ src_gui.subdir = $$PWD/gui
src_gui.target = sub-gui
src_gui.depends = src_corelib
+src_platformheaders.subdir = $$PWD/platformheaders
+src_platformheaders.target = sub-platformheaders
+src_platformheaders.depends = src_corelib src_gui
+
src_platformsupport.subdir = $$PWD/platformsupport
src_platformsupport.target = sub-platformsupport
-src_platformsupport.depends = src_corelib src_gui src_network
+src_platformsupport.depends = src_corelib src_gui src_network src_platformheaders
src_widgets.subdir = $$PWD/widgets
src_widgets.target = sub-widgets
@@ -141,14 +145,14 @@ contains(QT_CONFIG, concurrent):SUBDIRS += src_concurrent
SUBDIRS += src_angle
src_gui.depends += src_angle
}
- SUBDIRS += src_gui src_platformsupport
+ SUBDIRS += src_gui src_platformsupport src_platformheaders
contains(QT_CONFIG, opengl(es2)?):SUBDIRS += src_openglextensions
- src_plugins.depends += src_gui src_platformsupport
+ src_plugins.depends += src_gui src_platformsupport src_platformheaders
!contains(QT_CONFIG, no-widgets) {
SUBDIRS += src_tools_uic src_widgets
TOOLS += src_tools_uic
src_plugins.depends += src_widgets
- contains(QT_CONFIG, opengl(es2)?):!contains(QT_CONFIG, dynamicgl) {
+ contains(QT_CONFIG, opengl(es2)?) {
SUBDIRS += src_opengl
src_plugins.depends += src_opengl
}
diff --git a/src/testlib/doc/qttestlib.qdocconf b/src/testlib/doc/qttestlib.qdocconf
index 92e5c97aab..35b4fbcb7b 100644
--- a/src/testlib/doc/qttestlib.qdocconf
+++ b/src/testlib/doc/qttestlib.qdocconf
@@ -2,7 +2,6 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = QtTestLib
description = Qt Test Reference Documentation
-url = http://qt-project.org/doc/qt-$QT_VER
version = $QT_VERSION
examplesinstallpath = testlib
diff --git a/src/testlib/doc/snippets/code/doc_src_qsignalspy.cpp b/src/testlib/doc/snippets/code/doc_src_qsignalspy.cpp
index e4702c6e0b..0856de9450 100644
--- a/src/testlib/doc/snippets/code/doc_src_qsignalspy.cpp
+++ b/src/testlib/doc/snippets/code/doc_src_qsignalspy.cpp
@@ -83,3 +83,8 @@ QSignalSpy spy(myPushButton, SIGNAL(clicked(bool)));
//! [5]
QVERIFY(spy.wait(1000));
//! [5]
+
+//! [6]
+QSignalSpy spy(myPushButton, &QPushButton::clicked);
+//! [6]
+
diff --git a/src/testlib/qplaintestlogger.cpp b/src/testlib/qplaintestlogger.cpp
index 39580f22d4..774f2cc4fb 100644
--- a/src/testlib/qplaintestlogger.cpp
+++ b/src/testlib/qplaintestlogger.cpp
@@ -51,21 +51,29 @@
#include <stdlib.h>
#include <string.h>
-#ifdef Q_OS_WIN
-#include <windows.h>
-#endif
-
#ifdef Q_OS_WINCE
#include <QtCore/QString>
#endif
+#ifdef min // windows.h without NOMINMAX is included by the benchmark headers.
+# undef min
+#endif
+#ifdef max
+# undef max
+#endif
+
#include <QtCore/QByteArray>
#include <QtCore/qmath.h>
+#include <QtCore/QLibraryInfo>
#ifdef Q_OS_ANDROID
# include <android/log.h>
#endif
+#ifdef Q_OS_WIN
+# include <qt_windows.h>
+#endif
+
QT_BEGIN_NAMESPACE
namespace QTest {
@@ -334,7 +342,7 @@ void QPlainTestLogger::startLogging()
qsnprintf(buf, sizeof(buf),
"********* Start testing of %s *********\n"
"Config: Using QtTest library " QTEST_VERSION_STR
- ", Qt %s\n", QTestResult::currentTestObjectName(), qVersion());
+ ", %s\n", QTestResult::currentTestObjectName(), QLibraryInfo::build());
}
outputMessage(buf);
}
diff --git a/src/testlib/qsignalspy.h b/src/testlib/qsignalspy.h
index 72a5df1ed9..3ce1c6f99b 100644
--- a/src/testlib/qsignalspy.h
+++ b/src/testlib/qsignalspy.h
@@ -98,6 +98,48 @@ public:
initArgs(mo->method(sigIndex), obj);
}
+#ifdef Q_QDOC
+ QSignalSpy(const QObject *object, PointerToMemberFunction signal);
+#else
+ template <typename Func>
+ QSignalSpy(const typename QtPrivate::FunctionPointer<Func>::Object *obj, Func signal0)
+ : m_waiting(false)
+ {
+#ifdef Q_CC_BOR
+ const int memberOffset = QObject::staticMetaObject.methodCount();
+#else
+ static const int memberOffset = QObject::staticMetaObject.methodCount();
+#endif
+ if (!obj) {
+ qWarning("QSignalSpy: Cannot spy on a null object");
+ return;
+ }
+
+ if (!signal0) {
+ qWarning("QSignalSpy: Null signal name is not valid");
+ return;
+ }
+
+ const QMetaObject * const mo = obj->metaObject();
+ const QMetaMethod signalMetaMethod = QMetaMethod::fromSignal(signal0);
+ const int sigIndex = signalMetaMethod.methodIndex();
+ if (!signalMetaMethod.isValid() ||
+ signalMetaMethod.methodType() != QMetaMethod::Signal) {
+ qWarning("QSignalSpy: Not a valid signal: '%s'",
+ signalMetaMethod.methodSignature().constData());
+ return;
+ }
+
+ if (!QMetaObject::connect(obj, sigIndex, this, memberOffset,
+ Qt::DirectConnection, 0)) {
+ qWarning("QSignalSpy: QMetaObject::connect returned false. Unable to connect.");
+ return;
+ }
+ sig = signalMetaMethod.methodSignature();
+ initArgs(mo->method(sigIndex), obj);
+ }
+#endif // Q_QDOC
+
inline bool isValid() const { return !sig.isEmpty(); }
inline QByteArray signal() const { return sig; }
@@ -127,17 +169,11 @@ public:
}
private:
- void initArgs(const QMetaMethod &member)
- {
- initArgs(member, 0);
- }
-
void initArgs(const QMetaMethod &member, const QObject *obj)
{
- const QList<QByteArray> params = member.parameterTypes();
- args.reserve(params.size());
- for (int i = 0; i < params.count(); ++i) {
- int tp = QMetaType::type(params.at(i).constData());
+ args.reserve(member.parameterCount());
+ for (int i = 0; i < member.parameterCount(); ++i) {
+ int tp = member.parameterType(i);
if (tp == QMetaType::UnknownType && obj) {
void *argv[] = { &tp, &i };
QMetaObject::metacall(const_cast<QObject*>(obj),
@@ -147,9 +183,8 @@ private:
tp = QMetaType::UnknownType;
}
if (tp == QMetaType::UnknownType) {
- Q_ASSERT(tp != QMetaType::Void); // void parameter => metaobject is corrupt
qWarning("Don't know how to handle '%s', use qRegisterMetaType to register it.",
- params.at(i).constData());
+ member.parameterNames().at(i).constData());
}
args << tp;
}
diff --git a/src/testlib/qsignalspy.qdoc b/src/testlib/qsignalspy.qdoc
index 9559090e8f..31cdeaba6a 100644
--- a/src/testlib/qsignalspy.qdoc
+++ b/src/testlib/qsignalspy.qdoc
@@ -72,6 +72,20 @@
\snippet code/doc_src_qsignalspy.cpp 4
*/
+/*! \fn QSignalSpy::QSignalSpy(const QObject *object, PointerToMemberFunction signal)
+ \since 5.4
+
+ Constructs a new QSignalSpy that listens for emissions of the \a signal
+ from the QObject \a object. If QSignalSpy is not able to listen for a
+ valid signal (for example, because \a object is null or \a signal does
+ not denote a valid signal of \a object), an explanatory warning message
+ will be output using qWarning() and subsequent calls to \c isValid() will
+ return false.
+
+ Example:
+ \snippet code/doc_src_qsignalspy.cpp 6
+*/
+
/*! \fn QSignalSpy::isValid() const
Returns \c true if the signal spy listens to a valid signal, otherwise false.
diff --git a/src/testlib/qtestaccessible.h b/src/testlib/qtestaccessible.h
index ef6f61bd82..65fbd4c818 100644
--- a/src/testlib/qtestaccessible.h
+++ b/src/testlib/qtestaccessible.h
@@ -194,42 +194,75 @@ private:
{
QAccessibleEvent *ev;
if (event->type() == QAccessible::StateChanged) {
- ev = new QAccessibleStateChangeEvent(event->object(),
+ if (event->object())
+ ev = new QAccessibleStateChangeEvent(event->object(),
+ static_cast<QAccessibleStateChangeEvent*>(event)->changedStates());
+ else
+ ev = new QAccessibleStateChangeEvent(event->accessibleInterface(),
static_cast<QAccessibleStateChangeEvent*>(event)->changedStates());
} else if (event->type() == QAccessible::TextCaretMoved) {
- ev = new QAccessibleTextCursorEvent(event->object(), static_cast<QAccessibleTextCursorEvent*>(event)->cursorPosition());
+ if (event->object())
+ ev = new QAccessibleTextCursorEvent(event->object(), static_cast<QAccessibleTextCursorEvent*>(event)->cursorPosition());
+ else
+ ev = new QAccessibleTextCursorEvent(event->accessibleInterface(), static_cast<QAccessibleTextCursorEvent*>(event)->cursorPosition());
} else if (event->type() == QAccessible::TextSelectionChanged) {
const QAccessibleTextSelectionEvent *original = static_cast<QAccessibleTextSelectionEvent*>(event);
- QAccessibleTextSelectionEvent *sel = new QAccessibleTextSelectionEvent(event->object(), original->selectionStart(), original->selectionEnd());
+ QAccessibleTextSelectionEvent *sel;
+ if (event->object())
+ sel = new QAccessibleTextSelectionEvent(event->object(), original->selectionStart(), original->selectionEnd());
+ else
+ sel = new QAccessibleTextSelectionEvent(event->accessibleInterface(), original->selectionStart(), original->selectionEnd());
sel->setCursorPosition(original->cursorPosition());
ev = sel;
} else if (event->type() == QAccessible::TextInserted) {
const QAccessibleTextInsertEvent *original = static_cast<QAccessibleTextInsertEvent*>(event);
- QAccessibleTextInsertEvent *ins = new QAccessibleTextInsertEvent(event->object(), original->changePosition(), original->textInserted());
+ QAccessibleTextInsertEvent *ins;
+ if (original->object())
+ ins = new QAccessibleTextInsertEvent(event->object(), original->changePosition(), original->textInserted());
+ else
+ ins = new QAccessibleTextInsertEvent(event->accessibleInterface(), original->changePosition(), original->textInserted());
ins->setCursorPosition(original->cursorPosition());
ev = ins;
} else if (event->type() == QAccessible::TextRemoved) {
const QAccessibleTextRemoveEvent *original = static_cast<QAccessibleTextRemoveEvent*>(event);
- QAccessibleTextRemoveEvent *rem = new QAccessibleTextRemoveEvent(event->object(), original->changePosition(), original->textRemoved());
+ QAccessibleTextRemoveEvent *rem;
+ if (event->object())
+ rem = new QAccessibleTextRemoveEvent(event->object(), original->changePosition(), original->textRemoved());
+ else
+ rem = new QAccessibleTextRemoveEvent(event->accessibleInterface(), original->changePosition(), original->textRemoved());
rem->setCursorPosition(original->cursorPosition());
ev = rem;
} else if (event->type() == QAccessible::TextUpdated) {
const QAccessibleTextUpdateEvent *original = static_cast<QAccessibleTextUpdateEvent*>(event);
- QAccessibleTextUpdateEvent *upd = new QAccessibleTextUpdateEvent(event->object(), original->changePosition(), original->textRemoved(), original->textInserted());
+ QAccessibleTextUpdateEvent *upd;
+ if (event->object())
+ upd = new QAccessibleTextUpdateEvent(event->object(), original->changePosition(), original->textRemoved(), original->textInserted());
+ else
+ upd = new QAccessibleTextUpdateEvent(event->accessibleInterface(), original->changePosition(), original->textRemoved(), original->textInserted());
upd->setCursorPosition(original->cursorPosition());
ev = upd;
} else if (event->type() == QAccessible::ValueChanged) {
- ev = new QAccessibleValueChangeEvent(event->object(), static_cast<QAccessibleValueChangeEvent*>(event)->value());
+ if (event->object())
+ ev = new QAccessibleValueChangeEvent(event->object(), static_cast<QAccessibleValueChangeEvent*>(event)->value());
+ else
+ ev = new QAccessibleValueChangeEvent(event->accessibleInterface(), static_cast<QAccessibleValueChangeEvent*>(event)->value());
} else if (event->type() == QAccessible::TableModelChanged) {
QAccessibleTableModelChangeEvent *oldEvent = static_cast<QAccessibleTableModelChangeEvent*>(event);
- QAccessibleTableModelChangeEvent *newEvent = new QAccessibleTableModelChangeEvent(event->object(), oldEvent->modelChangeType());
+ QAccessibleTableModelChangeEvent *newEvent;
+ if (event->object())
+ newEvent = new QAccessibleTableModelChangeEvent(event->object(), oldEvent->modelChangeType());
+ else
+ newEvent = new QAccessibleTableModelChangeEvent(event->accessibleInterface(), oldEvent->modelChangeType());
newEvent->setFirstRow(oldEvent->firstRow());
newEvent->setFirstColumn(oldEvent->firstColumn());
newEvent->setLastRow(oldEvent->lastRow());
newEvent->setLastColumn(oldEvent->lastColumn());
ev = newEvent;
} else {
- ev = new QAccessibleEvent(event->object(), event->type());
+ if (event->object())
+ ev = new QAccessibleEvent(event->object(), event->type());
+ else
+ ev = new QAccessibleEvent(event->accessibleInterface(), event->type());
}
ev->setChild(event->child());
return ev;
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 5d2014b0c5..703e547f6b 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -2601,6 +2601,7 @@ void QTest::ignoreMessage(QtMsgType type, const char *message)
QTestLog::ignoreMessage(type, message);
}
+#ifndef QT_NO_REGULAREXPRESSION
/*!
\overload
@@ -2621,6 +2622,7 @@ void QTest::ignoreMessage(QtMsgType type, const QRegularExpression &messagePatte
{
QTestLog::ignoreMessage(type, messagePattern);
}
+#endif // QT_NO_REGULAREXPRESSION
/*! \internal
*/
diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h
index d9c8a43a2a..2b9acabf95 100644
--- a/src/testlib/qtestcase.h
+++ b/src/testlib/qtestcase.h
@@ -248,7 +248,9 @@ namespace QTest
const char *file, int line);
Q_TESTLIB_EXPORT void qWarn(const char *message, const char *file = 0, int line = 0);
Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const char *message);
+#ifndef QT_NO_REGULAREXPRESSION
Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const QRegularExpression &messagePattern);
+#endif
Q_TESTLIB_EXPORT QString qFindTestData(const char* basepath, const char* file = 0, int line = 0, const char* builddir = 0);
Q_TESTLIB_EXPORT QString qFindTestData(const QString& basepath, const char* file = 0, int line = 0, const char* builddir = 0);
diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp
index 8cca892a4d..1e7f131652 100644
--- a/src/testlib/qtestlog.cpp
+++ b/src/testlib/qtestlog.cpp
@@ -133,7 +133,11 @@ namespace QTest {
return tp == type
&& (pattern.type() == QVariant::String ?
stringsMatch(pattern.toString(), message) :
+#ifndef QT_NO_REGULAREXPRESSION
pattern.toRegularExpression().match(message).hasMatch());
+#else
+ false);
+#endif
}
QtMsgType type;
@@ -359,7 +363,9 @@ void QTestLog::printUnhandledIgnoreMessages()
if (list->pattern.type() == QVariant::String) {
message = QStringLiteral("Did not receive message: \"") + list->pattern.toString() + QLatin1Char('"');
} else {
+#ifndef QT_NO_REGULAREXPRESSION
message = QStringLiteral("Did not receive any message matching: \"") + list->pattern.toRegularExpression().pattern() + QLatin1Char('"');
+#endif
}
QTest::TestLoggers::addMessage(QAbstractTestLogger::Info, message);
@@ -512,12 +518,14 @@ void QTestLog::ignoreMessage(QtMsgType type, const char *msg)
QTest::IgnoreResultList::append(QTest::ignoreResultList, type, QString::fromLocal8Bit(msg));
}
+#ifndef QT_NO_REGULAREXPRESSION
void QTestLog::ignoreMessage(QtMsgType type, const QRegularExpression &expression)
{
QTEST_ASSERT(expression.isValid());
QTest::IgnoreResultList::append(QTest::ignoreResultList, type, QVariant(expression));
}
+#endif // QT_NO_REGULAREXPRESSION
void QTestLog::setMaxWarnings(int m)
{
diff --git a/src/testlib/qxmltestlogger.cpp b/src/testlib/qxmltestlogger.cpp
index 3fff753c5c..5ea28bd46d 100644
--- a/src/testlib/qxmltestlogger.cpp
+++ b/src/testlib/qxmltestlogger.cpp
@@ -42,6 +42,7 @@
#include <stdio.h>
#include <string.h>
#include <QtCore/qglobal.h>
+#include <QtCore/qlibraryinfo.h>
#include <QtTest/private/qxmltestlogger_p.h>
#include <QtTest/private/qtestresult_p.h>
@@ -115,11 +116,15 @@ void QXmlTestLogger::startLogging()
outputString(buf.constData());
}
+ QTestCharBuffer quotedBuild;
+ xmlQuote(&quotedBuild, QLibraryInfo::build());
+
QTest::qt_asprintf(&buf,
"<Environment>\n"
" <QtVersion>%s</QtVersion>\n"
+ " <QtBuild>%s</QtBuild>\n"
" <QTestVersion>" QTEST_VERSION_STR "</QTestVersion>\n"
- "</Environment>\n", qVersion());
+ "</Environment>\n", qVersion(), quotedBuild.constData());
outputString(buf.constData());
m_totalTime.start();
}
diff --git a/src/testlib/qxunittestlogger.cpp b/src/testlib/qxunittestlogger.cpp
index a47f77ae49..fe5b13eeeb 100644
--- a/src/testlib/qxunittestlogger.cpp
+++ b/src/testlib/qxunittestlogger.cpp
@@ -46,6 +46,15 @@
#include <QtTest/private/qtestresult_p.h>
#include <QtTest/private/qbenchmark_p.h>
+#ifdef min // windows.h without NOMINMAX is included by the benchmark headers.
+# undef min
+#endif
+#ifdef max
+# undef max
+#endif
+
+#include <QtCore/qlibraryinfo.h>
+
#include <string.h>
QT_BEGIN_NAMESPACE
@@ -108,6 +117,11 @@ void QXunitTestLogger::stopLogging()
property->addAttribute(QTest::AI_PropertyValue, qVersion());
properties->addLogElement(property);
+ property = new QTestElement(QTest::LET_Property);
+ property->addAttribute(QTest::AI_Name, "QtBuild");
+ property->addAttribute(QTest::AI_PropertyValue, QLibraryInfo::build());
+ properties->addLogElement(property);
+
currentLogElement->addLogElement(properties);
currentLogElement->addLogElement(iterator);
diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro
index 310ea317ac..2b58bff8f3 100644
--- a/src/tools/bootstrap/bootstrap.pro
+++ b/src/tools/bootstrap/bootstrap.pro
@@ -61,6 +61,7 @@ SOURCES += \
../../corelib/io/qabstractfileengine.cpp \
../../corelib/io/qbuffer.cpp \
../../corelib/io/qdatastream.cpp \
+ ../../corelib/io/qdebug.cpp \
../../corelib/io/qdir.cpp \
../../corelib/io/qdiriterator.cpp \
../../corelib/io/qfile.cpp \
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index a67ea05956..c63e80f90f 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -266,10 +266,12 @@ void Generator::generateCode()
{
int idx = 0;
for (int i = 0; i < strings.size(); ++i) {
- if (i)
- fprintf(out, ",\n");
const QByteArray &str = strings.at(i);
fprintf(out, "QT_MOC_LITERAL(%d, %d, %d)", i, idx, str.length());
+ if (i != strings.size() - 1)
+ fputc(',', out);
+ const QByteArray comment = str.length() > 32 ? str.left(29) + "..." : str;
+ fprintf(out, " // \"%s\"\n", comment.constData());
idx += str.length() + 1;
for (int j = 0; j < str.length(); ++j) {
if (str.at(j) == '\\') {
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index f5700899fa..91aa97a443 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -1552,10 +1552,17 @@ void Moc::checkProperties(ClassDef *cdef)
// specify get function, for compatibiliy we accept functions
// returning pointers, or const char * for QByteArray.
//
+ QSet<QByteArray> definedProperties;
for (int i = 0; i < cdef->propertyList.count(); ++i) {
PropertyDef &p = cdef->propertyList[i];
if (p.read.isEmpty() && p.member.isEmpty())
continue;
+ if (definedProperties.contains(p.name)) {
+ QByteArray msg = "The property '" + p.name + "' is defined multiple times in class " + cdef->classname + ".";
+ warning(msg.constData());
+ }
+ definedProperties.insert(p.name);
+
for (int j = 0; j < cdef->publicList.count(); ++j) {
const FunctionDef &f = cdef->publicList.at(j);
if (f.name != p.read)
diff --git a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp
index b4f9aedd7a..0df82cb4f5 100644
--- a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp
+++ b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp
@@ -705,9 +705,9 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf
if (isNoReply)
hs << " callWithArgumentList(QDBus::NoBlock, "
- << "QLatin1String(\"" << method.name << "\"), argumentList);" << endl;
+ << "QStringLiteral(\"" << method.name << "\"), argumentList);" << endl;
else
- hs << " return asyncCallWithArgumentList(QLatin1String(\""
+ hs << " return asyncCallWithArgumentList(QStringLiteral(\""
<< method.name << "\"), argumentList);" << endl;
// close the function:
@@ -737,7 +737,7 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf
}
hs << " QDBusMessage reply = callWithArgumentList(QDBus::Block, "
- << "QLatin1String(\"" << method.name << "\"), argumentList);" << endl;
+ << "QStringLiteral(\"" << method.name << "\"), argumentList);" << endl;
argPos++;
hs << " if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == "
diff --git a/src/tools/qdoc/atom.cpp b/src/tools/qdoc/atom.cpp
index 6f9da3790d..5c699b0546 100644
--- a/src/tools/qdoc/atom.cpp
+++ b/src/tools/qdoc/atom.cpp
@@ -42,31 +42,12 @@
#include <qregexp.h>
#include "atom.h"
#include "location.h"
+#include "qdocdatabase.h"
#include <stdio.h>
+#include <qdebug.h>
QT_BEGIN_NAMESPACE
-QLatin1String Atom::BOLD_ ("bold");
-QLatin1String Atom::INDEX_ ("index");
-QLatin1String Atom::ITALIC_ ("italic");
-QLatin1String Atom::LINK_ ("link");
-QLatin1String Atom::PARAMETER_ ("parameter");
-QLatin1String Atom::SPAN_ ("span");
-QLatin1String Atom::SUBSCRIPT_ ("subscript");
-QLatin1String Atom::SUPERSCRIPT_ ("superscript");
-QLatin1String Atom::TELETYPE_ ("teletype");
-QLatin1String Atom::UICONTROL_ ("uicontrol");
-QLatin1String Atom::UNDERLINE_ ("underline");
-
-QLatin1String Atom::BULLET_ ("bullet");
-QLatin1String Atom::TAG_ ("tag");
-QLatin1String Atom::VALUE_ ("value");
-QLatin1String Atom::LOWERALPHA_ ("loweralpha");
-QLatin1String Atom::LOWERROMAN_ ("lowerroman");
-QLatin1String Atom::NUMERIC_ ("numeric");
-QLatin1String Atom::UPPERALPHA_ ("upperalpha");
-QLatin1String Atom::UPPERROMAN_ ("upperroman");
-
/*! \class Atom
\brief The Atom class is the fundamental unit for representing
documents internally.
@@ -387,4 +368,57 @@ void Atom::dump() const
str.toLatin1().data());
}
+/*!
+ The only constructor for LinkAtom. It only create an Atom
+ of type Atom::Link with \a p1 being the link text. \a p2
+ contains some search parameters.
+ */
+LinkAtom::LinkAtom(const QString& p1, const QString& p2)
+ : Atom(p1), genus_(DontCare), goal_(Node::NoType), domain_(0)
+{
+ QStringList params = p2.toLower().split(QLatin1Char(' '));
+ foreach (const QString& p, params) {
+ if (!domain_) {
+ domain_ = QDocDatabase::qdocDB()->findTree(p);
+ if (domain_)
+ continue;
+ }
+ if (goal_ == Node::NoType) {
+ goal_ = Node::goal(p);
+ if (goal_ != Node::NoType)
+ continue;
+ }
+ if (p == "qml")
+ genus_ = QML;
+ else if (p == "cpp")
+ genus_ = CPP;
+ }
+}
+
+/*!
+ Standard copy constructor of LinkAtom \a t.
+ */
+LinkAtom::LinkAtom(const LinkAtom& t)
+ : Atom(Link, t.string()),
+ genus_(t.genus_),
+ goal_(t.goal_),
+ domain_(t.domain_)
+{
+ // nothing
+}
+
+/*!
+ Special copy constructor of LinkAtom \a t, where
+ where the new LinkAtom will not be the first one
+ in the list.
+ */
+LinkAtom::LinkAtom(Atom* previous, const LinkAtom& t)
+ : Atom(previous, Link, t.string()),
+ genus_(t.genus_),
+ goal_(t.goal_),
+ domain_(t.domain_)
+{
+ previous->next_ = this;
+}
+
QT_END_NAMESPACE
diff --git a/src/tools/qdoc/atom.h b/src/tools/qdoc/atom.h
index 84a52c9257..36a7390ae2 100644
--- a/src/tools/qdoc/atom.h
+++ b/src/tools/qdoc/atom.h
@@ -39,17 +39,18 @@
**
****************************************************************************/
-/*
- atom.h
-*/
-
#ifndef ATOM_H
#define ATOM_H
#include <qstringlist.h>
+#include "node.h"
+#include <qdebug.h>
QT_BEGIN_NAMESPACE
+class Tree;
+class LinkAtom;
+
class Atom
{
public:
@@ -64,7 +65,7 @@ public:
BriefRight,
C,
CaptionLeft,
- CaptionRight,
+ CaptionRight, // 10
Code,
CodeBad,
CodeNew,
@@ -74,7 +75,7 @@ public:
DivLeft,
DivRight,
EndQmlText,
- FootnoteLeft,
+ FootnoteLeft, // 20
FootnoteRight,
FormatElse,
FormatEndif,
@@ -84,7 +85,7 @@ public:
GeneratedList,
GuidLink,
HR,
- Image,
+ Image, // 30
ImageText,
ImportantLeft,
ImportantRight,
@@ -94,7 +95,7 @@ public:
LegaleseLeft,
LegaleseRight,
LineBreak,
- Link,
+ Link, // 40
LinkNode,
ListLeft,
ListItemNumber,
@@ -104,7 +105,7 @@ public:
ListItemRight,
ListRight,
Nop,
- NoteLeft,
+ NoteLeft, // 50
NoteRight,
ParaLeft,
ParaRight,
@@ -114,7 +115,7 @@ public:
QuotationRight,
RawString,
SectionLeft,
- SectionRight,
+ SectionRight, // 60
SectionHeadingLeft,
SectionHeadingRight,
SidebarLeft,
@@ -124,7 +125,7 @@ public:
SnippetIdentifier,
SnippetLocation,
String,
- TableLeft,
+ TableLeft, // 70
TableRight,
TableHeaderLeft,
TableHeaderRight,
@@ -134,11 +135,21 @@ public:
TableItemRight,
TableOfContents,
Target,
- UnhandledFormat,
+ UnhandledFormat, // 80
UnknownCommand,
Last = UnknownCommand
};
+ enum NodeGenus { DontCare, CPP, QML };
+
+ friend class LinkAtom;
+
+ Atom(const QString& string)
+ : next_(0), type_(Link)
+ {
+ strs << string;
+ }
+
Atom(Type type, const QString& string = "")
: next_(0), type_(type)
{
@@ -169,6 +180,8 @@ public:
previous->next_ = this;
}
+ virtual ~Atom() { }
+
void appendChar(QChar ch) { strs[0] += ch; }
void appendString(const QString& string) { strs[0] += string; }
void chopString() { strs[0].chop(1); }
@@ -185,34 +198,40 @@ public:
const QString& string(int i) const { return strs[i]; }
int count() const { return strs.size(); }
void dump() const;
+ const QStringList& strings() const { return strs; }
+
+ virtual bool isLinkAtom() const { return false; }
+ virtual NodeGenus genus() const { return DontCare; }
+ virtual bool specifiesDomain() const { return false; }
+ virtual Tree* domain() const { return 0; }
+ virtual Node::Type goal() const { return Node::NoType; }
- static QLatin1String BOLD_;
- static QLatin1String INDEX_;
- static QLatin1String ITALIC_;
- static QLatin1String LINK_;
- static QLatin1String PARAMETER_;
- static QLatin1String SPAN_;
- static QLatin1String SUBSCRIPT_;
- static QLatin1String SUPERSCRIPT_;
- static QLatin1String TELETYPE_;
- static QLatin1String UICONTROL_;
- static QLatin1String UNDERLINE_;
-
- static QLatin1String BULLET_;
- static QLatin1String TAG_;
- static QLatin1String VALUE_;
- static QLatin1String LOWERALPHA_;
- static QLatin1String LOWERROMAN_;
- static QLatin1String NUMERIC_;
- static QLatin1String UPPERALPHA_;
- static QLatin1String UPPERROMAN_;
-
-private:
+ protected:
Atom* next_;
Type type_;
QStringList strs;
};
+class LinkAtom : public Atom
+{
+ public:
+ LinkAtom(const QString& p1, const QString& p2);
+ LinkAtom(const LinkAtom& t);
+ LinkAtom(Atom* previous, const LinkAtom& t);
+ virtual ~LinkAtom() { }
+
+ virtual bool isLinkAtom() const { return true; }
+ virtual NodeGenus genus() const { return genus_; }
+ virtual bool specifiesDomain() const { return (domain_ != 0); }
+ virtual Tree* domain() const { return domain_; }
+ virtual Node::Type goal() const { return goal_; }
+
+ protected:
+ NodeGenus genus_;
+ Node::Type goal_;
+ Tree* domain_;
+};
+
#define ATOM_FORMATTING_BOLD "bold"
#define ATOM_FORMATTING_INDEX "index"
#define ATOM_FORMATTING_ITALIC "italic"
diff --git a/src/tools/qdoc/codemarker.cpp b/src/tools/qdoc/codemarker.cpp
index 99f2abfb2f..235b3c3f04 100644
--- a/src/tools/qdoc/codemarker.cpp
+++ b/src/tools/qdoc/codemarker.cpp
@@ -273,7 +273,7 @@ QString CodeMarker::taggedNode(const Node* node)
case Node::Property:
tag = QLatin1String("@property");
break;
- case Node::Document:
+ case Node::QmlType:
/*
Remove the "QML:" prefix, if present.
There shouldn't be any of these "QML:"
@@ -282,10 +282,11 @@ QString CodeMarker::taggedNode(const Node* node)
qualifiers, but this code is kept to
be backward compatible.
*/
- if (node->subType() == Node::QmlClass) {
- if (node->name().startsWith(QLatin1String("QML:")))
- name = name.mid(4);
- }
+ if (node->name().startsWith(QLatin1String("QML:")))
+ name = name.mid(4);
+ tag = QLatin1String("@property");
+ break;
+ case Node::Document:
tag = QLatin1String("@property");
break;
case Node::QmlMethod:
@@ -400,9 +401,8 @@ void CodeMarker::insert(FastSection &fastSection,
InnerNode* p = node->parent();
if (p->type() == Node::QmlPropertyGroup)
p = p->parent();
- if (p != fastSection.parent_) { // && !node->parent()->isAbstract()) {
- if (p->subType() != Node::QmlClass || !p->isAbstract()) {
- //if (node->type() != Node::QmlProperty) {
+ if (p != fastSection.parent_) {
+ if (!p->isQmlType() || !p->isAbstract()) {
inheritedMember = true;
}
}
@@ -622,6 +622,7 @@ QStringList CodeMarker::macRefsForNode(Node *node)
}
case Node::Namespace:
case Node::Document:
+ case Node::QmlType:
default:
return QStringList();
}
@@ -648,7 +649,7 @@ QString CodeMarker::macName(const Node *node, const QString &name)
/*!
Returns an empty list of documentation sections.
*/
-QList<Section> CodeMarker::qmlSections(const QmlClassNode* , SynopsisStyle )
+QList<Section> CodeMarker::qmlSections(QmlClassNode* , SynopsisStyle )
{
return QList<Section>();
}
diff --git a/src/tools/qdoc/codemarker.h b/src/tools/qdoc/codemarker.h
index 02caedf9b8..aa38b82e24 100644
--- a/src/tools/qdoc/codemarker.h
+++ b/src/tools/qdoc/codemarker.h
@@ -54,7 +54,6 @@
QT_BEGIN_NAMESPACE
class Config;
-class Tree;
typedef QMultiMap<QString, Node*> MemberMap; // the string is the member signature
typedef QPair<const QmlClassNode*, MemberMap> ClassMap; // the node is the QML type
@@ -155,7 +154,7 @@ public:
virtual QList<Section> sections(const InnerNode *inner,
SynopsisStyle style,
Status status) = 0;
- virtual QList<Section> qmlSections(const QmlClassNode* qmlClassNode, SynopsisStyle style);
+ virtual QList<Section> qmlSections(QmlClassNode* qmlClassNode, SynopsisStyle style);
virtual QStringList macRefsForNode(Node* node);
static void initialize(const Config& config);
diff --git a/src/tools/qdoc/codeparser.cpp b/src/tools/qdoc/codeparser.cpp
index a0ea561b28..e25056e353 100644
--- a/src/tools/qdoc/codeparser.cpp
+++ b/src/tools/qdoc/codeparser.cpp
@@ -76,7 +76,6 @@ QT_BEGIN_NAMESPACE
QString CodeParser::currentSubDir_;
QList<CodeParser *> CodeParser::parsers;
bool CodeParser::showInternal = false;
-QMap<QString,QString> CodeParser::nameToTitle;
/*!
The constructor adds this code parser to the static
@@ -300,50 +299,30 @@ void CodeParser::processCommonMetaCommand(const Location& location,
else if (command == COMMAND_PAGEKEYWORDS) {
node->addPageKeywords(arg.first);
}
- else if (command == COMMAND_SUBTITLE) {
- if (node->type() == Node::Document) {
- DocNode *dn = static_cast<DocNode *>(node);
- dn->setSubTitle(arg.first);
- }
- else
- location.warning(tr("Ignored '\\%1'").arg(COMMAND_SUBTITLE));
- }
else if (command == COMMAND_THREADSAFE) {
node->setThreadSafeness(Node::ThreadSafe);
}
else if (command == COMMAND_TITLE) {
- if (node->type() == Node::Document) {
- DocNode *dn = static_cast<DocNode *>(node);
- dn->setTitle(arg.first);
- if (dn->subType() == Node::Example) {
- ExampleNode::exampleNodeMap.insert(dn->title(),static_cast<ExampleNode*>(dn));
- }
- nameToTitle.insert(dn->name(),arg.first);
- }
- else
- location.warning(tr("Ignored '\\%1'").arg(COMMAND_TITLE));
+ node->setTitle(arg.first);
+ if (!node->isDocNode() && !node->isCollectionNode())
+ location.warning(tr("Ignored '\\%1'").arg(COMMAND_SUBTITLE));
+ else if (node->isExample())
+ qdb_->addExampleNode(static_cast<ExampleNode*>(node));
+ }
+ else if (command == COMMAND_SUBTITLE) {
+ node->setSubTitle(arg.first);
+ if (!node->isDocNode() && !node->isCollectionNode())
+ location.warning(tr("Ignored '\\%1'").arg(COMMAND_SUBTITLE));
}
else if (command == COMMAND_QTVARIABLE) {
- if (node->subType() == Node::Module) {
- DocNode *dn = static_cast<DocNode *>(node);
- dn->setQtVariable(arg.first);
- }
- else
- location.warning(tr("Command '\\%1' found outside of '\\module'. It can only be used within a module page.")
+ node->setQtVariable(arg.first);
+ if (!node->isModule() && !node->isQmlModule())
+ location.warning(tr("Command '\\%1' is only meanigfule in '\\module' and '\\qmlmodule'.")
.arg(COMMAND_QTVARIABLE));
}
}
/*!
- Find the page title given the page \a name and return it.
- */
-const QString CodeParser::titleFromName(const QString& name)
-{
- const QString t = nameToTitle.value(name);
- return t;
-}
-
-/*!
\internal
*/
void CodeParser::extractPageLinkAndDesc(const QString& arg,
@@ -412,9 +391,9 @@ bool CodeParser::isParsingQdoc() const
for an entity that will produce a documentation page will contain an
\inmodule command to tell qdoc which module the entity belongs to.
- But now that we normally run qdoc on each module in two passes. The
- first produces an index file; the second pass generates the docs
- after reading all the index files it needs.
+ But now we normally run qdoc on each module in two passes. The first
+ produces an index file; the second pass generates the docs after
+ reading all the index files it needs.
This means that all the pages generated during each pass 2 run of
qdoc almost certainly belong to a single module, and the name of
@@ -431,10 +410,10 @@ bool CodeParser::isParsingQdoc() const
void CodeParser::checkModuleInclusion(Node* n)
{
if (n->moduleName().isEmpty()) {
+ n->setModuleName(Generator::defaultModuleName());
switch (n->type()) {
case Node::Class:
if (n->access() != Node::Private && !n->doc().isEmpty()) {
- n->setModuleName(Generator::defaultModuleName());
n->doc().location().warning(tr("Class %1 has no \\inmodule command; "
"using project name by default: %2")
.arg(n->name()).arg(Generator::defaultModuleName()));
@@ -442,16 +421,15 @@ void CodeParser::checkModuleInclusion(Node* n)
break;
case Node::Namespace:
if (n->access() != Node::Private && !n->name().isEmpty() && !n->doc().isEmpty()) {
- n->setModuleName(Generator::defaultModuleName());
n->doc().location().warning(tr("Namespace %1 has no \\inmodule command; "
"using project name by default: %2")
.arg(n->name()).arg(Generator::defaultModuleName()));
}
break;
+#if 0
case Node::Document:
if (n->access() != Node::Private && !n->doc().isEmpty()) {
if (n->subType() == Node::HeaderFile) {
- n->setModuleName(Generator::defaultModuleName());
#if 0
n->doc().location().warning(tr("Header file with title \"%1\" has no \\inmodule command; "
"using project name by default: %2")
@@ -459,7 +437,6 @@ void CodeParser::checkModuleInclusion(Node* n)
#endif
}
else if (n->subType() == Node::Page) {
- n->setModuleName(Generator::defaultModuleName());
#if 0
n->doc().location().warning(tr("Page with title \"%1\" has no \\inmodule command; "
"using project name by default: %2")
@@ -467,7 +444,6 @@ void CodeParser::checkModuleInclusion(Node* n)
#endif
}
else if (n->subType() == Node::Example) {
- n->setModuleName(Generator::defaultModuleName());
#if 0
n->doc().location().warning(tr("Example with title \"%1\" has no \\inmodule command; "
"using project name by default: %2")
@@ -476,6 +452,7 @@ void CodeParser::checkModuleInclusion(Node* n)
}
}
break;
+#endif
default:
break;
}
diff --git a/src/tools/qdoc/codeparser.h b/src/tools/qdoc/codeparser.h
index 89f661abeb..baa82fc650 100644
--- a/src/tools/qdoc/codeparser.h
+++ b/src/tools/qdoc/codeparser.h
@@ -81,7 +81,6 @@ public:
static CodeParser *parserForLanguage(const QString& language);
static CodeParser *parserForHeaderFile(const QString &filePath);
static CodeParser *parserForSourceFile(const QString &filePath);
- static const QString titleFromName(const QString& name);
static void setLink(Node* node, Node::LinkType linkType, const QString& arg);
static const QString& currentOutputSubdirectory() { return currentSubDir_; }
@@ -101,7 +100,6 @@ private:
static QString currentSubDir_;
static QList<CodeParser *> parsers;
static bool showInternal;
- static QMap<QString,QString> nameToTitle;
};
QT_END_NAMESPACE
diff --git a/src/tools/qdoc/config.cpp b/src/tools/qdoc/config.cpp
index 56e7287c40..74a571fa3c 100644
--- a/src/tools/qdoc/config.cpp
+++ b/src/tools/qdoc/config.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the tools applications of the Qt Toolkit.
@@ -56,6 +56,7 @@
QT_BEGIN_NAMESPACE
QString ConfigStrings::ALIAS = QStringLiteral("alias");
+QString ConfigStrings::AUTOLINKERRORS = QStringLiteral("autolinkerrors");
QString ConfigStrings::BASE = QStringLiteral("base");
QString ConfigStrings::BASEDIR = QStringLiteral("basedir");
QString ConfigStrings::BUILDVERSION = QStringLiteral("buildversion");
@@ -241,7 +242,8 @@ QStringList MetaStack::getExpanded(const Location& location)
return top().accum;
}
-QT_STATIC_CONST_IMPL QString Config::dot = QLatin1String(".");
+const QString Config::dot = QLatin1String(".");
+bool Config::debug_ = false;
bool Config::generateExamples = true;
QString Config::overrideOutputDir;
QString Config::installDir;
@@ -326,11 +328,14 @@ bool Config::getBool(const QString& var) const
Looks up the configuration variable \a var in the string list
map. Iterates through the string list found, interpreting each
string in the list as an integer and adding it to a total sum.
- Returns the sum.
+ Returns the sum or \c -1 if \a var is not set.
*/
int Config::getInt(const QString& var) const
{
QStringList strs = getStringList(var);
+ if (strs.isEmpty())
+ return -1;
+
QStringList::ConstIterator s = strs.constBegin();
int sum = 0;
@@ -452,87 +457,21 @@ QStringList Config::getStringList(const QString& var) const
}
/*!
- \brief Returns the a path list where all paths are canonicalized, then
- made relative to the config file.
- \param var The variable containing the list of paths.
- \see Location::canonicalRelativePath()
- */
-QStringList Config::getCanonicalPathList(const QString& var) const
-{
- QStringList t;
- QList<ConfigVar> configVars = configVars_.values(var);
- if (!configVars.empty()) {
- int i = configVars.size() - 1;
- while (i >= 0) {
- const ConfigVar& cv = configVars[i];
- if (!cv.location_.isEmpty())
- (Location&) lastLocation_ = cv.location_;
- if (!cv.plus_)
- t.clear();
- const QString d = cv.currentPath_;
- const QStringList& sl = cv.values_;
- if (!sl.isEmpty()) {
- t.reserve(t.size() + sl.size());
- for (int i=0; i<sl.size(); ++i) {
- QDir dir(d + "/" + sl[i]);
- t.append(dir.canonicalPath());
- }
- }
- --i;
- }
- }
- return t;
-}
-
-/*!
- This function should only be called when the configuration
- variable \a var maps to string lists that contain file paths.
- It cleans the paths with QDir::cleanPath() before returning
- them.
- */
-QStringList Config::getCleanPathList(const QString& var) const
-{
- QStringList t;
- QList<ConfigVar> configVars = configVars_.values(var);
- if (!configVars.empty()) {
- int i = configVars.size() - 1;
- while (i >= 0) {
- const ConfigVar& cv = configVars[i];
- if (!cv.plus_)
- t.clear();
- if (!cv.location_.isEmpty())
- (Location&) lastLocation_ = cv.location_;
- const QStringList& sl = cv.values_;
- if (!sl.isEmpty()) {
- t.reserve(t.size() + sl.size());
- for (int i=0; i<sl.size(); ++i) {
- t.append(QDir::cleanPath(sl[i].simplified()));
- }
- }
- --i;
- }
- }
- return t;
-}
-
-/*!
- This function should only be called when the configuration
- variable \a var maps to string lists that contain file paths.
- It cleans the paths with QDir::cleanPath() before returning
- them.
+ Returns the a path list where all paths from the config variable \a var
+ are canonicalized. If \a validate is true, a warning for invalid paths is
+ generated.
- First, this function looks up the configuration variable \a var
- in the location map and, if found, sets the internal variable
- \c{lastLocation_} the Location that \a var maps to.
+ First, this function looks up the configuration variable \a var
+ in the location map and, if found, sets the internal variable
+ \c{lastLocation_} the Location that \a var maps to.
- Then it looks up the configuration variable \a var in the string
- list map, which maps to one or more records that each contains a
- list of file paths.
+ Then it looks up the configuration variable \a var in the string
+ list map, which maps to one or more records that each contains a
+ list of file paths.
- These paths might not be clean, so QDir::cleanPath() is called
- for each one. The string list returned contains cleaned paths.
+ \sa Location::canonicalRelativePath()
*/
-QStringList Config::getPathList(const QString& var) const
+QStringList Config::getCanonicalPathList(const QString& var, bool validate) const
{
QStringList t;
QList<ConfigVar> configVars = configVars_.values(var);
@@ -540,22 +479,23 @@ QStringList Config::getPathList(const QString& var) const
int i = configVars.size() - 1;
while (i >= 0) {
const ConfigVar& cv = configVars[i];
- if (!cv.plus_)
- t.clear();
if (!cv.location_.isEmpty())
(Location&) lastLocation_ = cv.location_;
+ if (!cv.plus_)
+ t.clear();
const QString d = cv.currentPath_;
const QStringList& sl = cv.values_;
if (!sl.isEmpty()) {
t.reserve(t.size() + sl.size());
for (int i=0; i<sl.size(); ++i) {
- QFileInfo fileInfo;
- QString path = d + "/" + QDir::cleanPath(sl[i].simplified());
- fileInfo.setFile(path);
- if (!fileInfo.exists())
- lastLocation_.warning(tr("File '%1' does not exist").arg(path));
+ QDir dir(sl[i].simplified());
+ QString path = dir.path();
+ if (dir.isRelative())
+ dir.setPath(d + "/" + path);
+ if (validate && !QFileInfo::exists(dir.path()))
+ lastLocation_.warning(tr("Cannot find file or directory: %1").arg(path));
else
- t.append(path);
+ t.append(dir.canonicalPath());
}
}
--i;
@@ -564,7 +504,6 @@ QStringList Config::getPathList(const QString& var) const
return t;
}
-
/*!
Calls getRegExpList() with the control variable \a var and
iterates through the resulting list of regular expressions,
diff --git a/src/tools/qdoc/config.h b/src/tools/qdoc/config.h
index 54ee8de47f..5e21e069b5 100644
--- a/src/tools/qdoc/config.h
+++ b/src/tools/qdoc/config.h
@@ -88,6 +88,8 @@ public:
Config(const QString& programName);
~Config();
+ static bool debug_;
+
void load(const QString& fileName);
void setStringList(const QString& var, const QStringList& values);
@@ -101,9 +103,7 @@ public:
QString getString(const QString& var) const;
QSet<QString> getStringSet(const QString& var) const;
QStringList getStringList(const QString& var) const;
- QStringList getCanonicalPathList(const QString& var) const;
- QStringList getCleanPathList(const QString& var) const;
- QStringList getPathList(const QString& var) const;
+ QStringList getCanonicalPathList(const QString& var, bool validate = false) const;
QRegExp getRegExp(const QString& var) const;
QList<QRegExp> getRegExpList(const QString& var) const;
QSet<QString> subVars(const QString& var) const;
@@ -141,7 +141,7 @@ public:
static void pushWorkingDir(const QString& dir);
static QString popWorkingDir();
- QT_STATIC_CONST QString dot;
+ static const QString dot;
static bool generateExamples;
static QString installDir;
@@ -167,6 +167,7 @@ private:
struct ConfigStrings
{
static QString ALIAS;
+ static QString AUTOLINKERRORS;
static QString BASE;
static QString BASEDIR;
static QString BUILDVERSION;
@@ -239,6 +240,7 @@ struct ConfigStrings
};
#define CONFIG_ALIAS ConfigStrings::ALIAS
+#define CONFIG_AUTOLINKERRORS ConfigStrings::AUTOLINKERRORS
#define CONFIG_BASE ConfigStrings::BASE
#define CONFIG_BASEDIR ConfigStrings::BASEDIR
#define CONFIG_BUILDVERSION ConfigStrings::BUILDVERSION
diff --git a/src/tools/qdoc/cppcodemarker.cpp b/src/tools/qdoc/cppcodemarker.cpp
index 64b11109f7..d3cb111873 100644
--- a/src/tools/qdoc/cppcodemarker.cpp
+++ b/src/tools/qdoc/cppcodemarker.cpp
@@ -403,6 +403,9 @@ QString CppCodeMarker::markedUpFullName(const Node *node, const Node *relative)
QString CppCodeMarker::markedUpEnumValue(const QString &enumValue, const Node *relative)
{
+ if (relative->type() != Node::Enum)
+ return enumValue;
+
const Node *node = relative->parent();
QString fullName;
while (node->parent()) {
@@ -629,7 +632,8 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner,
QList<RelatedClass>::ConstIterator r =
ancestorClass->baseClasses().constBegin();
while (r != ancestorClass->baseClasses().constEnd()) {
- stack.prepend((*r).node);
+ if ((*r).node_)
+ stack.prepend((*r).node_);
++r;
}
}
@@ -724,7 +728,8 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner,
QList<RelatedClass>::ConstIterator r =
ancestorClass->baseClasses().constBegin();
while (r != ancestorClass->baseClasses().constEnd()) {
- stack.prepend((*r).node);
+ if ((*r).node_)
+ stack.prepend((*r).node_);
++r;
}
}
@@ -748,6 +753,16 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner,
style == Detailed ? "types" : QString(),
"type",
"types");
+ FastSection variables(inner,
+ style == Summary ? "Variables" : "Variable Documentation",
+ style == Detailed ? "vars" : QString(),
+ "variable",
+ "variables");
+ FastSection staticVariables(inner,
+ "Static Variables",
+ QString(),
+ "static variable",
+ "static variables");
FastSection functions(inner,
style == Summary ?
"Functions" : "Function Documentation",
@@ -786,14 +801,27 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner,
insert(functions, *n, style, status);
}
break;
+ case Node::Variable:
+ {
+ const VariableNode* var = static_cast<const VariableNode*>(*n);
+ if (!var->doc().isEmpty()) {
+ if (var->isStatic())
+ insert(staticVariables,*n,style,status);
+ else
+ insert(variables, *n, style, status);
+ }
+ }
+ break;
default:
- ;
+ break;
}
++n;
}
append(sections, namespaces);
append(sections, classes);
append(sections, types);
+ append(sections, variables);
+ append(sections, staticVariables);
append(sections, functions);
append(sections, macros);
}
@@ -1066,7 +1094,7 @@ QString CppCodeMarker::addMarkUp(const QString &in,
the list of documentation sections for the children of the
\a qmlClassNode.
*/
-QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, SynopsisStyle style)
+QList<Section> CppCodeMarker::qmlSections(QmlClassNode* qmlClassNode, SynopsisStyle style)
{
QList<Section> sections;
if (qmlClassNode) {
@@ -1107,7 +1135,7 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, Syno
"method",
"methods");
- const QmlClassNode* qcn = qmlClassNode;
+ QmlClassNode* qcn = qmlClassNode;
while (qcn != 0) {
NodeList::ConstIterator c = qcn->childNodes().constBegin();
while (c != qcn->childNodes().constEnd()) {
@@ -1146,7 +1174,7 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, Syno
++c;
}
if (qcn->qmlBaseNode() != 0) {
- qcn = static_cast<const QmlClassNode*>(qcn->qmlBaseNode());
+ qcn = static_cast<QmlClassNode*>(qcn->qmlBaseNode());
if (!qcn->isAbstract())
qcn = 0;
}
@@ -1172,7 +1200,7 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, Syno
FastSection qmlmethods(qmlClassNode,"Method Documentation","qmlmeth","member","members");
FastSection qmlattachedmethods(qmlClassNode,"Attached Method Documentation","qmlattmeth",
"member","members");
- const QmlClassNode* qcn = qmlClassNode;
+ QmlClassNode* qcn = qmlClassNode;
while (qcn != 0) {
NodeList::ConstIterator c = qcn->childNodes().constBegin();
while (c != qcn->childNodes().constEnd()) {
@@ -1210,7 +1238,7 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, Syno
++c;
}
if (qcn->qmlBaseNode() != 0) {
- qcn = static_cast<const QmlClassNode*>(qcn->qmlBaseNode());
+ qcn = static_cast<QmlClassNode*>(qcn->qmlBaseNode());
if (!qcn->isAbstract())
qcn = 0;
}
@@ -1232,7 +1260,7 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, Syno
*/
ClassMap* classMap = 0;
FastSection all(qmlClassNode,QString(),QString(),"member","members");
- const QmlClassNode* current = qmlClassNode;
+ QmlClassNode* current = qmlClassNode;
while (current != 0) {
/*
If the QML type is abstract, do not create
diff --git a/src/tools/qdoc/cppcodemarker.h b/src/tools/qdoc/cppcodemarker.h
index 91a9c01a28..74faf1ca57 100644
--- a/src/tools/qdoc/cppcodemarker.h
+++ b/src/tools/qdoc/cppcodemarker.h
@@ -78,7 +78,7 @@ public:
virtual QList<Section> sections(const InnerNode *innerNode,
SynopsisStyle style,
Status status);
- virtual QList<Section> qmlSections(const QmlClassNode* qmlClassNode, SynopsisStyle style);
+ virtual QList<Section> qmlSections(QmlClassNode* qmlClassNode, SynopsisStyle style);
private:
QString addMarkUp(const QString& protectedCode,
diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp
index bb403bd4d9..2755bf7254 100644
--- a/src/tools/qdoc/cppcodeparser.cpp
+++ b/src/tools/qdoc/cppcodeparser.cpp
@@ -52,6 +52,7 @@
#include "tokenizer.h"
#include "qdocdatabase.h"
#include <qdebug.h>
+#include "generator.h"
QT_BEGIN_NAMESPACE
@@ -99,8 +100,8 @@ void CppCodeParser::initializeParser(const Config &config)
nodeTypeMap.insert(COMMAND_PROPERTY, Node::Property);
nodeTypeMap.insert(COMMAND_VARIABLE, Node::Variable);
- exampleFiles = config.getCleanPathList(CONFIG_EXAMPLES);
- exampleDirs = config.getCleanPathList(CONFIG_EXAMPLEDIRS);
+ exampleFiles = config.getCanonicalPathList(CONFIG_EXAMPLES);
+ exampleDirs = config.getCanonicalPathList(CONFIG_EXAMPLEDIRS);
QStringList exampleFilePatterns = config.getStringList(
CONFIG_EXAMPLES + Config::dot + CONFIG_FILEEXTENSIONS);
@@ -173,7 +174,7 @@ void CppCodeParser::parseHeaderFile(const Location& location, const QString& fil
Tokenizer fileTokenizer(fileLocation, in);
tokenizer = &fileTokenizer;
readToken();
- matchDeclList(qdb_->treeRoot());
+ matchDeclList(qdb_->primaryTreeRoot());
if (!fileTokenizer.version().isEmpty())
qdb_->setVersion(fileTokenizer.version());
in.close();
@@ -218,15 +219,13 @@ void CppCodeParser::parseSourceFile(const Location& location, const QString& fil
}
/*!
- This is called after all the header files have been parsed.
- I think the most important thing it does is resolve class
- inheritance links in the tree. But it also initializes a
- bunch of stuff.
+ This is called after all the C++ header files have been
+ parsed. The most important thing it does is resolve C++
+ class inheritance links in the tree. It also initializes
+ a bunch of other collections.
*/
void CppCodeParser::doneParsingHeaderFiles()
{
- qdb_->resolveInheritance();
-
QMapIterator<QString, QString> i(sequentialIteratorClasses);
while (i.hasNext()) {
i.next();
@@ -265,11 +264,10 @@ void CppCodeParser::doneParsingHeaderFiles()
*/
void CppCodeParser::doneParsingSourceFiles()
{
- qdb_->treeRoot()->clearCurrentChildPointers();
- qdb_->treeRoot()->normalizeOverloads();
+ qdb_->primaryTreeRoot()->normalizeOverloads();
qdb_->fixInheritance();
qdb_->resolveProperties();
- qdb_->treeRoot()->makeUndocumentedChildrenInternal();
+ qdb_->primaryTreeRoot()->makeUndocumentedChildrenInternal();
}
static QSet<QString> topicCommands_;
@@ -328,38 +326,33 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
doc.startLocation().warning(tr("Invalid syntax in '\\%1'").arg(COMMAND_FN));
}
else {
- func = qdb_->findNodeInOpenNamespace(parentPath, clone);
- /*
- Search the root namespace if no match was found.
- */
+ func = qdb_->findFunctionNode(parentPath, clone);
if (func == 0) {
- func = qdb_->findFunctionNode(parentPath, clone);
+ if (parentPath.isEmpty() && !lastPath_.isEmpty())
+ func = qdb_->findFunctionNode(lastPath_, clone);
}
+ /*
+ If the node was not found, then search for it in the
+ open C++ namespaces. We don't expect this search to
+ be necessary often. Nor do we expect it to succeed
+ very often.
+ */
+ if (func == 0)
+ func = qdb_->findNodeInOpenNamespace(parentPath, clone);
+
if (func == 0) {
- if (parentPath.isEmpty() && !lastPath_.isEmpty()) {
- func = qdb_->findFunctionNode(lastPath_, clone);
- }
- if (func == 0) {
- doc.location().warning(tr("Cannot find '%1' in '\\%2' %3")
- .arg(clone->name() + "(...)")
- .arg(COMMAND_FN)
- .arg(arg.first),
- tr("I cannot find any function of that name with the "
- "specified signature. Make sure that the signature "
- "is identical to the declaration, including 'const' "
- "qualifiers."));
- }
- else {
- doc.location().warning(tr("Missing '%1::' for '%2' in '\\%3'")
- .arg(lastPath_.join("::"))
- .arg(clone->name() + "()")
- .arg(COMMAND_FN));
- }
+ doc.location().warning(tr("Cannot find '%1' in '\\%2' %3")
+ .arg(clone->name() + "(...)")
+ .arg(COMMAND_FN)
+ .arg(arg.first),
+ tr("I cannot find any function of that name with the "
+ "specified signature. Make sure that the signature "
+ "is identical to the declaration, including 'const' "
+ "qualifiers."));
}
- else {
+ else
lastPath_ = parentPath;
- }
if (func) {
func->borrowParameterNames(clone);
func->setParentPath(clone->parentPath());
@@ -372,7 +365,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
QStringList parentPath;
FunctionNode *func = 0;
- extra.root = qdb_->treeRoot();
+ extra.root = qdb_->primaryTreeRoot();
extra.isMacro = true;
if (makeFunctionNode(arg.first, &parentPath, &func, extra)) {
if (!parentPath.isEmpty()) {
@@ -394,7 +387,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
return func;
}
else if (QRegExp("[A-Za-z_][A-Za-z0-9_]+").exactMatch(arg.first)) {
- func = new FunctionNode(qdb_->treeRoot(), arg.first);
+ func = new FunctionNode(qdb_->primaryTreeRoot(), arg.first);
func->setAccess(Node::Public);
func->setLocation(doc.startLocation());
func->setMetaness(FunctionNode::MacroWithoutParams);
@@ -415,29 +408,13 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
without including the namespace qualifier.
*/
Node::Type type = nodeTypeMap[command];
- Node::SubType subtype = Node::NoSubType;
- if (type == Node::Document)
- subtype = Node::QmlClass;
-
QStringList paths = arg.first.split(QLatin1Char(' '));
QStringList path = paths[0].split("::");
Node *node = 0;
- /*
- If the command refers to something that can be in a
- C++ namespace, search for it first in all the known
- C++ namespaces.
- */
- node = qdb_->findNodeInOpenNamespace(path, type, subtype);
-
- /*
- If the node was not found in a C++ namespace, search
- for it in the root namespace.
- */
- if (node == 0) {
- node = qdb_->findNodeByNameAndType(path, type, subtype);
- }
-
+ node = qdb_->findNodeInOpenNamespace(path, type);
+ if (node == 0)
+ node = qdb_->findNodeByNameAndType(path, type);
if (node == 0) {
doc.location().warning(tr("Cannot find '%1' specified with '\\%2' in any header file")
.arg(arg.first).arg(command));
@@ -446,53 +423,58 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
}
else if (node->isInnerNode()) {
/*
- This treets a class as a namespace.
+ This treats a class as a namespace.
*/
- if (path.size() > 1) {
- path.pop_back();
- QString ns = path.join("::");
- qdb_->insertOpenNamespace(ns);
+ if ((type == Node::Class) || (type == Node::Namespace)) {
+ if (path.size() > 1) {
+ path.pop_back();
+ QString ns = path.join("::");
+ qdb_->insertOpenNamespace(ns);
+ }
}
}
return node;
}
else if (command == COMMAND_EXAMPLE) {
if (Config::generateExamples) {
- ExampleNode* en = new ExampleNode(qdb_->treeRoot(), arg.first);
+ ExampleNode* en = new ExampleNode(qdb_->primaryTreeRoot(), arg.first);
en->setLocation(doc.startLocation());
createExampleFileNodes(en);
return en;
}
}
else if (command == COMMAND_EXTERNALPAGE) {
- DocNode* dn = new DocNode(qdb_->treeRoot(), arg.first, Node::ExternalPage, Node::ArticlePage);
+ DocNode* dn = new DocNode(qdb_->primaryTreeRoot(), arg.first, Node::ExternalPage, Node::ArticlePage);
dn->setLocation(doc.startLocation());
return dn;
}
else if (command == COMMAND_FILE) {
- DocNode* dn = new DocNode(qdb_->treeRoot(), arg.first, Node::File, Node::NoPageType);
- dn->setLocation(doc.startLocation());
- return dn;
- }
- else if (command == COMMAND_GROUP) {
- DocNode* dn = qdb_->addGroup(arg.first);
+ DocNode* dn = new DocNode(qdb_->primaryTreeRoot(), arg.first, Node::File, Node::NoPageType);
dn->setLocation(doc.startLocation());
return dn;
}
else if (command == COMMAND_HEADERFILE) {
- DocNode* dn = new DocNode(qdb_->treeRoot(), arg.first, Node::HeaderFile, Node::ApiPage);
+ DocNode* dn = new DocNode(qdb_->primaryTreeRoot(), arg.first, Node::HeaderFile, Node::ApiPage);
dn->setLocation(doc.startLocation());
return dn;
}
+ else if (command == COMMAND_GROUP) {
+ GroupNode* gn = qdb_->addGroup(arg.first);
+ gn->setLocation(doc.startLocation());
+ gn->markSeen();
+ return gn;
+ }
else if (command == COMMAND_MODULE) {
- DocNode* dn = qdb_->addModule(arg.first);
- dn->setLocation(doc.startLocation());
- return dn;
+ ModuleNode* mn = qdb_->addModule(arg.first);
+ mn->setLocation(doc.startLocation());
+ mn->markSeen();
+ return mn;
}
else if (command == COMMAND_QMLMODULE) {
- DocNode* dn = qdb_->addQmlModule(arg.first);
- dn->setLocation(doc.startLocation());
- return dn;
+ QmlModuleNode* qmn = qdb_->addQmlModule(arg.first);
+ qmn->setLocation(doc.startLocation());
+ qmn->markSeen();
+ return qmn;
}
else if (command == COMMAND_PAGE) {
Node::PageType ptype = Node::ArticlePage;
@@ -529,9 +511,9 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
NameCollisionNode* ncn = qdb_->checkForCollision(args[0]);
DocNode* dn = 0;
if (ptype == Node::DitaMapPage)
- dn = new DitaMapNode(qdb_->treeRoot(), args[0]);
+ dn = new DitaMapNode(qdb_->primaryTreeRoot(), args[0]);
else
- dn = new DocNode(qdb_->treeRoot(), args[0], Node::Page, ptype);
+ dn = new DocNode(qdb_->primaryTreeRoot(), args[0], Node::Page, ptype);
dn->setLocation(doc.startLocation());
if (ncn) {
ncn->addCollision(dn);
@@ -539,7 +521,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
return dn;
}
else if (command == COMMAND_DITAMAP) {
- DocNode* dn = new DitaMapNode(qdb_->treeRoot(), arg.first);
+ DocNode* dn = new DitaMapNode(qdb_->primaryTreeRoot(), arg.first);
dn->setLocation(doc.startLocation());
return dn;
}
@@ -579,7 +561,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
node and return that one.
*/
NameCollisionNode* ncn = qdb_->checkForCollision(names[0]);
- QmlClassNode* qcn = new QmlClassNode(qdb_->treeRoot(), names[0]);
+ QmlClassNode* qcn = new QmlClassNode(qdb_->primaryTreeRoot(), names[0]);
qcn->setClassNode(classNode);
qcn->setLocation(doc.startLocation());
#if 0
@@ -598,12 +580,13 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
}
}
#endif
- if (ncn)
+ if (ncn) {
ncn->addCollision(qcn);
+ }
return qcn;
}
else if (command == COMMAND_QMLBASICTYPE) {
- QmlBasicTypeNode* n = new QmlBasicTypeNode(qdb_->treeRoot(), arg.first);
+ QmlBasicTypeNode* n = new QmlBasicTypeNode(qdb_->primaryTreeRoot(), arg.first);
n->setLocation(doc.startLocation());
return n;
}
@@ -959,38 +942,12 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc,
}
}
else if (command == COMMAND_RELATES) {
- /*
- Find the node that this node relates to.
- */
- Node* n = 0;
- if (arg.startsWith(QLatin1Char('<')) || arg.startsWith('"')) {
- /*
- It should be a header file, I think.
- */
- n = qdb_->findNodeByNameAndType(QStringList(arg), Node::Document, Node::NoSubType);
- }
- else {
- /*
- If it wasn't a file, it should be either a class or a namespace.
- */
- QStringList newPath = arg.split("::");
- n = qdb_->findClassNode(newPath);
- if (!n)
- n = qdb_->findNamespaceNode(newPath);
- }
-
- if (!n) {
- /*
- Didn't ind it. Error...
- */
+ QStringList path = arg.split("::");
+ Node* n = qdb_->findRelatesNode(path);
+ if (!n)
doc.location().warning(tr("Cannot find '%1' in '\\%2'").arg(arg).arg(COMMAND_RELATES));
- }
- else {
- /*
- Found it. This node relates to it.
- */
+ else
node->setRelates(static_cast<InnerNode*>(n));
- }
}
else if (command == COMMAND_CONTENTSPAGE) {
setLink(node, Node::ContentsLink, arg);
@@ -1010,14 +967,14 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc,
else if (command == COMMAND_QMLINHERITS) {
if (node->name() == arg)
doc.location().warning(tr("%1 tries to inherit itself").arg(arg));
- else if (node->subType() == Node::QmlClass) {
+ else if (node->isQmlType()) {
QmlClassNode *qmlClass = static_cast<QmlClassNode*>(node);
qmlClass->setQmlBaseName(arg);
QmlClassNode::addInheritedBy(arg,node);
}
}
else if (command == COMMAND_QMLINSTANTIATES) {
- if ((node->type() == Node::Document) && (node->subType() == Node::QmlClass)) {
+ if (node->isQmlType()) {
ClassNode* classNode = qdb_->findClassNode(arg.split("::"));
if (classNode)
node->setClassNode(classNode);
@@ -1062,9 +1019,8 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc,
}
}
else if (command == COMMAND_QMLABSTRACT) {
- if ((node->type() == Node::Document) && (node->subType() == Node::QmlClass)) {
+ if (node->isQmlType())
node->setAbstract(true);
- }
}
else {
processCommonMetaCommand(doc.location(),command,argLocPair,node);
@@ -1636,11 +1592,7 @@ bool CppCodeParser::matchBaseSpecifier(ClassNode *classe, bool isClass)
if (!matchDataType(&baseClass))
return false;
- qdb_->addBaseClass(classe,
- access,
- baseClass.toPath(),
- baseClass.toString(),
- classe->parent());
+ classe->addUnresolvedBaseClass(access, baseClass.toPath(), baseClass.toString());
return true;
}
@@ -1676,7 +1628,7 @@ bool CppCodeParser::matchClassDecl(InnerNode *parent,
while (tok == Tok_Ident)
readToken();
if (tok == Tok_Gulbrandsen) {
- Node* n = parent->findChildNodeByNameAndType(previousLexeme(),Node::Class);
+ Node* n = parent->findChildNode(previousLexeme(),Node::Class);
if (n) {
parent = static_cast<InnerNode*>(n);
if (parent) {
@@ -1735,9 +1687,8 @@ bool CppCodeParser::matchNamespaceDecl(InnerNode *parent)
*/
QString namespaceName = previousLexeme();
NamespaceNode* ns = 0;
- if (parent) {
- ns = static_cast<NamespaceNode*>(parent->findChildNodeByNameAndType(namespaceName, Node::Namespace));
- }
+ if (parent)
+ ns = static_cast<NamespaceNode*>(parent->findChildNode(namespaceName, Node::Namespace));
if (!ns) {
ns = new NamespaceNode(parent, namespaceName);
ns->setAccess(access);
@@ -1875,7 +1826,7 @@ bool CppCodeParser::matchTypedefDecl(InnerNode *parent)
if (!match(Tok_Semicolon))
return false;
- if (parent && !parent->findChildNodeByNameAndType(name, Node::Typedef)) {
+ if (parent && !parent->findChildNode(name, Node::Typedef)) {
TypedefNode* td = new TypedefNode(parent, name);
td->setAccess(access);
td->setLocation(location());
@@ -2110,7 +2061,7 @@ bool CppCodeParser::matchDeclList(InnerNode *parent)
TypedefNode *flagsNode = new TypedefNode(parent, flagsType);
flagsNode->setAccess(access);
flagsNode->setLocation(location());
- EnumNode* en = static_cast<EnumNode*>(parent->findChildNodeByNameAndType(name, Node::Enum));
+ EnumNode* en = static_cast<EnumNode*>(parent->findChildNode(name, Node::Enum));
if (en)
en->setFlagsType(flagsNode);
}
@@ -2189,9 +2140,15 @@ bool CppCodeParser::matchDocsAndStuff()
FunctionNode *func = 0;
if (matchFunctionDecl(0, &parentPath, &clone, QString(), extra)) {
- func = qdb_->findNodeInOpenNamespace(parentPath, clone);
+ func = qdb_->findFunctionNode(parentPath, clone);
+ /*
+ If the node was not found, then search for it in the
+ open C++ namespaces. We don't expect this search to
+ be necessary often. Nor do we expect it to succeed
+ very often.
+ */
if (func == 0)
- func = qdb_->findFunctionNode(parentPath, clone);
+ func = qdb_->findNodeInOpenNamespace(parentPath, clone);
if (func) {
func->borrowParameterNames(clone);
@@ -2253,8 +2210,9 @@ bool CppCodeParser::matchDocsAndStuff()
checkModuleInclusion(*n);
if ((*n)->isInnerNode() && ((InnerNode *)*n)->includes().isEmpty()) {
InnerNode *m = static_cast<InnerNode *>(*n);
- while (m->parent() != qdb_->treeRoot())
+ while (m->parent() && m->moduleName().isEmpty()) {
m = m->parent();
+ }
if (m == *n)
((InnerNode *)*n)->addInclude((*n)->name());
else
@@ -2391,7 +2349,7 @@ void CppCodeParser::instantiateIteratorMacro(const QString &container,
Tokenizer stringTokenizer(loc, latin1);
tokenizer = &stringTokenizer;
readToken();
- matchDeclList(QDocDatabase::qdocDB()->treeRoot());
+ matchDeclList(QDocDatabase::qdocDB()->primaryTreeRoot());
}
void CppCodeParser::createExampleFileNodes(DocNode *dn)
diff --git a/src/tools/qdoc/ditaxmlgenerator.cpp b/src/tools/qdoc/ditaxmlgenerator.cpp
index e3b9bdd264..c2a5cdb8b8 100644
--- a/src/tools/qdoc/ditaxmlgenerator.cpp
+++ b/src/tools/qdoc/ditaxmlgenerator.cpp
@@ -667,13 +667,12 @@ GuidMap* DitaXmlGenerator::lookupGuidMap(const QString& fileName)
}
/*!
- Traverses the database generating all the DITA XML documentation.
+ Traverses the current tree generating all the DITA XML documentation.
*/
-void DitaXmlGenerator::generateTree()
+void DitaXmlGenerator::generateDocs()
{
- qdb_->buildCollections();
if (!runPrepareOnly()) {
- Generator::generateTree();
+ Generator::generateDocs();
generateCollisionPages();
}
@@ -766,7 +765,7 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
case Atom::AutoLink:
if (!noLinks && !inLink_ && !inContents_ && !inSectionHeading_) {
const Node* node = 0;
- QString link = getLink(atom, relative, &node);
+ QString link = getAutoLink(atom, relative, &node);
if (!link.isEmpty()) {
beginLink(link);
generateLink(atom, marker);
@@ -820,7 +819,6 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
}
break;
case Atom::BriefRight:
- // if (relative->type() != Node::Document)
writeEndTag(); // </shortdesc> or </p>
if (in_para)
in_para = false;
@@ -1013,9 +1011,9 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
break;
case Atom::AnnotatedList:
{
- DocNode* dn = qdb_->getGroup(atom->string());
- if (dn)
- generateAnnotatedList(relative, marker, dn->members());
+ GroupNode* gn = qdb_->getGroup(atom->string());
+ if (gn)
+ generateAnnotatedList(relative, marker, gn->members());
}
break;
case Atom::GeneratedList:
@@ -1032,10 +1030,10 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
QString arg = atom->string().trimmed();
QString moduleName = atom->string().mid(atom->string().indexOf("classesbymodule") + 15).trimmed();
QDocDatabase* qdb = QDocDatabase::qdocDB();
- DocNode* dn = qdb->findModule(moduleName);
- if (dn) {
+ ModuleNode* mn = qdb->findModule(moduleName);
+ if (mn) {
NodeMap m;
- dn->getMemberClasses(m);
+ mn->getMemberClasses(m);
if (!m.isEmpty()) {
generateAnnotatedList(relative, marker, m);
}
@@ -1084,9 +1082,11 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
generateAnnotatedList(relative, marker, qdb_->getNamespaces());
}
else if (atom->string() == "related") {
- const DocNode *dn = static_cast<const DocNode *>(relative);
- if (dn)
- generateAnnotatedList(dn, marker, dn->members());
+ if (relative && relative->isCollectionNode()) {
+ const CollectionNode* cn = static_cast<const CollectionNode *>(relative);
+ if (cn)
+ generateAnnotatedList(cn, marker, cn->members());
+ }
}
break;
case Atom::SinceList:
@@ -1105,10 +1105,8 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
while (n != nsmap.constEnd()) {
const Node* node = n.value();
switch (node->type()) {
- case Node::Document:
- if (node->subType() == Node::QmlClass) {
- sections[QmlClass].appendMember((Node*)node);
- }
+ case Node::QmlType:
+ sections[QmlClass].appendMember((Node*)node);
break;
case Node::Namespace:
sections[Namespace].appendMember((Node*)node);
@@ -1255,8 +1253,7 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
images.append(QLatin1Char('/'));
fileName = images + atom->string();
}
- if (relative && (relative->type() == Node::Document) &&
- (relative->subType() == Node::Example)) {
+ if (relative && relative->isExample()) {
const ExampleNode* cen = static_cast<const ExampleNode*>(relative);
if (cen->imageFileName().isEmpty()) {
ExampleNode* en = const_cast<ExampleNode*>(cen);
@@ -1311,13 +1308,11 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
case Atom::Link:
{
const Node *node = 0;
- QString myLink = getLink(atom, relative, &node);
- if (myLink.isEmpty())
- myLink = getCollisionLink(atom);
- if (myLink.isEmpty() && !noLinkErrors())
+ QString link = getLink(atom, relative, &node);
+ if (link.isEmpty() && !noLinkErrors())
relative->doc().location().warning(tr("Can't link to '%1'").arg(atom->string()));
else if (!inSectionHeading_)
- beginLink(myLink);
+ beginLink(link);
skipAhead = 1;
}
break;
@@ -2051,7 +2046,7 @@ DitaXmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker)
generateLowStatusMembers(inner,marker,CodeMarker::Compat);
writeEndTag(); // </cxxClass>
}
- else if ((inner->type() == Node::Document) && (inner->subType() == Node::HeaderFile)) {
+ else if (inner->isHeaderFile()) {
const DocNode* dn = const_cast<DocNode*>(static_cast<const DocNode*>(inner));
rawTitle = inner->plainName();
fullTitle = inner->plainFullName();
@@ -2167,7 +2162,7 @@ DitaXmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker)
generateLowStatusMembers(inner,marker,CodeMarker::Compat);
writeEndTag(); // </cxxClass>
}
- else if ((inner->type() == Node::Document) && (inner->subType() == Node::QmlClass)) {
+ else if (inner->isQmlType()) {
QmlClassNode* qcn = const_cast<QmlClassNode*>(static_cast<const QmlClassNode*>(inner));
ClassNode* cn = qcn->classNode();
rawTitle = inner->plainName();
@@ -2216,6 +2211,36 @@ DitaXmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker)
}
/*!
+ Generate the DITA page for a qdoc file that doesn't map
+ to an underlying c++ file.
+ */
+void DitaXmlGenerator::generateQmlBasicTypePage(QmlBasicTypeNode* qbtn, CodeMarker* marker)
+{
+ QList<Section> sections;
+ QList<Section>::const_iterator s;
+ QString fullTitle = "QML Basic Type: " + qbtn->fullTitle();
+
+ generateHeader(qbtn, fullTitle);
+ generateBrief(qbtn, marker); // <shortdesc>
+ writeProlog(qbtn);
+
+ writeStartTag(DT_body);
+ enterSection(QString(), QString());
+
+ if (!qbtn->doc().isEmpty()) {
+ generateBody(qbtn, marker);
+ generateAlsoList(qbtn, marker);
+ }
+ leaveSection(); // </section>
+ if (!writeEndTag()) { // </body>
+ qbtn->doc().location().warning(tr("Pop of empty XML tag stack; generating DITA for '%1'").arg(qbtn->name()));
+ return;
+ }
+ writeRelatedLinks(qbtn);
+ writeEndTag(); // </topic>
+}
+
+/*!
Write a list item for a \a link with the given \a text.
*/
void DitaXmlGenerator::writeXrefListItem(const QString& link, const QString& text)
@@ -2250,10 +2275,7 @@ void DitaXmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
QList<Section>::const_iterator s;
QString fullTitle = dn->fullTitle();
- if (dn->subType() == Node::QmlBasicType) {
- fullTitle = "QML Basic Type: " + fullTitle;
- }
- else if (dn->subType() == Node::Collision) {
+ if (dn->subType() == Node::Collision) {
fullTitle = "Name Collision: " + fullTitle;
}
@@ -2263,24 +2285,6 @@ void DitaXmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
writeStartTag(DT_body);
enterSection(QString(), QString());
- if (dn->subType() == Node::Module) {
- generateStatus(dn, marker);
- NodeMap nm;
- dn->getMemberNamespaces(nm);
- if (!nm.isEmpty()) {
- enterSection("h2","Namespaces");
- generateAnnotatedList(dn, marker, nm);
- leaveSection();
- }
- nm.clear();
- dn->getMemberClasses(nm);
- if (!nm.isEmpty()) {
- enterSection("h2","Classes");
- generateAnnotatedList(dn, marker, nm);
- leaveSection();
- }
- nm.clear();
- }
if (dn->doc().isEmpty()) {
if (dn->subType() == Node::File) {
@@ -2299,23 +2303,70 @@ void DitaXmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
}
}
else {
- if (dn->subType() == Node::Module) {
+ generateBody(dn, marker);
+ generateAlsoList(dn, marker);
+ }
+ leaveSection(); // </section>
+ if (!writeEndTag()) { // </body>
+ dn->doc().location().warning(tr("Pop of empty XML tag stack; generating DITA for '%1'").arg(dn->name()));
+ return;
+ }
+ writeRelatedLinks(dn);
+ writeEndTag(); // </topic>
+}
+
+/*!
+ Generate the DITA XML file for a group, module, or QML module.
+ */
+void DitaXmlGenerator::generateCollectionNode(CollectionNode* cn, CodeMarker* marker)
+{
+ QList<Section> sections;
+ QList<Section>::const_iterator s;
+ QString fullTitle = cn->fullTitle();
+
+ generateHeader(cn, fullTitle);
+ generateBrief(cn, marker); // <shortdesc>
+ writeProlog(cn);
+
+ writeStartTag(DT_body);
+ enterSection(QString(), QString());
+ if (cn->isModule()) {
+ generateStatus(cn, marker);
+ NodeMap nm;
+ cn->getMemberNamespaces(nm);
+ if (!nm.isEmpty()) {
+ enterSection("h2","Namespaces");
+ generateAnnotatedList(cn, marker, nm);
+ leaveSection();
+ }
+ nm.clear();
+ cn->getMemberClasses(nm);
+ if (!nm.isEmpty()) {
+ enterSection("h2","Classes");
+ generateAnnotatedList(cn, marker, nm);
+ leaveSection();
+ }
+ nm.clear();
+ }
+
+ if (!cn->doc().isEmpty()) {
+ if (cn->isModule()) {
enterSection(QString(), QString());
- generateBody(dn, marker);
+ generateBody(cn, marker);
leaveSection();
}
else {
- generateBody(dn, marker);
+ generateBody(cn, marker);
}
- generateAlsoList(dn, marker);
- generateAnnotatedList(dn, marker, dn->members());
+ generateAlsoList(cn, marker);
+ generateAnnotatedList(cn, marker, cn->members());
}
leaveSection(); // </section>
if (!writeEndTag()) { // </body>
- dn->doc().location().warning(tr("Pop of empty XML tag stack; generating DITA for '%1'").arg(dn->name()));
+ cn->doc().location().warning(tr("Pop of empty XML tag stack; generating DITA for '%1'").arg(cn->name()));
return;
}
- writeRelatedLinks(dn);
+ writeRelatedLinks(cn);
writeEndTag(); // </topic>
}
@@ -2350,7 +2401,7 @@ void DitaXmlGenerator::writeLink(const Node* node,
value of the \e role attribute is \c{parent} for the
\c{start} link.
*/
-void DitaXmlGenerator::writeRelatedLinks(const DocNode* node)
+void DitaXmlGenerator::writeRelatedLinks(const Node* node)
{
const Node* linkNode = 0;
QPair<QString,QString> linkPair;
@@ -2361,7 +2412,7 @@ void DitaXmlGenerator::writeRelatedLinks(const DocNode* node)
linkNode = qdb_->findNodeForTarget(linkPair.first, node);
if (!linkNode)
node->doc().location().warning(tr("Cannot link to '%1'").arg(linkPair.first));
- if (linkNode && linkNode->type() == Node::Document) {
+ if (linkNode && linkNode->isDocNode()) {
const DocNode *docNode = static_cast<const DocNode*>(linkNode);
linkPair.second = docNode->title();
}
@@ -2372,7 +2423,7 @@ void DitaXmlGenerator::writeRelatedLinks(const DocNode* node)
linkNode = qdb_->findNodeForTarget(linkPair.first, node);
if (!linkNode)
node->doc().location().warning(tr("Cannot link to '%1'").arg(linkPair.first));
- if (linkNode && linkNode->type() == Node::Document) {
+ if (linkNode && linkNode->isDocNode()) {
const DocNode *docNode = static_cast<const DocNode*>(linkNode);
linkPair.second = docNode->title();
}
@@ -2383,7 +2434,7 @@ void DitaXmlGenerator::writeRelatedLinks(const DocNode* node)
linkNode = qdb_->findNodeForTarget(linkPair.first, node);
if (!linkNode)
node->doc().location().warning(tr("Cannot link to '%1'").arg(linkPair.first));
- if (linkNode && linkNode->type() == Node::Document) {
+ if (linkNode && linkNode->isDocNode()) {
const DocNode *docNode = static_cast<const DocNode*>(linkNode);
linkPair.second = docNode->title();
}
@@ -2405,12 +2456,9 @@ QString DitaXmlGenerator::fileExtension() const
Writes an XML file header to the current XML stream. This
depends on which kind of DITA XML file is being generated,
which is determined by the \a node type and subtype and the
- \a subpage flag. If the \subpage flag is true, a \c{<topic>}
- header is written, regardless of the type of \a node.
+ \a subpage flag.
*/
-void DitaXmlGenerator::generateHeader(const Node* node,
- const QString& name,
- bool subpage)
+void DitaXmlGenerator::generateHeader(const Node* node, const QString& name)
{
if (!node)
return;
@@ -2423,7 +2471,7 @@ void DitaXmlGenerator::generateHeader(const Node* node,
QString version;
QString outputclass;
- if (node->type() == Node::Class) {
+ if (node->isClass()) {
mainTag = DT_cxxClass;
nameTag = DT_apiName;
dtd = "dtd/cxxClass.dtd";
@@ -2432,7 +2480,7 @@ void DitaXmlGenerator::generateHeader(const Node* node,
" PUBLIC \"-//NOKIA//DTD DITA C++ API Class Reference Type v" +
version + "//EN\" \"" + dtd + "\">";
}
- else if (node->type() == Node::Namespace) {
+ else if (node->isNamespace()) {
mainTag = DT_cxxClass;
nameTag = DT_apiName;
dtd = "dtd/cxxClass.dtd";
@@ -2442,8 +2490,28 @@ void DitaXmlGenerator::generateHeader(const Node* node,
version + "//EN\" \"" + dtd + "\">";
outputclass = "namespace";
}
- else if (node->type() == Node::Document || subpage) {
- if (node->subType() == Node::HeaderFile) {
+ else if (node->isCollectionNode()) {
+ mainTag = DT_topic;
+ nameTag = DT_title;
+ dtd = "dtd/topic.dtd";
+ doctype = "<!DOCTYPE " + ditaTags[mainTag] +
+ " PUBLIC \"-//OASIS//DTD DITA Topic//EN\" \"" + dtd + "\">";
+ switch (node->type()) {
+ case Node::Group:
+ outputclass = "group";
+ break;
+ case Node::Module:
+ outputclass = "module";
+ break;
+ case Node::QmlModule:
+ outputclass = "qmlmodule";
+ break;
+ default:
+ outputclass = "page";
+ }
+ }
+ else if (node->isDocNode()) {
+ if (node->isHeaderFile()) {
mainTag = DT_cxxClass;
nameTag = DT_apiName;
dtd = "dtd/cxxClass.dtd";
@@ -2453,7 +2521,7 @@ void DitaXmlGenerator::generateHeader(const Node* node,
version + "//EN\" \"" + dtd + "\">";
outputclass = "headerfile";
}
- else if (node->subType() == Node::QmlClass) {
+ else if (node->isQmlType()) {
mainTag = DT_qmlType;
nameTag = DT_apiName;
dtd = "dtd/qmlType.dtd";
@@ -2473,9 +2541,6 @@ void DitaXmlGenerator::generateHeader(const Node* node,
case Node::Page:
outputclass = node->pageTypeString();
break;
- case Node::Group:
- outputclass = "group";
- break;
case Node::Example:
outputclass = "example";
break;
@@ -2485,9 +2550,6 @@ void DitaXmlGenerator::generateHeader(const Node* node,
case Node::Image: // not used
outputclass = "image";
break;
- case Node::Module:
- outputclass = "module";
- break;
case Node::ExternalPage: // not used
outputclass = "externalpage";
break;
@@ -2696,8 +2758,8 @@ void DitaXmlGenerator::generateClassHierarchy(const Node* relative, NodeMap& cla
NodeMap newTop;
foreach (const RelatedClass &d, child->derivedClasses()) {
- if (d.access != Node::Private && !d.node->doc().isEmpty())
- newTop.insert(d.node->name(), d.node);
+ if (d.node_ && d.access_ != Node::Private && !d.node_->doc().isEmpty())
+ newTop.insert(d.node_->name(), d.node_);
}
if (!newTop.isEmpty()) {
stack.push(newTop);
@@ -2763,7 +2825,7 @@ void DitaXmlGenerator::generateAnnotatedList(const Node* relative,
writeEndTag(); // </p>
writeEndTag(); // <entry>
- if (!(node->type() == Node::Document)) {
+ if (!node->isDocNode()) {
Text brief = node->doc().trimmedBriefText(node->name());
if (!brief.isEmpty()) {
writeStartTag(DT_entry);
@@ -2985,7 +3047,7 @@ void DitaXmlGenerator::generateCompactList(ListType , // currently not needed fo
writeHrefAttribute(linkForNode(it.value(), relative));
QStringList pieces;
- if (it.value()->subType() == Node::QmlClass)
+ if (it.value()->isQmlType())
pieces << it.value()->name();
else
pieces = it.value()->fullName(relative).split("::");
@@ -3106,100 +3168,57 @@ void DitaXmlGenerator::generateQmlItem(const Node* node,
*/
void DitaXmlGenerator::generateOverviewList(const Node* relative)
{
- QMap<const DocNode*, QMap<QString, DocNode*> > docNodeMap;
- QMap<QString, const DocNode*> groupTitlesMap;
- QMap<QString, DocNode*> uncategorizedNodeMap;
+ CNMap groups;
+ CNMap modules;
+ CNMap qmlModules;
QRegExp singleDigit("\\b([0-9])\\b");
- const NodeList children = qdb_->treeRoot()->childNodes();
- foreach (Node* child, children) {
- if (child->type() == Node::Document && child != relative) {
- DocNode* docNode = static_cast<DocNode*>(child);
-
- // Check whether the page is part of a group or is the group
- // definition page.
- QString group;
- bool isGroupPage = false;
- if (docNode->doc().metaCommandsUsed().contains("group")) {
- group = docNode->doc().metaCommandArgs("group")[0].first;
- isGroupPage = true;
- }
-
- // there are too many examples; they would clutter the list
- if (docNode->subType() == Node::Example)
- continue;
-
- // not interested either in individual (Qt Designer etc.) manual chapters
- if (docNode->links().contains(Node::ContentsLink))
- continue;
+ qdb_->mergeCollections(Node::Group, groups, relative);
+ qdb_->mergeCollections(Node::Module, modules, relative);
+ qdb_->mergeCollections(Node::QmlModule, qmlModules, relative);
- // Discard external nodes.
- if (docNode->subType() == Node::ExternalPage)
- continue;
-
- QString sortKey = docNode->fullTitle().toLower();
- if (sortKey.startsWith("the "))
- sortKey.remove(0, 4);
- sortKey.replace(singleDigit, "0\\1");
-
- if (!group.isEmpty()) {
- if (isGroupPage) {
- // If we encounter a group definition page, we add all
- // the pages in that group to the list for that group.
- foreach (Node* member, docNode->members()) {
- if (member->isInternal() || member->type() != Node::Document)
- continue;
- DocNode* page = static_cast<DocNode*>(member);
- if (page) {
- QString sortKey = page->fullTitle().toLower();
- if (sortKey.startsWith("the "))
- sortKey.remove(0, 4);
- sortKey.replace(singleDigit, "0\\1");
- docNodeMap[const_cast<const DocNode*>(docNode)].insert(sortKey, page);
- groupTitlesMap[docNode->fullTitle()] = const_cast<const DocNode*>(docNode);
- }
- }
- }
- else if (!isGroupPage) {
- // If we encounter a page that belongs to a group then
- // we add that page to the list for that group.
- const DocNode* gn = qdb_->getGroup(group);
- if (gn && !docNode->isInternal())
- docNodeMap[gn].insert(sortKey, docNode);
- }
- }
- }
- }
-
- // We now list all the pages found that belong to groups.
- // If only certain pages were found for a group, but the definition page
- // for that group wasn't listed, the list of pages will be intentionally
- // incomplete. However, if the group definition page was listed, all the
- // pages in that group are listed for completeness.
-
- if (!docNodeMap.isEmpty()) {
- foreach (const QString& groupTitle, groupTitlesMap.keys()) {
- const DocNode* groupNode = groupTitlesMap[groupTitle];
+ QStringList keys = groups.uniqueKeys();
+ foreach (QString key, keys) {
+ GroupNode* gn = static_cast<GroupNode*>(groups.value(key));
+ if (gn) {
writeStartTag(DT_p);
xmlWriter().writeAttribute("outputclass","h3");
writeStartTag(DT_xref);
// formathtml
- xmlWriter().writeAttribute("href",linkForNode(groupNode, relative));
- writeCharacters(protectEnc(groupNode->fullTitle()));
+ xmlWriter().writeAttribute("href",linkForNode(gn, relative));
+ writeCharacters(protectEnc(gn->fullTitle()));
writeEndTag(); // </xref>
writeEndTag(); // </p>
- if (docNodeMap[groupNode].count() == 0)
+
+ if (gn->members().isEmpty())
continue;
+ NodeMap nm;
+ foreach (Node* member, gn->members()) {
+ if (member->isInternal() || member->isExample() || member->isExternalPage() ||
+ member->isObsolete())
+ continue;
+ // not interested either in individual (Qt Designer etc.) manual chapters
+ if (member->links().contains(Node::ContentsLink))
+ continue;
+ QString sortKey = member->fullTitle().toLower();
+ if (sortKey.startsWith("the "))
+ sortKey.remove(0, 4);
+ sortKey.replace(singleDigit, "0\\1");
+ nm.insert(sortKey, member);
+ }
+
writeStartTag(DT_ul);
- foreach (const DocNode* docNode, docNodeMap[groupNode]) {
- QString title = docNode->fullTitle();
+ QStringList titles = nm.keys();
+ foreach (QString t, titles) {
+ Node* member = nm.value(t);
+ QString title = member->fullTitle();
if (title.startsWith("The "))
title.remove(0, 4);
writeStartTag(DT_li);
writeStartTag(DT_xref);
// formathtml
- xmlWriter().writeAttribute("href",linkForNode(docNode, relative));
+ xmlWriter().writeAttribute("href",linkForNode(member, relative));
writeCharacters(protectEnc(title));
writeEndTag(); // </xref>
writeEndTag(); // </li>
@@ -3207,27 +3226,6 @@ void DitaXmlGenerator::generateOverviewList(const Node* relative)
writeEndTag(); // </ul>
}
}
-
- if (!uncategorizedNodeMap.isEmpty()) {
- writeStartTag(DT_p);
- xmlWriter().writeAttribute("outputclass","h3");
- xmlWriter().writeCharacters("Miscellaneous");
- writeEndTag(); // </p>
- writeStartTag(DT_ul);
- foreach (const DocNode *docNode, uncategorizedNodeMap) {
- QString title = docNode->fullTitle();
- if (title.startsWith("The "))
- title.remove(0, 4);
- writeStartTag(DT_li);
- writeStartTag(DT_xref);
- // formathtml
- xmlWriter().writeAttribute("href",linkForNode(docNode, relative));
- writeCharacters(protectEnc(title));
- writeEndTag(); // </xref>
- writeEndTag(); // </li>
- }
- writeEndTag(); // </ul>
- }
}
/*!
@@ -3412,68 +3410,71 @@ void DitaXmlGenerator::writeText(const QString& markedCode, const Node* relative
for (int k = 0; k != 6; ++k) {
if (parseArg(src, markTags[k], &i, n, &arg, &par1)) {
const Node* n = 0;
- if (k == 0) { // <@link>
- if (!text.isEmpty()) {
- writeCharacters(text);
- text.clear();
- }
- n = CodeMarker::nodeForString(par1.toString());
- QString link = linkForNode(n, relative);
- addLink(link, arg);
- }
- else if (k == 4) { // <@param>
- if (!text.isEmpty()) {
- writeCharacters(text);
- text.clear();
- }
- writeStartTag(DT_i);
- //writeCharacters(" " + arg.toString());
- writeCharacters(arg.toString());
- writeEndTag(); // </i>
- }
- else if (k == 5) { // <@extra>
- if (!text.isEmpty()) {
- writeCharacters(text);
- text.clear();
- }
- writeStartTag(DT_tt);
- writeCharacters(arg.toString());
- writeEndTag(); // </tt>
- }
- else {
- if (!text.isEmpty()) {
- writeCharacters(text);
- text.clear();
- }
- par1 = QStringRef();
- QString link;
- n = qdb_->resolveTarget(arg.toString(), relative);
- if (n && n->subType() == Node::QmlBasicType) {
- if (relative && relative->subType() == Node::QmlClass) {
- link = linkForNode(n,relative);
- addLink(link, arg);
+ switch (k) {
+ case 0: // <@link>
+ if (!text.isEmpty()) {
+ writeCharacters(text);
+ text.clear();
}
- else {
- writeCharacters(arg.toString());
+ n = CodeMarker::nodeForString(par1.toString());
+ addLink(linkForNode(n, relative), arg);
+ break;
+ case 4: // <@param>
+ if (!text.isEmpty()) {
+ writeCharacters(text);
+ text.clear();
}
- }
- else {
- // (zzz) Is this correct for all cases?
- link = linkForNode(n,relative);
- addLink(link, arg);
- }
- }
+ writeStartTag(DT_i);
+ //writeCharacters(" " + arg.toString());
+ writeCharacters(arg.toString());
+ writeEndTag(); // </i>
+ break;
+ case 5: // <@extra>
+ if (!text.isEmpty()) {
+ writeCharacters(text);
+ text.clear();
+ }
+ writeStartTag(DT_tt);
+ writeCharacters(arg.toString());
+ writeEndTag(); // </tt>
+ break;
+ case 3:
+ if (!text.isEmpty()) {
+ writeCharacters(text);
+ text.clear();
+ }
+ par1 = QStringRef();
+ n = qdb_->resolveFunctionTarget(arg.toString(), relative);
+ addLink(linkForNode(n, relative), arg);
+ break;
+ case 1:
+ case 2:
+ default:
+ if (!text.isEmpty()) {
+ writeCharacters(text);
+ text.clear();
+ }
+ par1 = QStringRef();
+ n = qdb_->resolveType(arg.toString(), relative);
+ if (n && n->isQmlBasicType()) {
+ if (relative && relative->isQmlType())
+ addLink(linkForNode(n, relative), arg);
+ else
+ writeCharacters(arg.toString());
+ }
+ else
+ addLink(linkForNode(n, relative), arg); // (zzz) Is this correct for all cases?
+ break;
+ } // switch
break;
}
}
}
- else {
+ else
text += src.at(i++);
- }
}
- if (!text.isEmpty()) {
+ if (!text.isEmpty())
writeCharacters(text);
- }
}
void DitaXmlGenerator::generateLink(const Atom* atom, CodeMarker* marker)
@@ -3703,13 +3704,12 @@ QString DitaXmlGenerator::guidForNode(const Node* node)
/*!
Constructs a file name appropriate for the \a node and returns
- it. If the \a node is not a fake node, or if it is a fake node but
- it is neither an external page node nor an image node or a ditamap,
- call the Generator::fileName() function.
+ it. If the \a node is not a not an external page, an image, or
+ a ditamap, call fileName() in the base class, Generator.
*/
QString DitaXmlGenerator::fileName(const Node* node)
{
- if (node->type() == Node::Document) {
+ if (node->isDocNode()) {
if (static_cast<const DocNode*>(node)->pageType() == Node::DitaMapPage)
return node->name();
if (static_cast<const DocNode*>(node)->subType() == Node::ExternalPage)
@@ -3720,6 +3720,129 @@ QString DitaXmlGenerator::fileName(const Node* node)
return Generator::fileName(node);
}
+/*!
+ This function is called for links, i.e. for words that
+ are marked with the qdoc link command. For autolinks
+ that are not marked with the qdoc link command, qdoc
+ calls getAutoLink().
+
+ Return the link represented by the \a atom, and set \a node
+ to point to the target node for that link. \a relative points
+ to the node holding the qdoc comment where the link command
+ was found.
+ */
+QString DitaXmlGenerator::getLink(const Atom *atom, const Node *relative, const Node** node)
+{
+ if (atom->string().contains(QLatin1Char(':')) && (atom->string().startsWith("file:") ||
+ atom->string().startsWith("http:") ||
+ atom->string().startsWith("https:") ||
+ atom->string().startsWith("ftp:") ||
+ atom->string().startsWith("mailto:"))) {
+ return atom->string(); // It's some kind of protocol.
+ }
+
+ QString ref;
+ QString link;
+ QStringList path = atom->string().split("#");
+ QString first = path.first().trimmed();
+
+ *node = 0;
+ if (first.isEmpty())
+ *node = relative; // search for a target on the current page.
+ else {
+ if (first.endsWith(".html")) { // The target is an html file.
+ *node = qdb_->findNodeByNameAndType(QStringList(first), Node::Document);
+ }
+ else if (first.endsWith("()")) { // The target is a C++ function or QML method.
+ *node = qdb_->resolveFunctionTarget(first, relative);
+ }
+ else {
+ *node = qdb_->resolveTarget(first, relative);
+ if (!(*node))
+ *node = qdb_->findDocNodeByTitle(first);
+ if (!(*node)) {
+ *node = qdb_->findUnambiguousTarget(first, ref);
+ if (*node && !(*node)->url().isEmpty() && !ref.isEmpty()) {
+ QString final = (*node)->url() + "#" + ref;
+ return final;
+ }
+ }
+ }
+ }
+ if (!(*node))
+ return link; // empty
+
+ if (!(*node)->url().isEmpty())
+ return (*node)->url();
+
+ if (!path.isEmpty()) {
+ ref = qdb_->findTarget(path.first(), *node);
+ if (ref.isEmpty())
+ return link; // empty
+ }
+
+ /*
+ Given that *node is not null, we now cconstruct a link
+ to the page that *node represents, and then if we found
+ a target on that page, we connect the target to the link
+ with '#'.
+ */
+ link = linkForNode(*node, relative);
+ if (*node && (*node)->subType() == Node::Image)
+ link = "images/used-in-examples/" + link;
+ if (!ref.isEmpty())
+ link += QLatin1Char('#') + ref;
+ return link;
+}
+
+/*!
+ This function is called for autolinks, i.e. for words that
+ are not marked with the qdoc link command that qdoc has
+ reason to believe should be links. For links marked with
+ the qdoc link command, qdoc calls getLink().
+
+ Return the link represented by the \a atom, and set \a node
+ to point to the target node for that link. \a relative points
+ to the node holding the qdoc comment where the link command
+ was found.
+ */
+QString DitaXmlGenerator::getAutoLink(const Atom *atom, const Node *relative, const Node** node)
+{
+ QString ref;
+ QString link;
+ QString target = atom->string().trimmed();
+ *node = 0;
+
+ if (target.endsWith("()")) { // The target is a C++ function or QML method.
+ *node = qdb_->resolveFunctionTarget(target, relative);
+ }
+ else {
+ *node = qdb_->resolveTarget(target, relative);
+ if (!(*node)) {
+ *node = qdb_->findDocNodeByTitle(target);
+ }
+ if (!(*node)) {
+ *node = qdb_->findUnambiguousTarget(target, ref);
+ if (*node && !(*node)->url().isEmpty() && !ref.isEmpty()) {
+ QString final = (*node)->url() + "#" + ref;
+ return final;
+ }
+ }
+ }
+
+ if (!(*node))
+ return link; // empty
+
+ if (!(*node)->url().isEmpty())
+ return (*node)->url();
+
+ link = linkForNode(*node, relative);
+ if (!ref.isEmpty())
+ link += QLatin1Char('#') + ref;
+ return link;
+}
+
+
QString DitaXmlGenerator::linkForNode(const Node* node, const Node* relative)
{
if (node == 0 || node == relative)
@@ -3733,7 +3856,7 @@ QString DitaXmlGenerator::linkForNode(const Node* node, const Node* relative)
QString fn = fileName(node);
if (node && relative && node->parent() != relative) {
- if (node->parent()->subType() == Node::QmlClass && relative->subType() == Node::QmlClass) {
+ if (node->parent()->isQmlType() && relative->isQmlType()) {
if (node->parent()->isAbstract()) {
/*
This is a bit of a hack. What we discover with
@@ -3796,6 +3919,7 @@ int DitaXmlGenerator::hOffset(const Node* node)
case Node::Namespace:
case Node::Class:
return 2;
+ case Node::QmlType:
case Node::Document:
return 1;
case Node::Enum:
@@ -3829,103 +3953,6 @@ const QPair<QString,QString> DitaXmlGenerator::anchorForNode(const Node* node)
return anchorPair;
}
-QString DitaXmlGenerator::getLink(const Atom* atom, const Node* relative, const Node** node)
-{
- QString link;
- *node = 0;
- inObsoleteLink = false;
-
- if (atom->string().contains(QLatin1Char(':')) &&
- (atom->string().startsWith("file:")
- || atom->string().startsWith("http:")
- || atom->string().startsWith("https:")
- || atom->string().startsWith("ftp:")
- || atom->string().startsWith("mailto:"))) {
-
- link = atom->string();
- }
- else {
- QStringList path;
- if (atom->string().contains('#'))
- path = atom->string().split('#');
- else
- path.append(atom->string());
-
- QString ref;
- QString first = path.first().trimmed();
-
- if (first.isEmpty()) {
- *node = relative;
- }
- else if (first.endsWith(".html")) {
- *node = qdb_->treeRoot()->findChildNodeByNameAndType(first, Node::Document);
- }
- else {
- *node = qdb_->resolveTarget(first, relative);
- if (!*node)
- *node = qdb_->findDocNodeByTitle(first, relative);
- if (!*node)
- *node = qdb_->findUnambiguousTarget(first, ref, relative);
- }
-
- if (*node) {
- if (!(*node)->url().isEmpty())
- return (*node)->url();
- else
- path.removeFirst();
- }
- else
- *node = relative;
-
- if (*node && (*node)->status() == Node::Obsolete) {
- if (relative && (relative->parent() != *node) &&
- (relative->status() != Node::Obsolete)) {
- bool porting = false;
- if (relative->type() == Node::Document) {
- const DocNode* fake = static_cast<const DocNode*>(relative);
- if (fake->title().startsWith("Porting"))
- porting = true;
- }
- QString name = relative->plainFullName();
- if (!porting && !name.startsWith("Q3")) {
- if (obsoleteLinks) {
- relative->doc().location().warning(tr("Link to obsolete item '%1' in %2")
- .arg(atom->string())
- .arg(name));
- }
- inObsoleteLink = true;
- }
- }
- }
-
- while (!path.isEmpty()) {
- ref = qdb_->findTarget(path.first(), *node);
- if (ref.isEmpty())
- break;
- path.removeFirst();
- }
-
- if (path.isEmpty()) {
- link = linkForNode(*node, relative);
- if (*node && (*node)->subType() == Node::Image)
- link = "images/used-in-examples/" + link;
- if (!ref.isEmpty()) {
- if (link.isEmpty())
- link = outFileName();
- QString guid = lookupGuid(link, ref);
- link += QLatin1Char('#') + guid;
- }
- else if (!link.isEmpty() && *node && (link.endsWith(".xml") || link.endsWith(".dita"))) {
- link += QLatin1Char('#') + (*node)->guid();
- }
- }
- }
- if (!link.isEmpty() && link[0] == '#') {
- link.prepend(outFileName());
- }
- return link;
-}
-
void DitaXmlGenerator::generateStatus(const Node* node, CodeMarker* marker)
{
Text text;
@@ -4050,7 +4077,7 @@ void DitaXmlGenerator::startQmlProperty(QmlPropertyNode* qpn,
writeStartTag(DT_qmlPropertyDetail);
writeStartTag(DT_qmlPropertyDef);
if (!qpn->isReadOnlySet())
- qpn->setReadOnly(!qpn->isWritable(qdb_));
+ qpn->setReadOnly(!qpn->isWritable());
if (qpn->isReadOnly()) {
writeStartTag(DT_qmlQualifier);
xmlWriter().writeAttribute("name","read-only");
@@ -4187,11 +4214,11 @@ void DitaXmlGenerator::generateQmlModuleDef(QmlClassNode* qcn)
Output the "Inherits" line for the QML element,
if there should be one.
*/
-void DitaXmlGenerator::generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker)
+void DitaXmlGenerator::generateQmlInherits(QmlClassNode* qcn, CodeMarker* marker)
{
if (!qcn)
return;
- const QmlClassNode* base = qcn->qmlBaseNode();
+ QmlClassNode* base = qcn->qmlBaseNode();
while (base && base->isInternal()) {
base = base->qmlBaseNode();
}
@@ -4365,25 +4392,27 @@ void DitaXmlGenerator::writeDerivations(const ClassNode* cn)
writeStartTag(DT_cxxClassDerivations);
r = cn->baseClasses().constBegin();
while (r != cn->baseClasses().constEnd()) {
- writeStartTag(DT_cxxClassDerivation);
- writeStartTag(DT_cxxClassDerivationAccessSpecifier);
- xmlWriter().writeAttribute("value",(*r).accessString());
- writeEndTag(); // </cxxClassDerivationAccessSpecifier>
+ ClassNode* bcn = (*r).node_;
+ if (bcn) {
+ writeStartTag(DT_cxxClassDerivation);
+ writeStartTag(DT_cxxClassDerivationAccessSpecifier);
+ xmlWriter().writeAttribute("value",(*r).accessString());
+ writeEndTag(); // </cxxClassDerivationAccessSpecifier>
- // not included: <cxxClassDerivationVirtual>
+ // not included: <cxxClassDerivationVirtual>
- writeStartTag(DT_cxxClassBaseClass);
- QString attr = fileName((*r).node) + QLatin1Char('#') + (*r).node->guid();
- xmlWriter().writeAttribute("href",attr);
- writeCharacters((*r).node->plainFullName());
- writeEndTag(); // </cxxClassBaseClass>
+ writeStartTag(DT_cxxClassBaseClass);
+ QString attr = fileName(bcn) + QLatin1Char('#') + bcn->guid();
+ xmlWriter().writeAttribute("href",attr);
+ writeCharacters(bcn->plainFullName());
+ writeEndTag(); // </cxxClassBaseClass>
- // not included: <ClassBaseStruct> or <cxxClassBaseUnion>
+ // not included: <ClassBaseStruct> or <cxxClassBaseUnion>
- writeEndTag(); // </cxxClassDerivation>
-
- // not included: <cxxStructDerivation>
+ writeEndTag(); // </cxxClassDerivation>
+ // not included: <cxxStructDerivation>
+ }
++r;
}
writeEndTag(); // </cxxClassDerivations>
@@ -4623,10 +4652,10 @@ void DitaXmlGenerator::replaceTypesWithLinks(const Node* n, const InnerNode* par
}
i += 2;
if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) {
- const Node* tn = qdb_->resolveTarget(arg.toString(), parent, n);
+ const Node* tn = qdb_->resolveType(arg.toString(), parent);
if (tn) {
//Do not generate a link from a C++ function to a QML Basic Type (such as int)
- if (n->type() == Node::Function && tn->subType() == Node::QmlBasicType)
+ if (n->isFunction() && tn->isQmlBasicType())
writeCharacters(arg.toString());
else
addLink(linkForNode(tn,parent),arg,DT_apiRelation);
@@ -4781,12 +4810,13 @@ void DitaXmlGenerator::writeEnumerations(const Section& s,
}
// not included: <cxxEnumeratorAPIItemLocation>
-
+#if 0
if (!(*i).text().isEmpty()) {
writeStartTag(DT_apiDesc);
generateText((*i).text(), en, marker);
writeEndTag(); // </apiDesc>
}
+#endif
writeEndTag(); // <cxxEnumerator>
++i;
}
@@ -5287,7 +5317,7 @@ DitaXmlGenerator::generateInnerNode(InnerNode* node)
if (!node->url().isNull())
return;
- if (node->type() == Node::Document) {
+ if (node->isDocNode()) {
DocNode* docNode = static_cast<DocNode*>(node);
if (docNode->subType() == Node::ExternalPage)
return;
@@ -5298,7 +5328,7 @@ DitaXmlGenerator::generateInnerNode(InnerNode* node)
qDebug("PAGE %s HAS CHILDREN", qPrintable(docNode->title()));
}
}
- else if (node->type() == Node::QmlPropertyGroup)
+ else if (node->isQmlPropertyGroup())
return;
/*
@@ -5311,24 +5341,19 @@ DitaXmlGenerator::generateInnerNode(InnerNode* node)
later in generateCollisionPages(). Each one is
appended to a list for later.
*/
- if ((node->type() == Node::Document) && (node->subType() == Node::Collision)) {
+ if (node->isCollisionNode()) {
NameCollisionNode* ncn = static_cast<NameCollisionNode*>(node);
collisionNodes.append(const_cast<NameCollisionNode*>(ncn));
}
else {
if (!node->name().endsWith(".ditamap"))
beginSubPage(node, fileName(node));
- if (node->type() == Node::Namespace || node->type() == Node::Class) {
+ if (node->isNamespace() || node->isClass() || node->isQmlType() || node->isHeaderFile())
generateClassLikeNode(node, marker);
- }
- else if (node->type() == Node::Document) {
- if (node->subType() == Node::HeaderFile)
- generateClassLikeNode(node, marker);
- else if (node->subType() == Node::QmlClass)
- generateClassLikeNode(node, marker);
- else
- generateDocNode(static_cast<DocNode*>(node), marker);
- }
+ else if (node->isDocNode())
+ generateDocNode(static_cast<DocNode*>(node), marker);
+ else if (node->isQmlBasicType())
+ generateQmlBasicTypePage(static_cast<QmlBasicTypeNode*>(node), marker);
if (!node->name().endsWith(".ditamap"))
endSubPage();
}
@@ -5397,7 +5422,7 @@ Node* DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent)
QString message;
for (int i=0; i<children.size(); ++i) {
Node* child = children[i];
- if ((child->type() == Node::Document) && (child->subType() == Node::Collision)) {
+ if (child->isCollisionNode()) {
const DocNode* fake = static_cast<const DocNode*>(child);
Node* n = collectNodesByTypeAndSubtype(fake);
if (n)
@@ -5420,6 +5445,26 @@ Node* DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent)
if (!isDuplicate(nodeTypeMaps[Node::Class],child->name(),child))
nodeTypeMaps[Node::Class]->insert(child->name(),child);
break;
+ case Node::QmlType:
+ if (!isDuplicate(nodeTypeMaps[Node::QmlType],child->name(),child))
+ nodeTypeMaps[Node::QmlType]->insert(child->name(),child);
+ break;
+ case Node::QmlBasicType:
+ if (!isDuplicate(nodeTypeMaps[Node::QmlBasicType],child->title(),child))
+ nodeTypeMaps[Node::QmlBasicType]->insert(child->title(),child);
+ break;
+ case Node::Group:
+ if (!isDuplicate(nodeTypeMaps[Node::Group],child->title(),child))
+ nodeTypeMaps[Node::Group]->insert(child->title(),child);
+ break;
+ case Node::Module:
+ if (!isDuplicate(nodeTypeMaps[Node::Module],child->title(),child))
+ nodeTypeMaps[Node::Module]->insert(child->title(),child);
+ break;
+ case Node::QmlModule:
+ if (!isDuplicate(nodeTypeMaps[Node::QmlModule],child->title(),child))
+ nodeTypeMaps[Node::QmlModule]->insert(child->title(),child);
+ break;
case Node::Document:
switch (child->subType()) {
case Node::Example:
@@ -5434,14 +5479,6 @@ Node* DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent)
break;
case Node::Image:
break;
- case Node::Group:
- if (!isDuplicate(nodeSubtypeMaps[Node::Group],child->title(),child))
- nodeSubtypeMaps[Node::Group]->insert(child->title(),child);
- break;
- case Node::Module:
- if (!isDuplicate(nodeSubtypeMaps[Node::Module],child->title(),child))
- nodeSubtypeMaps[Node::Module]->insert(child->title(),child);
- break;
case Node::Page:
if (!isDuplicate(pageTypeMaps[child->pageType()],child->title(),child))
pageTypeMaps[child->pageType()]->insert(child->title(),child);
@@ -5450,18 +5487,6 @@ Node* DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent)
if (!isDuplicate(nodeSubtypeMaps[Node::ExternalPage],child->title(),child))
nodeSubtypeMaps[Node::ExternalPage]->insert(child->title(),child);
break;
- case Node::QmlClass:
- if (!isDuplicate(nodeSubtypeMaps[Node::QmlClass],child->title(),child))
- nodeSubtypeMaps[Node::QmlClass]->insert(child->title(),child);
- break;
- case Node::QmlBasicType:
- if (!isDuplicate(nodeSubtypeMaps[Node::QmlBasicType],child->title(),child))
- nodeSubtypeMaps[Node::QmlBasicType]->insert(child->title(),child);
- break;
- case Node::QmlModule:
- if (!isDuplicate(nodeSubtypeMaps[Node::QmlModule],child->title(),child))
- nodeSubtypeMaps[Node::QmlModule]->insert(child->title(),child);
- break;
case Node::Collision:
if (!isDuplicate(nodeSubtypeMaps[Node::Collision],child->title(),child))
nodeSubtypeMaps[Node::Collision]->insert(child->title(),child);
@@ -5509,7 +5534,7 @@ void DitaXmlGenerator::writeDitaMap()
Remove #if 0 to get a flat ditamap.
*/
#if 0
- beginSubPage(qdb_->treeRoot(),"qt.ditamap");
+ beginSubPage(qdb_->primaryTreeRoot(),"qt.ditamap");
doctype = "<!DOCTYPE map PUBLIC \"-//OASIS//DTD DITA Map//EN\" \"map.dtd\">";
xmlWriter().writeDTD(doctype);
writeStartTag(DT_map);
@@ -5535,9 +5560,9 @@ void DitaXmlGenerator::writeDitaMap()
nodeSubtypeMaps[i] = new NodeMultiMap;
for (unsigned i=0; i<Node::OnBeyondZebra; ++i)
pageTypeMaps[i] = new NodeMultiMap;
- Node* rootPageNode = collectNodesByTypeAndSubtype(qdb_->treeRoot());
+ Node* rootPageNode = collectNodesByTypeAndSubtype(qdb_->primaryTreeRoot());
- beginSubPage(qdb_->treeRoot(),"qt.ditamap");
+ beginSubPage(qdb_->primaryTreeRoot(),"qt.ditamap");
doctype = "<!DOCTYPE map PUBLIC \"-//OASIS//DTD DITA Map//EN\" \"map.dtd\">";
xmlWriter().writeDTD(doctype);
@@ -5565,22 +5590,26 @@ void DitaXmlGenerator::writeDitaMap()
writeTopicrefs(pageTypeMaps[Node::FAQPage], "FAQs");
writeTopicrefs(pageTypeMaps[Node::ArticlePage], "Articles");
writeTopicrefs(nodeSubtypeMaps[Node::Example], "Examples");
- if (nodeSubtypeMaps[Node::QmlModule]->size() > 1)
- writeTopicrefs(nodeSubtypeMaps[Node::QmlModule], "QML modules");
- if (nodeSubtypeMaps[Node::QmlModule]->size() == 1)
- writeTopicrefs(nodeSubtypeMaps[Node::QmlClass], "QML types", nodeSubtypeMaps[Node::QmlModule]->values()[0]);
+
+ if (nodeTypeMaps[Node::QmlModule]->size() > 1)
+ writeTopicrefs(nodeTypeMaps[Node::QmlModule], "QML modules");
+
+ if (nodeTypeMaps[Node::QmlModule]->size() == 1)
+ writeTopicrefs(nodeTypeMaps[Node::QmlType], "QML types", nodeTypeMaps[Node::QmlModule]->values()[0]);
else
- writeTopicrefs(nodeSubtypeMaps[Node::QmlClass], "QML types");
- writeTopicrefs(nodeSubtypeMaps[Node::QmlBasicType], "QML basic types");
- if (nodeSubtypeMaps[Node::Module]->size() > 1)
- writeTopicrefs(nodeSubtypeMaps[Node::Module], "Modules");
- if (nodeSubtypeMaps[Node::Module]->size() == 1)
- writeTopicrefs(nodeTypeMaps[Node::Class], "C++ classes", nodeSubtypeMaps[Node::Module]->values()[0]);
+ writeTopicrefs(nodeTypeMaps[Node::QmlType], "QML types");
+ writeTopicrefs(nodeTypeMaps[Node::QmlBasicType], "QML basic types");
+
+ if (nodeTypeMaps[Node::Module]->size() > 1)
+ writeTopicrefs(nodeTypeMaps[Node::Module], "Modules");
+
+ if (nodeTypeMaps[Node::Module]->size() == 1)
+ writeTopicrefs(nodeTypeMaps[Node::Class], "C++ classes", nodeTypeMaps[Node::Module]->values()[0]);
else
writeTopicrefs(nodeTypeMaps[Node::Class], "C++ classes");
writeTopicrefs(nodeTypeMaps[Node::Namespace], "C++ namespaces");
writeTopicrefs(nodeSubtypeMaps[Node::HeaderFile], "Header files");
- writeTopicrefs(nodeSubtypeMaps[Node::Group], "Groups");
+ writeTopicrefs(nodeTypeMaps[Node::Group], "Groups");
writeEndTag(); // </topicref>
endSubPage();
@@ -5925,30 +5954,32 @@ DitaXmlGenerator::writeProlog(const InnerNode* inner)
if (!writeMetadataElement(inner,DT_category,false)) {
writeStartTag(DT_category);
QString category = "Page";
- if (inner->type() == Node::Class)
+ if (inner->isClass())
category = "Class reference";
- else if (inner->type() == Node::Namespace)
+ if (inner->isQmlType())
+ category = "QML Reference";
+ else if (inner->isQmlBasicType())
+ category = "QML Basic Type";
+ else if (inner->isNamespace())
category = "Namespace";
- else if (inner->type() == Node::Document) {
- if (inner->subType() == Node::QmlClass)
- category = "QML Reference";
- else if (inner->subType() == Node::QmlBasicType)
- category = "QML Basic Type";
- else if (inner->subType() == Node::HeaderFile)
+ else if (inner->isModule())
+ category = "Module";
+ else if (inner->isQmlModule())
+ category = "QML Module";
+ else if (inner->isGroup())
+ category = "Group";
+ else if (inner->isDocNode()) {
+ if (inner->isHeaderFile())
category = "Header File";
- else if (inner->subType() == Node::Module)
- category = "Module";
else if (inner->subType() == Node::File)
category = "Example Source File";
- else if (inner->subType() == Node::Example)
+ else if (inner->isExample())
category = "Example";
else if (inner->subType() == Node::Image)
category = "Image";
- else if (inner->subType() == Node::Group)
- category = "Group";
else if (inner->subType() == Node::Page)
category = "Page";
- else if (inner->subType() == Node::ExternalPage)
+ else if (inner->isExternalPage())
category = "External Page"; // Is this necessary?
}
xmlWriter().writeCharacters(category);
@@ -5990,8 +6021,7 @@ DitaXmlGenerator::writeProlog(const InnerNode* inner)
xmlWriter().writeAttribute("content",i.value());
writeEndTag(); // </othermeta>
}
- if ((tagStack.first() == DT_cxxClass && !inner->includes().isEmpty()) ||
- (inner->type() == Node::Document && inner->subType() == Node::HeaderFile)) {
+ if ((tagStack.first() == DT_cxxClass && !inner->includes().isEmpty()) || inner->isHeaderFile()) {
writeStartTag(DT_othermeta);
xmlWriter().writeAttribute("name","includeFile");
QString text;
@@ -6096,7 +6126,6 @@ void DitaXmlGenerator::generateCollisionPages()
if (collisions.size() <= 1)
continue;
- ncn->clearCurrentChild();
beginSubPage(ncn, Generator::fileName(ncn));
QString fullTitle = ncn->fullTitle();
QString ditaTitle = fullTitle;
@@ -6130,7 +6159,7 @@ void DitaXmlGenerator::generateCollisionPages()
int count = 0;
for (int i=0; i<collisions.size(); ++i) {
InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
- if (n->findChildNodeByName(t.key())) {
+ if (n->findChildNode(t.key())) {
++count;
if (count > 1) {
targets.append(t.key());
@@ -6152,7 +6181,7 @@ void DitaXmlGenerator::generateCollisionPages()
writeStartTag(DT_ul);
for (int i=0; i<collisions.size(); ++i) {
InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
- Node* p = n->findChildNodeByName(*t);
+ Node* p = n->findChildNode(*t);
if (p) {
QString link = linkForNode(p,0);
QString label;
diff --git a/src/tools/qdoc/ditaxmlgenerator.h b/src/tools/qdoc/ditaxmlgenerator.h
index da05bb0274..d4264d948c 100644
--- a/src/tools/qdoc/ditaxmlgenerator.h
+++ b/src/tools/qdoc/ditaxmlgenerator.h
@@ -302,7 +302,7 @@ public:
virtual void terminateGenerator();
virtual QString format();
virtual bool canHandleFormat(const QString& format);
- virtual void generateTree();
+ virtual void generateDocs();
void generateCollisionPages();
QString protectEnc(const QString& string);
@@ -315,7 +315,9 @@ protected:
const Node* relative,
CodeMarker* marker);
virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker);
+ virtual void generateQmlBasicTypePage(QmlBasicTypeNode* qbtn, CodeMarker* marker);
virtual void generateDocNode(DocNode* dn, CodeMarker* marker);
+ virtual void generateCollectionNode(CollectionNode* cn, CodeMarker* marker);
virtual QString fileExtension() const;
virtual QString guidForNode(const Node* node);
virtual QString linkForNode(const Node* node, const Node* relative);
@@ -349,7 +351,7 @@ protected:
CodeMarker* marker,
const QString& attribute = QString());
void writePropertyParameter(const QString& tag, const NodeList& nlist);
- void writeRelatedLinks(const DocNode* dn);
+ void writeRelatedLinks(const Node* dn);
void writeLink(const Node* node, const QString& tex, const QString& role);
void writeProlog(const InnerNode* inner);
bool writeMetadataElement(const InnerNode* inner,
@@ -364,9 +366,7 @@ private:
enum SubTitleSize { SmallSubTitle, LargeSubTitle };
const QPair<QString,QString> anchorForNode(const Node* node);
- void generateHeader(const Node* node,
- const QString& name,
- bool subpage = false);
+ void generateHeader(const Node* node, const QString& name);
void generateBrief(const Node* node, CodeMarker* marker);
void generateTableOfContents(const Node* node,
CodeMarker* marker,
@@ -403,7 +403,7 @@ private:
void generateDetailedQmlMember(Node* node,
const InnerNode* relative,
CodeMarker* marker);
- void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker);
+ void generateQmlInherits(QmlClassNode* qcn, CodeMarker* marker);
void generateQmlInheritedBy(const QmlClassNode* qcn, CodeMarker* marker);
void generateQmlInstantiates(QmlClassNode* qcn, CodeMarker* marker);
void generateInstantiatedBy(ClassNode* cn, CodeMarker* marker);
@@ -425,12 +425,14 @@ private:
void generateLink(const Atom* atom, CodeMarker* marker);
void generateStatus(const Node* node, CodeMarker* marker);
+ QString getLink(const Atom *atom, const Node *relative, const Node** node);
+ QString getAutoLink(const Atom *atom, const Node *relative, const Node** node);
+
QString registerRef(const QString& ref);
virtual QString fileBase(const Node *node) const;
QString fileName(const Node *node);
static int hOffset(const Node *node);
static bool isThreeColumnEnumValueTable(const Atom *atom);
- QString getLink(const Atom *atom, const Node *relative, const Node **node);
#ifdef GENERATE_MAC_REFS
void generateMacRef(const Node* node, CodeMarker* marker);
#endif
diff --git a/src/tools/qdoc/doc.cpp b/src/tools/qdoc/doc.cpp
index 6e70671d1d..5745b094d5 100644
--- a/src/tools/qdoc/doc.cpp
+++ b/src/tools/qdoc/doc.cpp
@@ -46,6 +46,7 @@
#include "openedlist.h"
#include "quoter.h"
#include "text.h"
+#include "atom.h"
#include "tokenizer.h"
#include <qdatetime.h>
#include <qfile.h>
@@ -63,7 +64,6 @@ Q_GLOBAL_STATIC(QSet<QString>, null_Set_QString)
Q_GLOBAL_STATIC(TopicList, nullTopicList)
Q_GLOBAL_STATIC(QStringList, null_QStringList)
Q_GLOBAL_STATIC(QList<Text>, null_QList_Text)
-//Q_GLOBAL_STATIC(QStringMap, null_QStringMap)
Q_GLOBAL_STATIC(QStringMultiMap, null_QStringMultiMap)
struct Macro
@@ -316,17 +316,17 @@ Q_GLOBAL_STATIC(QHash_QString_Macro, macroHash)
class DocPrivateExtra
{
public:
- Doc::Sections granularity;
- Doc::Sections section; // ###
- QList<Atom*> tableOfContents;
- QList<int> tableOfContentsLevels;
- QList<Atom*> keywords;
- QList<Atom*> targets;
- QStringMultiMap metaMap;
+ Doc::Sections granularity_;
+ Doc::Sections section_; // ###
+ QList<Atom*> tableOfContents_;
+ QList<int> tableOfContentsLevels_;
+ QList<Atom*> keywords_;
+ QList<Atom*> targets_;
+ QStringMultiMap metaMap_;
DocPrivateExtra()
- : granularity(Doc::Part)
- , section(Doc::NoSection)
+ : granularity_(Doc::Part)
+ , section_(Doc::NoSection)
{ }
};
@@ -475,8 +475,10 @@ private:
void startSection(Doc::Sections unit, int cmd);
void endSection(int unit, int endCmd);
void parseAlso();
+ void append(const QString &string);
void append(Atom::Type type, const QString& string = QString());
void append(Atom::Type type, const QString& p1, const QString& p2);
+ void append(const QString& p1, const QString& p2);
void appendChar(QChar ch);
void appendWord(const QString &word);
void appendToCode(const QString &code);
@@ -495,6 +497,7 @@ private:
Doc::Sections getSectioningUnit();
QString getArgument(bool verbatim = false);
QString getBracedArgument(bool verbatim);
+ QString getBracketedArgument();
QString getOptionalArgument();
QString getRestOfLine();
QString getMetaCommandArgument(const QString &cmdStr);
@@ -504,6 +507,7 @@ private:
bool isBlankLine();
bool isLeftBraceAhead();
+ bool isLeftBracketAhead();
void skipSpacesOnLine();
void skipSpacesOrOneEndl();
void skipAllSpaces();
@@ -535,7 +539,7 @@ private:
int braceDepth;
int minIndent;
Doc::Sections currentSection;
- QMap<QString, Location> targetMap;
+ QMap<QString, Location> targetMap_;
QMap<int, QString> pendingFormats;
QStack<int> openedCommands;
QStack<OpenedList> openedLists;
@@ -876,11 +880,17 @@ void DocParser::parse(const QString& source,
append(Atom::SinceList, getRestOfLine().simplified());
break;
case CMD_GENERATELIST:
- append(Atom::GeneratedList, getArgument());
+ {
+ QString arg1 = getArgument();
+ QString arg2 = getOptionalArgument();
+ if (!arg2.isEmpty())
+ arg1 += " " + arg2;
+ append(Atom::GeneratedList, arg1);
+ }
break;
case CMD_GRANULARITY:
priv->constructExtra();
- priv->extra->granularity = getSectioningUnit();
+ priv->extra->granularity_ = getSectioningUnit();
break;
case CMD_HEADER:
if (openedCommands.top() == CMD_TABLE) {
@@ -959,9 +969,12 @@ void DocParser::parse(const QString& source,
break;
case CMD_L:
enterPara();
+ if (isLeftBracketAhead()) {
+ p2 = getBracketedArgument();
+ }
if (isLeftBraceAhead()) {
p1 = getArgument();
- append(Atom::Link, p1);
+ append(p1, p2);
if (isLeftBraceAhead()) {
currentLinkAtom = priv->text.lastAtom();
startFormat(ATOM_FORMATTING_LINK, cmd);
@@ -974,11 +987,12 @@ void DocParser::parse(const QString& source,
}
else {
p1 = getArgument();
- append(Atom::Link, p1);
+ append(p1, p2);
append(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
append(Atom::String, cleanLink(p1));
append(Atom::FormattingRight, ATOM_FORMATTING_LINK);
}
+ p2.clear();
break;
case CMD_LEGALESE:
leavePara();
@@ -990,7 +1004,7 @@ void DocParser::parse(const QString& source,
if (openCommand(cmd)) {
enterPara();
p1 = getArgument();
- append(Atom::Link, p1);
+ append(p1);
append(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
skipSpacesOrOneEndl();
}
@@ -1025,7 +1039,7 @@ void DocParser::parse(const QString& source,
case CMD_META:
priv->constructExtra();
p1 = getArgument();
- priv->extra->metaMap.insert(p1, getArgument());
+ priv->extra->metaMap_.insert(p1, getArgument());
break;
case CMD_NEWCODE:
location().warning(tr("Unexpected '\\%1'").arg(cmdName(CMD_NEWCODE)));
@@ -1626,8 +1640,8 @@ void DocParser::parse(const QString& source,
currentSection = Doc::NoSection;
}
- if (priv->extra && priv->extra->granularity < priv->extra->section)
- priv->extra->granularity = priv->extra->section;
+ if (priv->extra && priv->extra->granularity_ < priv->extra->section_)
+ priv->extra->granularity_ = priv->extra->section_;
priv->text.stripFirstAtom();
}
@@ -1668,18 +1682,18 @@ QString DocParser::detailsUnknownCommand(const QSet<QString> &metaCommandSet,
void DocParser::insertTarget(const QString &target, bool keyword)
{
- if (targetMap.contains(target)) {
+ if (targetMap_.contains(target)) {
location().warning(tr("Duplicate target name '%1'").arg(target));
- targetMap[target].warning(tr("(The previous occurrence is here)"));
+ targetMap_[target].warning(tr("(The previous occurrence is here)"));
}
else {
- targetMap.insert(target, location());
+ targetMap_.insert(target, location());
append(Atom::Target, target);
priv->constructExtra();
if (keyword)
- priv->extra->keywords.append(priv->text.lastAtom());
+ priv->extra->keywords_.append(priv->text.lastAtom());
else
- priv->extra->targets.append(priv->text.lastAtom());
+ priv->extra->targets_.append(priv->text.lastAtom());
}
}
@@ -1883,15 +1897,15 @@ void DocParser::startSection(Doc::Sections unit, int cmd)
if (currentSection == Doc::NoSection) {
currentSection = (Doc::Sections) (unit);
priv->constructExtra();
- priv->extra->section = currentSection;
+ priv->extra->section_ = currentSection;
}
else
endSection(unit,cmd);
append(Atom::SectionLeft, QString::number(unit));
priv->constructExtra();
- priv->extra->tableOfContents.append(priv->text.lastAtom());
- priv->extra->tableOfContentsLevels.append(unit);
+ priv->extra->tableOfContents_.append(priv->text.lastAtom());
+ priv->extra->tableOfContentsLevels_.append(unit);
enterPara(Atom::SectionHeadingLeft,
Atom::SectionHeadingRight,
QString::number(unit));
@@ -1970,6 +1984,14 @@ void DocParser::append(Atom::Type type, const QString &string)
priv->text << Atom(type, string);
}
+void DocParser::append(const QString &string)
+{
+ Atom::Type lastType = priv->text.lastAtom()->type();
+ if ((lastType == Atom::Code) && priv->text.lastAtom()->string().endsWith(QLatin1String("\n\n")))
+ priv->text.lastAtom()->chopString();
+ priv->text << Atom(string);
+}
+
void DocParser::append(Atom::Type type, const QString& p1, const QString& p2)
{
Atom::Type lastType = priv->text.lastAtom()->type();
@@ -1978,6 +2000,17 @@ void DocParser::append(Atom::Type type, const QString& p1, const QString& p2)
priv->text << Atom(type, p1, p2);
}
+void DocParser::append(const QString& p1, const QString& p2)
+{
+ Atom::Type lastType = priv->text.lastAtom()->type();
+ if ((lastType == Atom::Code) && priv->text.lastAtom()->string().endsWith(QLatin1String("\n\n")))
+ priv->text.lastAtom()->chopString();
+ if (p2.isEmpty())
+ priv->text << Atom(p1);
+ else
+ priv->text << LinkAtom(p1, p2);
+}
+
void DocParser::appendChar(QChar ch)
{
if (priv->text.lastAtom()->type() != Atom::String)
@@ -2239,10 +2272,10 @@ Doc::Sections DocParser::getSectioningUnit()
Gets an argument that is enclosed in braces and returns it
without the enclosing braces. On entry, the current character
is the left brace. On exit, the current character is the one
- that comes afterr the right brace.
+ that comes after the right brace.
If \a verbatim is true, extra whitespace is retained in the
- returned string. Otherwise, extr whitespace is removed.
+ returned string. Otherwise, extra whitespace is removed.
*/
QString DocParser::getBracedArgument(bool verbatim)
{
@@ -2373,6 +2406,47 @@ QString DocParser::getArgument(bool verbatim)
return arg.simplified();
}
+/*!
+ Gets an argument that is enclosed in brackets and returns it
+ without the enclosing brackets. On entry, the current character
+ is the left bracket. On exit, the current character is the one
+ that comes after the right bracket.
+ */
+QString DocParser::getBracketedArgument()
+{
+ QString arg;
+ int delimDepth = 0;
+ skipSpacesOrOneEndl();
+ if (pos < in.length() && in[pos] == '[') {
+ pos++;
+ while (pos < in.length() && delimDepth >= 0) {
+ switch (in[pos].unicode()) {
+ case '[':
+ delimDepth++;
+ arg += QLatin1Char('[');
+ pos++;
+ break;
+ case ']':
+ delimDepth--;
+ if (delimDepth >= 0)
+ arg += QLatin1Char(']');
+ pos++;
+ break;
+ case '\\':
+ arg += in[pos];
+ pos++;
+ break;
+ default:
+ arg += in[pos];
+ pos++;
+ }
+ }
+ if (delimDepth > 0)
+ location().warning(tr("Missing ']'"));
+ }
+ return arg;
+}
+
QString DocParser::getOptionalArgument()
{
skipSpacesOrOneEndl();
@@ -2521,6 +2595,20 @@ bool DocParser::isLeftBraceAhead()
return numEndl < 2 && i < len && in[i] == '{';
}
+bool DocParser::isLeftBracketAhead()
+{
+ int numEndl = 0;
+ int i = pos;
+
+ while (i < len && in[i].isSpace() && numEndl < 2) {
+ // ### bug with '\\'
+ if (in[i] == '\n')
+ numEndl++;
+ i++;
+ }
+ return numEndl < 2 && i < len && in[i] == '[';
+}
+
/*!
Skips to the next non-space character or EOL.
*/
@@ -2958,10 +3046,10 @@ Text Doc::legaleseText() const
Doc::Sections Doc::granularity() const
{
if (priv == 0 || priv->extra == 0) {
- return DocPrivateExtra().granularity;
+ return DocPrivateExtra().granularity_;
}
else {
- return priv->extra->granularity;
+ return priv->extra->granularity_;
}
}
@@ -3007,46 +3095,46 @@ const QList<Text> &Doc::alsoList() const
bool Doc::hasTableOfContents() const
{
- return priv && priv->extra && !priv->extra->tableOfContents.isEmpty();
+ return priv && priv->extra && !priv->extra->tableOfContents_.isEmpty();
}
bool Doc::hasKeywords() const
{
- return priv && priv->extra && !priv->extra->keywords.isEmpty();
+ return priv && priv->extra && !priv->extra->keywords_.isEmpty();
}
bool Doc::hasTargets() const
{
- return priv && priv->extra && !priv->extra->targets.isEmpty();
+ return priv && priv->extra && !priv->extra->targets_.isEmpty();
}
const QList<Atom *> &Doc::tableOfContents() const
{
priv->constructExtra();
- return priv->extra->tableOfContents;
+ return priv->extra->tableOfContents_;
}
const QList<int> &Doc::tableOfContentsLevels() const
{
priv->constructExtra();
- return priv->extra->tableOfContentsLevels;
+ return priv->extra->tableOfContentsLevels_;
}
const QList<Atom *> &Doc::keywords() const
{
priv->constructExtra();
- return priv->extra->keywords;
+ return priv->extra->keywords_;
}
const QList<Atom *> &Doc::targets() const
{
priv->constructExtra();
- return priv->extra->targets;
+ return priv->extra->targets_;
}
const QStringMultiMap &Doc::metaTagMap() const
{
- return priv && priv->extra ? priv->extra->metaMap : *null_QStringMultiMap();
+ return priv && priv->extra ? priv->extra->metaMap_ : *null_QStringMultiMap();
}
const Config* Doc::config_ = 0;
@@ -3054,10 +3142,10 @@ const Config* Doc::config_ = 0;
void Doc::initialize(const Config& config)
{
DocParser::tabSize = config.getInt(CONFIG_TABSIZE);
- DocParser::exampleFiles = config.getCleanPathList(CONFIG_EXAMPLES);
- DocParser::exampleDirs = config.getCleanPathList(CONFIG_EXAMPLEDIRS);
- DocParser::sourceFiles = config.getCleanPathList(CONFIG_SOURCES);
- DocParser::sourceDirs = config.getCleanPathList(CONFIG_SOURCEDIRS);
+ DocParser::exampleFiles = config.getCanonicalPathList(CONFIG_EXAMPLES);
+ DocParser::exampleDirs = config.getCanonicalPathList(CONFIG_EXAMPLEDIRS);
+ DocParser::sourceFiles = config.getCanonicalPathList(CONFIG_SOURCES);
+ DocParser::sourceDirs = config.getCanonicalPathList(CONFIG_SOURCEDIRS);
DocParser::quoting = config.getBool(CONFIG_QUOTINGINFORMATION);
QmlClassNode::qmlOnly = config.getBool(CONFIG_QMLONLY);
diff --git a/src/tools/qdoc/doc/config/qdoc.qdocconf b/src/tools/qdoc/doc/config/qdoc.qdocconf
index 0f4ad07711..9d841e9b64 100644
--- a/src/tools/qdoc/doc/config/qdoc.qdocconf
+++ b/src/tools/qdoc/doc/config/qdoc.qdocconf
@@ -2,7 +2,6 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = QDoc
description = QDoc Manual
-url = http://qt-project.org/doc/qt-$QT_VER
version = $QT_VERSION
sourcedirs = ..
diff --git a/src/tools/qdoc/doc/files/qtgui.qdocconf b/src/tools/qdoc/doc/files/qtgui.qdocconf
index 7f80808bfc..855ed538c2 100644
--- a/src/tools/qdoc/doc/files/qtgui.qdocconf
+++ b/src/tools/qdoc/doc/files/qtgui.qdocconf
@@ -2,7 +2,6 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = QtGui
description = Qt GUI Reference Documentation
-url = http://qt-project.org/doc/qt-$QT_VER
version = $QT_VERSION
examplesinstallpath = gui
diff --git a/src/tools/qdoc/doc/qdoc-manual-markupcmds.qdoc b/src/tools/qdoc/doc/qdoc-manual-markupcmds.qdoc
index fe43938968..c04cdeca2b 100644
--- a/src/tools/qdoc/doc/qdoc-manual-markupcmds.qdoc
+++ b/src/tools/qdoc/doc/qdoc-manual-markupcmds.qdoc
@@ -2543,6 +2543,13 @@
file or namespace documentation. See the \l {enum-command}
{\\enum} documentation for an example.
+ \note Since Qt 5.4, \\value command can also be used outside the
+ \l {enum-command} {\\enum} topic. In this case, QDoc renders a
+ two-column table listing the constant name (taken as-is from the
+ first argument) and its description. This can be used, for
+ example, in \l {qmlproperty-command}{\\qmlproperty} topic for
+ documenting acceptable values for a QML enumeration property.
+
See also \l {enum-command} {\\enum} and \l {omitvalue-command} {\\omitvalue}.
\target omitvalue-command
@@ -3251,9 +3258,9 @@
\target generatelist-command
\section1 \\generatelist
- The \\generatelist command expands to a list of various
- documentation or links to documentation. Below is an example from
- the Qt Reference Documentation:
+ The \\generatelist command expands to a list of links to the
+ documentation entities in a group. Below is an example from the Qt
+ Reference Documentation:
\code
/ *!
@@ -3263,7 +3270,7 @@
For a shorter list that only includes the most
frequently used classes, see \l{Qt's Main Classes}.
- \generatelist classes
+ \generatelist classes Q
* /
\endcode
@@ -3295,10 +3302,17 @@
of the class comment's \l {brief-command} {\\brief} command.
\target list example
- \section2 \c classes
+ \section2 \c {classes <prefix>}
The \c classes argument provides a complete alphabetical list of
- the classes. Each class name is a link to the class's reference
+ the classes. The second argument, \c{<prefix>}, is the common
+ prefix for the class names. The class names will be sorted on the
+ character that follows the common prefix. e.g. The common prefix
+ for the Qt classes is \c Q. The common prefix argument is
+ optional. If no common prefix is provided, the class names will
+ be sorted on their first character.
+
+ Each class name becomes a link to the class's reference
documentation. This command is used to generate the
\e {All Classes} page this way:
@@ -3315,7 +3329,7 @@
Classes}. For classes that have been deprecated, see the
\l{Obsolete Classes} list.
- \generatelist classes
+ \generatelist classes Q
* /
\endcode
diff --git a/src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc b/src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc
index 913f8fcc00..fee5085821 100644
--- a/src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc
+++ b/src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@@ -1331,6 +1331,13 @@
\l qtgui.qdocconf file, and it will copy those specified to the output
directory alongside the HTML pages.
+ \target HTML.tocdepth
+ \section1 HTML.tocdepth
+
+ The HTML.tocdepth variable defines how many document sections are printed in
+ the table of contents. Setting tocdepth to \c 0 disables the table of
+ contents while not setting the variable prints all document sections.
+
*/
/*!
diff --git a/src/tools/qdoc/doc/qdoc-manual-topiccmds.qdoc b/src/tools/qdoc/doc/qdoc-manual-topiccmds.qdoc
index b9667b7758..b50a343a22 100644
--- a/src/tools/qdoc/doc/qdoc-manual-topiccmds.qdoc
+++ b/src/tools/qdoc/doc/qdoc-manual-topiccmds.qdoc
@@ -1315,6 +1315,10 @@
\l {http://qt-project.org/doc/qt-4.7/qml-translate.html} {Translate}
element.
+ If the QML property is of enumeration type, or it holds a bit-wise
+ combination of flags, the \l{value-command}{\\value} command can
+ be used to document the acceptable values.
+
\target qmlsignal-command
\section1 \\qmlsignal
diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp
index 9b82e80927..6bba83efdb 100644
--- a/src/tools/qdoc/generator.cpp
+++ b/src/tools/qdoc/generator.cpp
@@ -97,26 +97,30 @@ QStringList Generator::styleDirs;
QStringList Generator::styleFiles;
bool Generator::debugging_ = false;
bool Generator::noLinkErrors_ = false;
+bool Generator::autolinkErrors_ = false;
bool Generator::redirectDocumentationToDevNull_ = false;
Generator::Passes Generator::qdocPass_ = Both;
bool Generator::useOutputSubdirs_ = true;
-void Generator::setDebugSegfaultFlag(bool b)
+void Generator::startDebugging(const QString& message)
{
- if (b)
- qDebug() << "DEBUG: Setting debug flag.";
- else
- qDebug() << "DEBUG: Clearing debug flag.";
- debugging_ = b;
+ debugging_ = true;
+ qDebug() << "START DEBUGGING:" << message;
+}
+
+void Generator::stopDebugging(const QString& message)
+{
+ debugging_ = false;
+ qDebug() << "STOP DEBUGGING:" << message;
}
/*!
Prints \a message as an aid to debugging the release version.
*/
-void Generator::debugSegfault(const QString& message)
+void Generator::debug(const QString& message)
{
if (debugging())
- qDebug() << "DEBUG:" << message;
+ qDebug() << " DEBUG:" << message;
}
/*!
@@ -189,19 +193,20 @@ void Generator::appendFullNames(Text& text, const NodeList& nodes, const Node* r
}
}
-void Generator::appendSortedNames(Text& text, const ClassNode *classe, const QList<RelatedClass> &classes)
+void Generator::appendSortedNames(Text& text, const ClassNode* cn, const QList<RelatedClass>& rc)
{
QList<RelatedClass>::ConstIterator r;
QMap<QString,Text> classMap;
int index = 0;
- r = classes.constBegin();
- while (r != classes.constEnd()) {
- if ((*r).node->access() == Node::Public &&
- (*r).node->status() != Node::Internal
- && !(*r).node->doc().isEmpty()) {
+ r = rc.constBegin();
+ while (r != rc.constEnd()) {
+ ClassNode* rcn = (*r).node_;
+ if (rcn && rcn->access() == Node::Public &&
+ rcn->status() != Node::Internal &&
+ !rcn->doc().isEmpty()) {
Text className;
- appendFullName(className, (*r).node, classe);
+ appendFullName(className, rcn, cn);
classMap[className.toString().toLower()] = className;
}
++r;
@@ -274,7 +279,7 @@ void Generator::beginSubPage(const InnerNode* node, const QString& fileName)
node->location().error(tr("HTML file already exists; overwriting %1").arg(outFile->fileName()));
if (!outFile->open(QFile::WriteOnly))
node->location().fatal(tr("Cannot open output file '%1'").arg(outFile->fileName()));
- Generator::debugSegfault("Writing: " + path);
+ Generator::debug("Writing: " + path);
outFileNames.insert(fileName,fileName);
QTextStream* out = new QTextStream(outFile);
@@ -308,47 +313,18 @@ QString Generator::fileBase(const Node *node) const
node = node->parent();
}
- if (node->type() == Node::Document && node->subType() == Node::Collision) {
- const NameCollisionNode* ncn = static_cast<const NameCollisionNode*>(node);
- if (ncn->currentChild())
- return fileBase(ncn->currentChild());
- }
-
- if (node->hasBaseName())
- return node->baseName();
+ if (node->hasFileNameBase())
+ return node->fileNameBase();
QString base;
- if (node->type() == Node::Document) {
+ if (node->isDocNode()) {
base = node->name();
- if (node->subType() == Node::Collision) {
- const NameCollisionNode* ncn = static_cast<const NameCollisionNode*>(node);
- if (ncn->currentChild())
- return fileBase(ncn->currentChild());
+ if (node->subType() == Node::Collision)
base.prepend("collision-");
- }
//Was QDOC2_COMPAT, required for index.html
if (base.endsWith(".html"))
base.truncate(base.length() - 5);
- if (node->isQmlNode()) {
- if (!node->qmlModuleName().isEmpty()) {
- base.prepend(node->qmlModuleName() + QLatin1Char('-'));
- }
- /*
- To avoid file name conflicts in the html directory,
- we prepend a prefix (by default, "qml-") to the file name of QML
- element doc files.
- */
- if ((node->subType() == Node::QmlClass) || (node->subType() == Node::QmlBasicType)) {
- base.prepend(outputPrefix(QLatin1String("QML")));
- }
- }
- else if (node->subType() == Node::QmlModule) {
- base.append("-qmlmodule");
- }
- else if (node->subType() == Node::Module) {
- base.append("-module");
- }
if (node->isExample() || node->isExampleFile()) {
QString modPrefix(node->moduleName());
if (modPrefix.isEmpty()) {
@@ -360,12 +336,37 @@ QString Generator::fileBase(const Node *node) const
base.append(QLatin1String("-example"));
}
}
+ else if (node->isQmlType() || node->isQmlBasicType()) {
+ base = node->name();
+ if (!node->qmlModuleName().isEmpty()) {
+ base.prepend(node->qmlModuleName() + QLatin1Char('-'));
+ }
+ /*
+ To avoid file name conflicts in the html directory,
+ we prepend a prefix (by default, "qml-") to the file name of QML
+ element doc files.
+ */
+ base.prepend(outputPrefix(QLatin1String("QML")));
+ }
+ else if (node->isCollectionNode()) {
+ base = node->name();
+ if (base.endsWith(".html"))
+ base.truncate(base.length() - 5);
+
+ if (node->isQmlModule()) {
+ base.append("-qmlmodule");
+ }
+ else if (node->isModule()) {
+ base.append("-module");
+ }
+ // Why not add "-group" for gropup pages?
+ }
else {
const Node *p = node;
forever {
const Node *pp = p->parent();
base.prepend(p->name());
- if (!pp || pp->name().isEmpty() || pp->type() == Node::Document)
+ if (!pp || pp->name().isEmpty() || pp->isDocNode())
break;
base.prepend(QLatin1Char('-'));
p = pp;
@@ -401,7 +402,7 @@ QString Generator::fileBase(const Node *node) const
while (res.endsWith(QLatin1Char('-')))
res.chop(1);
Node* n = const_cast<Node*>(node);
- n->setBaseName(res);
+ n->setFileNameBase(res);
return res;
}
@@ -455,7 +456,7 @@ QString Generator::fullDocumentLocation(const Node *node, bool useSubdir)
if (!fdl.isEmpty())
fdl.append(QLatin1Char('/'));
}
- if (node->type() == Node::Namespace) {
+ if (node->isNamespace()) {
// The root namespace has no name - check for this before creating
// an attribute containing the location of any documentation.
@@ -465,26 +466,23 @@ QString Generator::fullDocumentLocation(const Node *node, bool useSubdir)
else
return QString();
}
- else if (node->type() == Node::Document) {
- if ((node->subType() == Node::QmlClass) ||
- (node->subType() == Node::QmlBasicType)) {
- QString fb = fileBase(node);
- if (fb.startsWith(Generator::outputPrefix(QLatin1String("QML"))))
- return fb + QLatin1Char('.') + currentGenerator()->fileExtension();
- else {
- QString mq;
- if (!node->qmlModuleName().isEmpty()) {
- mq = node->qmlModuleName().replace(QChar('.'),QChar('-'));
- mq = mq.toLower() + QLatin1Char('-');
- }
- return fdl+ Generator::outputPrefix(QLatin1String("QML")) + mq +
- fileBase(node) + QLatin1Char('.') + currentGenerator()->fileExtension();
- }
- }
+ else if (node->isQmlType() || node->isQmlBasicType()) {
+ QString fb = fileBase(node);
+ if (fb.startsWith(Generator::outputPrefix(QLatin1String("QML"))))
+ return fb + QLatin1Char('.') + currentGenerator()->fileExtension();
else {
- parentName = fileBase(node) + QLatin1Char('.') + currentGenerator()->fileExtension();
+ QString mq;
+ if (!node->qmlModuleName().isEmpty()) {
+ mq = node->qmlModuleName().replace(QChar('.'),QChar('-'));
+ mq = mq.toLower() + QLatin1Char('-');
+ }
+ return fdl+ Generator::outputPrefix(QLatin1String("QML")) + mq +
+ fileBase(node) + QLatin1Char('.') + currentGenerator()->fileExtension();
}
}
+ else if (node->isDocNode() || node->isCollectionNode()) {
+ parentName = fileBase(node) + QLatin1Char('.') + currentGenerator()->fileExtension();
+ }
else if (fileBase(node).isEmpty())
return QString();
@@ -561,7 +559,11 @@ QString Generator::fullDocumentLocation(const Node *node, bool useSubdir)
case Node::Variable:
anchorRef = QLatin1Char('#') + node->name() + "-var";
break;
+ case Node::QmlType:
case Node::Document:
+ case Node::Group:
+ case Node::Module:
+ case Node::QmlModule:
{
parentName = fileBase(node);
parentName.replace(QLatin1Char('/'), QLatin1Char('-')).replace(QLatin1Char('.'), QLatin1Char('-'));
@@ -573,7 +575,8 @@ QString Generator::fullDocumentLocation(const Node *node, bool useSubdir)
}
// Various objects can be compat (deprecated) or obsolete.
- if (node->type() != Node::Class && node->type() != Node::Namespace) {
+ // Is this even correct?
+ if (!node->isClass() && !node->isNamespace()) {
switch (node->status()) {
case Node::Compat:
parentName.replace(QLatin1Char('.') + currentGenerator()->fileExtension(),
@@ -678,6 +681,10 @@ const Atom *Generator::generateAtomList(const Atom *atom,
return 0;
}
+/*!
+ Generate the body of the documentation from the qdoc comment
+ found with the entity represented by the \a node.
+ */
void Generator::generateBody(const Node *node, CodeMarker *marker)
{
bool quiet = false;
@@ -808,9 +815,9 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
}
}
- if (node->type() == Node::Document) {
+ if (node->isDocNode()) {
const DocNode *dn = static_cast<const DocNode *>(node);
- if (dn->subType() == Node::Example) {
+ if (dn->isExample()) {
generateExampleFiles(dn, marker);
}
else if (dn->subType() == Node::File) {
@@ -841,6 +848,10 @@ void Generator::generateDocNode(DocNode* /* dn */, CodeMarker* /* marker */)
{
}
+void Generator::generateCollectionNode(CollectionNode* , CodeMarker* )
+{
+}
+
/*!
This function is called when the documentation for an
example is being formatted. It outputs the list of source
@@ -936,18 +947,20 @@ void Generator::generateInherits(const ClassNode *classe, CodeMarker *marker)
r = classe->baseClasses().constBegin();
index = 0;
while (r != classe->baseClasses().constEnd()) {
- text << Atom(Atom::LinkNode, CodeMarker::stringForNode((*r).node))
- << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, (*r).dataTypeWithTemplateArgs)
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
-
- if ((*r).access == Node::Protected) {
- text << " (protected)";
- }
- else if ((*r).access == Node::Private) {
- text << " (private)";
+ if ((*r).node_) {
+ text << Atom(Atom::LinkNode, CodeMarker::stringForNode((*r).node_))
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << Atom(Atom::String, (*r).signature_)
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+
+ if ((*r).access_ == Node::Protected) {
+ text << " (protected)";
+ }
+ else if ((*r).access_ == Node::Private) {
+ text << " (private)";
+ }
+ text << separator(index++, classe->baseClasses().count());
}
- text << separator(index++, classe->baseClasses().count());
++r;
}
text << Atom::ParaRight;
@@ -958,6 +971,9 @@ void Generator::generateInherits(const ClassNode *classe, CodeMarker *marker)
/*!
Recursive writing of HTML files from the root \a node.
+ \note DitaXmlGenerator overrides this function, but
+ HtmlGenerator does not.
+
\note NameCollisionNodes are skipped here and processed
later. See HtmlGenerator::generateCollisionPages() for
more on this.
@@ -971,7 +987,7 @@ void Generator::generateInnerNode(InnerNode* node)
if (node->isInternal() && !showInternal_)
return;
- if (node->type() == Node::Document) {
+ if (node->isDocNode()) {
DocNode* docNode = static_cast<DocNode*>(node);
if (docNode->subType() == Node::ExternalPage)
return;
@@ -982,7 +998,7 @@ void Generator::generateInnerNode(InnerNode* node)
qDebug("PAGE %s HAS CHILDREN", qPrintable(docNode->title()));
}
}
- else if (node->type() == Node::QmlPropertyGroup)
+ else if (node->isQmlPropertyGroup())
return;
/*
@@ -996,19 +1012,61 @@ void Generator::generateInnerNode(InnerNode* node)
later in generateCollisionPages(). Each one is
appended to a list for later.
*/
- if ((node->type() == Node::Document) && (node->subType() == Node::Collision)) {
+ if (node->isCollisionNode()) {
NameCollisionNode* ncn = static_cast<NameCollisionNode*>(node);
collisionNodes.append(const_cast<NameCollisionNode*>(ncn));
}
else {
- beginSubPage(node, fileName(node));
- if (node->type() == Node::Namespace || node->type() == Node::Class) {
+ if (node->isNamespace() || node->isClass()) {
+ beginSubPage(node, fileName(node));
generateClassLikeNode(node, marker);
+ endSubPage();
}
- else if (node->type() == Node::Document) {
+ if (node->isQmlType()) {
+ beginSubPage(node, fileName(node));
+ QmlClassNode* qcn = static_cast<QmlClassNode*>(node);
+ generateQmlTypePage(qcn, marker);
+ endSubPage();
+ }
+ else if (node->isDocNode()) {
+ beginSubPage(node, fileName(node));
generateDocNode(static_cast<DocNode*>(node), marker);
+ endSubPage();
+ }
+ else if (node->isQmlBasicType()) {
+ beginSubPage(node, fileName(node));
+ QmlBasicTypeNode* qbtn = static_cast<QmlBasicTypeNode*>(node);
+ generateQmlBasicTypePage(qbtn, marker);
+ endSubPage();
+ }
+ else if (node->isCollectionNode()) {
+ CollectionNode* cn = static_cast<CollectionNode*>(node);
+ /*
+ A collection node is one of: group, module,
+ or QML module.
+
+ Don't output an HTML page for the collection
+ node unless the \group, \module, or \qmlmodule
+ command was actually seen by qdoc in the qdoc
+ comment for the node.
+
+ A key prerequisite in this case is the call to
+ mergeCollections(cn). We don't know if this
+ collection (group, module, or QML module) has
+ members in other modules. We know at this point
+ that cn's members list contains only members in
+ the current module. Therefore, before outputting
+ the page for cn, we must search for members of
+ cn in the other modules and add them to the
+ members list.
+ */
+ if (cn->wasSeen()) {
+ qdb_->mergeCollections(cn);
+ beginSubPage(node, fileName(node));
+ generateCollectionNode(cn, marker);
+ endSubPage();
+ }
}
- endSubPage();
}
}
@@ -1066,7 +1124,7 @@ void Generator::generateQmlInheritedBy(const QmlClassNode* qcn,
/*!
*/
-void Generator::generateQmlInherits(const QmlClassNode* , CodeMarker* )
+void Generator::generateQmlInherits(QmlClassNode* , CodeMarker* )
{
// stub.
}
@@ -1203,6 +1261,11 @@ void Generator::generateStatus(const Node *node, CodeMarker *marker)
generateText(text, node, marker);
}
+/*!
+ Generate the documentation for \a relative. i.e. \a relative
+ is the node that reporesentas the entity where a qdoc comment
+ was found, and \a text represents the qdoc comment.
+ */
bool Generator::generateText(const Text& text,
const Node *relative,
CodeMarker *marker)
@@ -1362,11 +1425,11 @@ void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker)
}
/*!
- Traverses the database recursivly to generate all the documentation.
+ Traverses the current tree to generate all the documentation.
*/
-void Generator::generateTree()
+void Generator::generateDocs()
{
- generateInnerNode(qdb_->treeRoot());
+ generateInnerNode(qdb_->primaryTreeRoot());
}
Generator *Generator::generatorForFormat(const QString& format)
@@ -1380,7 +1443,14 @@ Generator *Generator::generatorForFormat(const QString& format)
return 0;
}
+#if 0
/*!
+ This function might be useless now with the addition of
+ multiple node trees. It is called a few hundred times,
+ but it never finds a collision node. The single call has
+ been commented out by mws (19/05/2014). If it is no
+ longer needed, it will be removed.
+
This function can be called if getLink() returns an empty
string. It tests the \a atom string to see if it is a link
of the form <element> :: <name>, where <element> is a QML
@@ -1412,7 +1482,7 @@ QString Generator::getCollisionLink(const Atom* atom)
}
return link;
}
-
+#endif
/*!
Looks up the tag \a t in the map of metadata values for the
@@ -1546,13 +1616,13 @@ void Generator::initialize(const Config &config)
config.lastLocation().fatal(tr("Cannot create style directory '%1'").arg(outDir_ + "/style"));
}
- imageFiles = config.getCleanPathList(CONFIG_IMAGES);
- imageDirs = config.getCleanPathList(CONFIG_IMAGEDIRS);
- scriptFiles = config.getCleanPathList(CONFIG_SCRIPTS);
- scriptDirs = config.getCleanPathList(CONFIG_SCRIPTDIRS);
- styleFiles = config.getCleanPathList(CONFIG_STYLES);
- styleDirs = config.getCleanPathList(CONFIG_STYLEDIRS);
- exampleDirs = config.getCleanPathList(CONFIG_EXAMPLEDIRS);
+ imageFiles = config.getCanonicalPathList(CONFIG_IMAGES);
+ imageDirs = config.getCanonicalPathList(CONFIG_IMAGEDIRS);
+ scriptFiles = config.getCanonicalPathList(CONFIG_SCRIPTS);
+ scriptDirs = config.getCanonicalPathList(CONFIG_SCRIPTDIRS);
+ styleFiles = config.getCanonicalPathList(CONFIG_STYLES);
+ styleDirs = config.getCanonicalPathList(CONFIG_STYLEDIRS);
+ exampleDirs = config.getCanonicalPathList(CONFIG_EXAMPLEDIRS);
exampleImgExts = config.getStringList(CONFIG_EXAMPLES + Config::dot + CONFIG_IMAGEEXTENSIONS);
QString imagesDotFileExtensions = CONFIG_IMAGES + Config::dot + CONFIG_FILEEXTENSIONS;
@@ -1568,9 +1638,9 @@ void Generator::initialize(const Config &config)
if (outputFormats.contains((*g)->format())) {
currentGenerator_ = (*g);
(*g)->initializeGenerator(config);
- QStringList extraImages = config.getPathList((*g)->format() +
+ QStringList extraImages = config.getCanonicalPathList((*g)->format() +
Config::dot +
- CONFIG_EXTRAIMAGES);
+ CONFIG_EXTRAIMAGES, true);
QStringList::ConstIterator e = extraImages.constBegin();
while (e != extraImages.constEnd()) {
QString filePath = *e;
@@ -1581,7 +1651,7 @@ void Generator::initialize(const Config &config)
}
// Documentation template handling
- QStringList scripts = config.getPathList((*g)->format()+Config::dot+CONFIG_SCRIPTS);
+ QStringList scripts = config.getCanonicalPathList((*g)->format()+Config::dot+CONFIG_SCRIPTS, true);
e = scripts.constBegin();
while (e != scripts.constEnd()) {
QString filePath = *e;
@@ -1591,7 +1661,7 @@ void Generator::initialize(const Config &config)
++e;
}
- QStringList styles = config.getPathList((*g)->format()+Config::dot+CONFIG_STYLESHEETS);
+ QStringList styles = config.getCanonicalPathList((*g)->format()+Config::dot+CONFIG_STYLESHEETS, true);
e = styles.constBegin();
while (e != styles.constEnd()) {
QString filePath = *e;
@@ -1650,6 +1720,7 @@ void Generator::initialize(const Config &config)
else
outputPrefixes[QLatin1String("QML")] = QLatin1String("qml-");
noLinkErrors_ = config.getBool(CONFIG_NOLINKERRORS);
+ autolinkErrors_ = config.getBool(CONFIG_AUTOLINKERRORS);
}
/*!
@@ -1916,7 +1987,6 @@ void Generator::terminate()
imageDirs.clear();
outDir_.clear();
QmlClassNode::terminate();
- ExampleNode::terminate();
}
void Generator::terminateGenerator()
@@ -1942,17 +2012,12 @@ QString Generator::typeString(const Node *node)
return "namespace";
case Node::Class:
return "class";
+ case Node::QmlType:
+ return "type";
+ case Node::QmlBasicType:
+ return "type";
case Node::Document:
- {
- switch (node->subType()) {
- case Node::QmlClass:
- return "type";
- case Node::QmlBasicType:
- return "type";
- default:
- return "documentation";
- }
- }
+ return "documentation";
case Node::Enum:
return "enum";
case Node::Typedef:
diff --git a/src/tools/qdoc/generator.h b/src/tools/qdoc/generator.h
index b464014308..81b63ef29a 100644
--- a/src/tools/qdoc/generator.h
+++ b/src/tools/qdoc/generator.h
@@ -77,7 +77,7 @@ public:
virtual bool canHandleFormat(const QString &format) { return format == this->format(); }
virtual QString format() = 0;
- virtual void generateTree();
+ virtual void generateDocs();
virtual void initializeGenerator(const Config &config);
virtual void terminateGenerator();
@@ -92,10 +92,12 @@ public:
static void terminate();
static void writeOutFileNames();
static void augmentImageDirs(QSet<QString>& moreImageDirs);
- static void debugSegfault(const QString& message);
- static void setDebugSegfaultFlag(bool b);
+ static void debug(const QString& message);
+ static void startDebugging(const QString& message);
+ static void stopDebugging(const QString& message);
static bool debugging() { return debugging_; }
static bool noLinkErrors() { return noLinkErrors_; }
+ static bool autolinkErrors() { return autolinkErrors_; }
static void setQDocPass(Passes pass) { qdocPass_ = pass; }
static bool runPrepareOnly() { return (qdocPass_ == Prepare); }
static bool runGenerateOnly() { return (qdocPass_ == Generate); }
@@ -109,27 +111,24 @@ protected:
virtual QString fileBase(const Node* node) const;
virtual QString fileExtension() const = 0;
virtual void generateAlsoList(const Node *node, CodeMarker *marker);
- virtual int generateAtom(const Atom *atom,
- const Node *relative,
- CodeMarker *marker);
+ virtual int generateAtom(const Atom *atom, const Node *relative, CodeMarker *marker);
virtual void generateBody(const Node *node, CodeMarker *marker);
virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker);
+ virtual void generateQmlTypePage(QmlClassNode* , CodeMarker* ) { }
+ virtual void generateQmlBasicTypePage(QmlBasicTypeNode* , CodeMarker* ) { }
virtual void generateDocNode(DocNode* dn, CodeMarker* marker);
- virtual void generateInheritedBy(const ClassNode *classe,
- CodeMarker *marker);
- virtual void generateInherits(const ClassNode *classe,
- CodeMarker *marker);
+ virtual void generateCollectionNode(CollectionNode* cn, CodeMarker* marker);
+ virtual void generateInheritedBy(const ClassNode *classe, CodeMarker *marker);
+ virtual void generateInherits(const ClassNode *classe, CodeMarker *marker);
virtual void generateInnerNode(InnerNode* node);
virtual void generateMaintainerList(const InnerNode* node, CodeMarker* marker);
virtual void generateQmlInheritedBy(const QmlClassNode* qcn, CodeMarker* marker);
- virtual void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker);
+ virtual void generateQmlInherits(QmlClassNode* qcn, CodeMarker* marker);
virtual bool generateQmlText(const Text& text,
const Node *relative,
CodeMarker *marker,
const QString& qmlName);
- virtual bool generateText(const Text& text,
- const Node *relative,
- CodeMarker *marker);
+ virtual bool generateText(const Text& text, const Node *relative, CodeMarker *marker);
virtual QString imageFileName(const Node *relative, const QString& fileBase);
virtual int skipAtoms(const Atom *atom, Atom::Type type) const;
virtual QString typeString(const Node *node);
@@ -158,7 +157,7 @@ protected:
void generateSince(const Node *node, CodeMarker *marker);
void generateStatus(const Node *node, CodeMarker *marker);
void generateThreadSafeness(const Node *node, CodeMarker *marker);
- QString getCollisionLink(const Atom* atom);
+ //QString getCollisionLink(const Atom* atom);
QString getMetadataElement(const InnerNode* inner, const QString& t);
QStringList getMetadataElements(const InnerNode* inner, const QString& t);
QString indent(int level, const QString& markedCode);
@@ -219,6 +218,7 @@ private:
static QStringList styleFiles;
static bool debugging_;
static bool noLinkErrors_;
+ static bool autolinkErrors_;
static bool redirectDocumentationToDevNull_;
static Passes qdocPass_;
static bool useOutputSubdirs_;
diff --git a/src/tools/qdoc/helpprojectwriter.cpp b/src/tools/qdoc/helpprojectwriter.cpp
index d46f887518..a1121a95cb 100644
--- a/src/tools/qdoc/helpprojectwriter.cpp
+++ b/src/tools/qdoc/helpprojectwriter.cpp
@@ -131,22 +131,23 @@ void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList
typeHash["function"] = Node::Function;
typeHash["property"] = Node::Property;
typeHash["variable"] = Node::Variable;
+ typeHash["group"] = Node::Group;
+ typeHash["module"] = Node::Module;
+ typeHash["qmlmodule"] = Node::QmlModule;
typeHash["qmlproperty"] = Node::QmlProperty;
typeHash["qmlsignal"] = Node::QmlSignal;
typeHash["qmlsignalhandler"] = Node::QmlSignalHandler;
typeHash["qmlmethod"] = Node::QmlMethod;
typeHash["qmlpropertygroup"] = Node::QmlPropertyGroup;
+ typeHash["qmlclass"] = Node::QmlType;
+ typeHash["qmlbasictype"] = Node::QmlBasicType;
QHash<QString, Node::SubType> subTypeHash;
subTypeHash["example"] = Node::Example;
subTypeHash["headerfile"] = Node::HeaderFile;
subTypeHash["file"] = Node::File;
- subTypeHash["group"] = Node::Group;
- subTypeHash["module"] = Node::Module;
subTypeHash["page"] = Node::Page;
subTypeHash["externalpage"] = Node::ExternalPage;
- subTypeHash["qmlclass"] = Node::QmlClass;
- subTypeHash["qmlbasictype"] = Node::QmlBasicType;
QSet<Node::SubType> allSubTypes = QSet<Node::SubType>::fromList(subTypeHash.values());
@@ -210,16 +211,14 @@ QStringList HelpProjectWriter::keywordDetails(const Node *node) const
// "id"
details << node->parent()->name()+"::"+node->name();
}
- else if (node->type() == Node::Document) {
+ else if (node->isQmlType() || node->isQmlBasicType()) {
+ details << node->name();
+ details << "QML." + node->name();
+ }
+ else if (node->isDocNode()) {
const DocNode *fake = static_cast<const DocNode *>(node);
- if (fake->subType() == Node::QmlClass) {
- details << (QmlClassNode::qmlOnly ? fake->name() : fake->fullTitle());
- details << "QML." + fake->name();
- }
- else {
- details << fake->fullTitle();
- details << fake->fullTitle();
- }
+ details << fake->fullTitle();
+ details << fake->fullTitle();
}
else {
details << node->name();
@@ -247,7 +246,7 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
return false;
QString objName;
- if (node->type() == Node::Document) {
+ if (node->isDocNode()) {
const DocNode *fake = static_cast<const DocNode *>(node);
objName = fake->fullTitle();
}
@@ -287,6 +286,25 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
project.keywords.append(keywordDetails(node));
project.files.insert(gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()));
break;
+ case Node::QmlType:
+ case Node::QmlBasicType:
+ if (node->doc().hasKeywords()) {
+ foreach (const Atom* keyword, node->doc().keywords()) {
+ if (!keyword->string().isEmpty()) {
+ QStringList details;
+ details << keyword->string()
+ << keyword->string()
+ << gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()) +
+ QLatin1Char('#') + Doc::canonicalTitle(keyword->string());
+ project.keywords.append(details);
+ }
+ else
+ node->doc().location().warning(tr("Bad keyword in %1").arg(gen_->fullDocumentLocation(node,Generator::useOutputSubdirs())));
+ }
+ }
+ project.keywords.append(keywordDetails(node));
+ project.files.insert(gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()));
+ break;
case Node::Namespace:
project.keywords.append(keywordDetails(node));
@@ -316,6 +334,34 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
}
break;
+ case Node::Group:
+ case Node::Module:
+ case Node::QmlModule:
+ {
+ const CollectionNode* cn = static_cast<const CollectionNode*>(node);
+ if (!cn->fullTitle().isEmpty()) {
+ if (cn->doc().hasKeywords()) {
+ foreach (const Atom* keyword, cn->doc().keywords()) {
+ if (!keyword->string().isEmpty()) {
+ QStringList details;
+ details << keyword->string()
+ << keyword->string()
+ << gen_->fullDocumentLocation(node, Generator::useOutputSubdirs()) +
+ QLatin1Char('#') + Doc::canonicalTitle(keyword->string());
+ project.keywords.append(details);
+ }
+ else
+ cn->doc().location().warning(
+ tr("Bad keyword in %1").arg(gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()))
+ );
+ }
+ }
+ project.keywords.append(keywordDetails(node));
+ project.files.insert(gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()));
+ }
+ }
+ break;
+
case Node::Property:
case Node::QmlProperty:
case Node::QmlSignal:
@@ -529,17 +575,14 @@ void HelpProjectWriter::addMembers(HelpProject &project, QXmlStreamWriter &write
if (href.isEmpty())
return;
- Node::SubType subType = static_cast<const DocNode*>(node)->subType();
-
bool derivedClass = false;
if (node->type() == Node::Class)
derivedClass = !(static_cast<const ClassNode *>(node)->baseClasses().isEmpty());
// Do not generate a 'List of all members' for namespaces or header files,
// but always generate it for derived classes and QML classes
- if (node->type() != Node::Namespace && subType != Node::HeaderFile &&
- (derivedClass || subType == Node::QmlClass ||
- !project.memberStatus[node].isEmpty())) {
+ if (!node->isNamespace() && !node->isHeaderFile() &&
+ (derivedClass || node->isQmlType() || !project.memberStatus[node].isEmpty())) {
QString membersPath = href + QStringLiteral("-members.html");
project.files.insert(membersPath);
if (writeSections)
@@ -583,6 +626,14 @@ void HelpProjectWriter::writeNode(HelpProject &project, QXmlStreamWriter &writer
writeSection(writer, href, objName);
break;
+ case Node::QmlType:
+ writer.writeStartElement("section");
+ writer.writeAttribute("ref", href);
+ writer.writeAttribute("title", tr("%1 Type Reference").arg(node->fullTitle()));
+ addMembers(project, writer, node);
+ writer.writeEndElement(); // section
+ break;
+
case Node::Document: {
// Document nodes (such as manual pages) contain subtypes, titles and other
// attributes.
@@ -590,17 +641,25 @@ void HelpProjectWriter::writeNode(HelpProject &project, QXmlStreamWriter &writer
writer.writeStartElement("section");
writer.writeAttribute("ref", href);
- if (docNode->subType() == Node::QmlClass)
- writer.writeAttribute("title", tr("%1 Type Reference").arg(docNode->fullTitle()));
- else
- writer.writeAttribute("title", docNode->fullTitle());
+ writer.writeAttribute("title", docNode->fullTitle());
- if ((docNode->subType() == Node::HeaderFile) || (docNode->subType() == Node::QmlClass))
+ if (docNode->subType() == Node::HeaderFile)
addMembers(project, writer, node);
writer.writeEndElement(); // section
}
break;
+ case Node::Group:
+ case Node::Module:
+ case Node::QmlModule:
+ {
+ const CollectionNode* cn = static_cast<const CollectionNode*>(node);
+ writer.writeStartElement("section");
+ writer.writeAttribute("ref", href);
+ writer.writeAttribute("title", cn->fullTitle());
+ writer.writeEndElement(); // section
+ }
+ break;
default:
;
}
@@ -612,7 +671,7 @@ void HelpProjectWriter::generateProject(HelpProject &project)
if (!project.indexRoot.isEmpty())
rootNode = qdb_->findDocNodeByTitle(project.indexRoot);
else
- rootNode = qdb_->treeRoot();
+ rootNode = qdb_->primaryTreeRoot();
if (!rootNode)
return;
@@ -655,7 +714,7 @@ void HelpProjectWriter::generateProject(HelpProject &project)
writer.writeStartElement("section");
const Node* node = qdb_->findDocNodeByTitle(project.indexTitle);
if (node == 0)
- node = qdb_->findNode(QStringList("index.html"));
+ node = qdb_->findNodeByNameAndType(QStringList("index.html"), Node::Document);
QString indexPath;
// Never use a collision node as a landing page
if (node && !node->isCollisionNode())
diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp
index d1bf34f8e1..3a4ef31a2a 100644
--- a/src/tools/qdoc/htmlgenerator.cpp
+++ b/src/tools/qdoc/htmlgenerator.cpp
@@ -169,6 +169,9 @@ void HtmlGenerator::initializeGenerator(const Config &config)
noNavigationBar = config.getBool(HtmlGenerator::format() +
Config::dot +
HTMLGENERATOR_NONAVIGATIONBAR);
+ tocDepth = config.getInt(HtmlGenerator::format() +
+ Config::dot +
+ HTMLGENERATOR_TOCDEPTH);
project = config.getString(CONFIG_PROJECT);
@@ -264,16 +267,15 @@ QString HtmlGenerator::format()
}
/*!
- Traverses the database generating all the HTML documentation.
+ Traverses the current tree generating all the HTML documentation.
*/
-void HtmlGenerator::generateTree()
+void HtmlGenerator::generateDocs()
{
- qdb_->buildCollections();
- Node* qflags = qdb_->findNodeByNameAndType(QStringList("QFlags"), Node::Class, Node::NoSubType);
+ Node* qflags = qdb_->findClassNode(QStringList("QFlags"));
if (qflags)
qflagsHref_ = linkForNode(qflags,0);
if (!runPrepareOnly()) {
- Generator::generateTree();
+ Generator::generateDocs();
generateCollisionPages();
}
@@ -304,9 +306,6 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
int skipAhead = 0;
static bool in_para = false;
- if (Generator::debugging()) {
- atom->dump();
- }
switch (atom->type()) {
case Atom::AbstractLeft:
if (relative)
@@ -319,15 +318,22 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
case Atom::AutoLink:
if (!inLink_ && !inContents_ && !inSectionHeading_) {
const Node *node = 0;
- QString link = getLink(atom, relative, &node);
- if (!link.isEmpty()) {
+ QString link = getAutoLink(atom, relative, &node);
+ if (link.isEmpty()) {
+ if (autolinkErrors())
+ relative->doc().location().warning(tr("Can't autolink to '%1'").arg(atom->string()));
+ }
+ else if (node && node->status() == Node::Obsolete) {
+ if ((relative->parent() != node) && !relative->isObsolete())
+ link.clear();
+ }
+ if (link.isEmpty())
+ out() << protectEnc(atom->string());
+ else {
beginLink(link, node, relative);
generateLink(atom, marker);
endLink();
}
- else {
- out() << protectEnc(atom->string());
- }
}
else {
out() << protectEnc(atom->string());
@@ -336,11 +342,10 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
case Atom::BaseName:
break;
case Atom::BriefLeft:
- if (relative->type() == Node::Document) {
- if (relative->subType() != Node::Example) {
- skipAhead = skipAtoms(atom, Atom::BriefRight);
- break;
- }
+ //do not output the brief for QML basic types and doc nodes (including examples).
+ if (relative->isQmlBasicType() || relative->isDocNode()) {
+ skipAhead = skipAtoms(atom, Atom::BriefRight);
+ break;
}
out() << "<p>";
@@ -374,7 +379,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
}
break;
case Atom::BriefRight:
- if (relative->type() != Node::Document)
+ if (!relative->isDocNode())
out() << "</p>\n";
break;
case Atom::C:
@@ -485,9 +490,9 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
break;
case Atom::AnnotatedList:
{
- DocNode* dn = qdb_->getGroup(atom->string());
- if (dn)
- generateAnnotatedList(relative, marker, dn->members());
+ GroupNode* gn = qdb_->getGroup(atom->string());
+ if (gn)
+ generateList(gn, marker, atom->string());
}
break;
case Atom::GeneratedList:
@@ -495,19 +500,25 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
generateAnnotatedList(relative, marker, qdb_->getCppClasses());
}
else if (atom->string() == "classes") {
- generateCompactList(Generic, relative, qdb_->getCppClasses(), true, QStringLiteral("Q"));
+ generateCompactList(Generic, relative, qdb_->getCppClasses(), true, QStringLiteral(""));
+ }
+ else if (atom->string().contains("classes ")) {
+ QString rootName = atom->string().mid(atom->string().indexOf("classes") + 7).trimmed();
+ generateCompactList(Generic, relative, qdb_->getCppClasses(), true, rootName);
+ }
+ else if (atom->string() == "qmlbasictypes") {
+ generateCompactList(Generic, relative, qdb_->getQmlBasicTypes(), true, QStringLiteral(""));
}
else if (atom->string() == "qmltypes") {
generateCompactList(Generic, relative, qdb_->getQmlTypes(), true, QStringLiteral(""));
}
else if (atom->string().contains("classesbymodule")) {
- QString arg = atom->string().trimmed();
QString moduleName = atom->string().mid(atom->string().indexOf("classesbymodule") + 15).trimmed();
QDocDatabase* qdb = QDocDatabase::qdocDB();
- DocNode* dn = qdb->findModule(moduleName);
- if (dn) {
+ ModuleNode* mn = qdb->findModule(moduleName);
+ if (mn) {
NodeMap m;
- dn->getMemberClasses(m);
+ mn->getMemberClasses(m);
if (!m.isEmpty()) {
generateAnnotatedList(relative, marker, m);
}
@@ -550,16 +561,25 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
generateCompactList(Generic, relative, qdb_->getServiceClasses(), false, QStringLiteral("Q"));
}
else if (atom->string() == "overviews") {
- generateOverviewList(relative);
+ generateList(relative, marker, "overviews");
+ }
+ else if (atom->string() == "cpp-modules") {
+ generateList(relative, marker, "cpp-modules");
+ }
+ else if (atom->string() == "qml-modules") {
+ generateList(relative, marker, "qml-modules");
}
else if (atom->string() == "namespaces") {
generateAnnotatedList(relative, marker, qdb_->getNamespaces());
}
else if (atom->string() == "related") {
- const DocNode *dn = static_cast<const DocNode *>(relative);
- if (dn)
- generateAnnotatedList(dn, marker, dn->members());
+ generateList(relative, marker, "related");
}
+#if 0
+ /*
+ This is not used in Qt5, as of 10/02/2014
+ Remove permanently if it is not missed.
+ */
else if (atom->string() == "relatedinline") {
const DocNode *dn = static_cast<const DocNode *>(relative);
if (dn && !dn->members().isEmpty()) {
@@ -573,6 +593,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
generateBody(node, marker);
}
}
+#endif
break;
case Atom::SinceList:
{
@@ -591,10 +612,8 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
while (n != nsmap.constEnd()) {
const Node* node = n.value();
switch (node->type()) {
- case Node::Document:
- if (node->subType() == Node::QmlClass) {
- sections[QmlClass].appendMember((Node*)node);
- }
+ case Node::QmlType:
+ sections[QmlClass].appendMember((Node*)node);
break;
case Node::Namespace:
sections[Namespace].appendMember((Node*)node);
@@ -750,8 +769,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
out() << " alt=\"\"";
out() << " />";
helpProjectWriter->addExtraFile(fileName);
- if ((relative->type() == Node::Document) &&
- (relative->subType() == Node::Example)) {
+ if (relative->isExample()) {
const ExampleNode* cen = static_cast<const ExampleNode*>(relative);
if (cen->imageFileName().isEmpty()) {
ExampleNode* en = const_cast<ExampleNode*>(cen);
@@ -794,17 +812,26 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
break;
case Atom::Link:
{
+ inObsoleteLink = false;
const Node *node = 0;
- QString myLink = getLink(atom, relative, &node);
- if (myLink.isEmpty()) {
- myLink = getCollisionLink(atom);
- if (myLink.isEmpty() && !noLinkErrors()) {
- relative->doc().location().warning(tr("Can't link to '%1'").arg(atom->string()));
+ QString link = getLink(atom, relative, &node);
+ if (link.isEmpty() && !noLinkErrors()) {
+ relative->doc().location().warning(tr("Can't link to '%1'").arg(atom->string()));
+ }
+ else {
+ node = 0;
+ if (node && node->status() == Node::Obsolete) {
+ if ((relative->parent() != node) && !relative->isObsolete()) {
+ inObsoleteLink = true;
+ if (obsoleteLinks) {
+ relative->doc().location().warning(tr("Link to obsolete item '%1' in %2")
+ .arg(atom->string())
+ .arg(relative->plainFullName()));
+ }
+ }
}
- else
- node = 0;
}
- beginLink(myLink, node, relative);
+ beginLink(link, node, relative);
skipAhead = 1;
}
break;
@@ -827,21 +854,24 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
out() << "<dl>\n";
}
else if (atom->string() == ATOM_LIST_VALUE) {
+ out() << "<table class=\"valuelist\">";
threeColumnEnumValueTable_ = isThreeColumnEnumValueTable(atom);
if (threeColumnEnumValueTable_) {
- out() << "<table class=\"valuelist\">";
if (++numTableRows_ % 2 == 1)
out() << "<tr valign=\"top\" class=\"odd\">";
else
out() << "<tr valign=\"top\" class=\"even\">";
- out() << "<th class=\"tblConst\">Constant</th>"
- << "<th class=\"tblval\">Value</th>"
- << "<th class=\"tbldscr\">Description</th></tr>\n";
+ out() << "<th class=\"tblConst\">Constant</th>";
+
+ // If not in \enum topic, skip the value column
+ if (relative->type() == Node::Enum)
+ out() << "<th class=\"tblval\">Value</th>";
+
+ out() << "<th class=\"tbldscr\">Description</th></tr>\n";
}
else {
- out() << "<table class=\"valuelist\">"
- << "<tr><th class=\"tblConst\">Constant</th><th class=\"tblVal\">Value</th></tr>\n";
+ out() << "<tr><th class=\"tblConst\">Constant</th><th class=\"tblVal\">Value</th></tr>\n";
}
}
else {
@@ -876,19 +906,18 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
// ### Trenton
QString t= protectEnc(plainCode(marker->markedUpEnumValue(atom->next()->string(),relative)));
- out() << "<tr><td class=\"topAlign\"><tt>" << t << "</tt></td><td class=\"topAlign\">";
+ out() << "<tr><td class=\"topAlign\"><tt>" << t << "</tt>";
- QString itemValue;
if (relative->type() == Node::Enum) {
+ out() << "</td><td class=\"topAlign\">";
const EnumNode *enume = static_cast<const EnumNode *>(relative);
- itemValue = enume->itemValue(atom->next()->string());
- }
-
- if (itemValue.isEmpty())
- out() << '?';
- else
- out() << "<tt>" << protectEnc(itemValue) << "</tt>";
+ QString itemValue = enume->itemValue(atom->next()->string());
+ if (itemValue.isEmpty())
+ out() << '?';
+ else
+ out() << "<tt>" << protectEnc(itemValue) << "</tt>";
+ }
skipAhead = 1;
}
break;
@@ -1117,7 +1146,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
}
/*!
- Generate a reference page for a C++ class.
+ Generate a reference page for a C++ class or a C++ namespace.
*/
void HtmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker)
{
@@ -1304,6 +1333,97 @@ void HtmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker)
}
/*!
+ Generate the HTML page for a QML type. \qcn is the QML type.
+ \marker is the code markeup object.
+ */
+void HtmlGenerator::generateQmlTypePage(QmlClassNode* qcn, CodeMarker* marker)
+{
+ SubTitleSize subTitleSize = LargeSubTitle;
+ QList<Section>::const_iterator s;
+ QString htmlTitle = qcn->fullTitle() + " QML Type";
+
+ generateHeader(htmlTitle, qcn, marker);
+ QList<Section> sections = marker->qmlSections(qcn, CodeMarker::Summary);
+ generateTableOfContents(qcn, marker, &sections);
+ marker = CodeMarker::markerForLanguage(QLatin1String("QML"));
+ generateTitle(htmlTitle, Text() << qcn->subTitle(), subTitleSize, qcn, marker);
+ generateBrief(qcn, marker);
+ generateQmlRequisites(qcn, marker);
+
+ QString allQmlMembersLink = generateAllQmlMembersFile(qcn, marker);
+ if (!allQmlMembersLink.isEmpty()) {
+ out() << "<ul>\n";
+ out() << "<li><a href=\"" << allQmlMembersLink << "\">"
+ << "List of all members, including inherited members</a></li>\n";
+ out() << "</ul>\n";
+ }
+
+ s = sections.constBegin();
+ while (s != sections.constEnd()) {
+ out() << "<a name=\"" << registerRef((*s).name.toLower())
+ << "\"></a>" << divNavTop << '\n';
+ out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
+ generateQmlSummary(*s, qcn, marker);
+ ++s;
+ }
+
+ generateExtractionMark(qcn, DetailedDescriptionMark);
+ out() << "<a name=\"" << registerRef("details") << "\"></a>" << divNavTop << '\n';
+ out() << "<h2>" << "Detailed Description" << "</h2>\n";
+ generateBody(qcn, marker);
+ ClassNode* cn = qcn->classNode();
+ if (cn)
+ generateQmlText(cn->doc().body(), cn, marker, qcn->name());
+ generateAlsoList(qcn, marker);
+ generateExtractionMark(qcn, EndMark);
+ //out() << "<hr />\n";
+
+ sections = marker->qmlSections(qcn,CodeMarker::Detailed);
+ s = sections.constBegin();
+ while (s != sections.constEnd()) {
+ out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
+ NodeList::ConstIterator m = (*s).members.constBegin();
+ while (m != (*s).members.constEnd()) {
+ generateDetailedQmlMember(*m, qcn, marker);
+ out() << "<br/>\n";
+ ++m;
+ }
+ ++s;
+ }
+ generateFooter(qcn);
+}
+
+/*!
+ Generate the HTML page for the QML basic type represented
+ by the QML basic type node \a qbtn.
+ */
+void HtmlGenerator::generateQmlBasicTypePage(QmlBasicTypeNode* qbtn, CodeMarker* marker)
+{
+ SubTitleSize subTitleSize = LargeSubTitle;
+ QList<Section>::const_iterator s;
+ QString htmlTitle = qbtn->fullTitle() + " QML Basic Type";
+
+ marker = CodeMarker::markerForLanguage(QLatin1String("QML"));
+
+ generateHeader(htmlTitle, qbtn, marker);
+ QList<Section> sections = marker->sections(qbtn, CodeMarker::Summary, CodeMarker::Okay);
+ generateTableOfContents(qbtn,marker,&sections);
+ generateTitle(htmlTitle,
+ Text() << qbtn->subTitle(),
+ subTitleSize,
+ qbtn,
+ marker);
+ generateExtractionMark(qbtn, DetailedDescriptionMark);
+ out() << "<div class=\"descr\"> <a name=\"" << registerRef("details") << "\"></a>\n"; // QTBUG-9504
+
+ generateBody(qbtn, marker);
+ out() << "</div>\n"; // QTBUG-9504
+ generateAlsoList(qbtn, marker);
+ generateExtractionMark(qbtn, EndMark);
+ generateFooter(qbtn);
+}
+
+/*!
We delayed generation of the disambiguation pages until now, after
all the other pages have been generated. We do this because we might
encounter a link command that tries to link to a target on a QML
@@ -1341,7 +1461,6 @@ void HtmlGenerator::generateCollisionPages()
if (collisions.size() <= 1)
continue;
- ncn->clearCurrentChild();
beginSubPage(ncn, Generator::fileName(ncn));
QString fullTitle = ncn->fullTitle();
CodeMarker* marker = CodeMarker::markerForFileName(ncn->location().filePath());
@@ -1373,7 +1492,7 @@ void HtmlGenerator::generateCollisionPages()
int count = 0;
for (int i=0; i<collisions.size(); ++i) {
InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
- if (n->findChildNodeByName(t.key())) {
+ if (n->findChildNode(t.key())) {
++count;
if (count > 1) {
targets.append(t.key());
@@ -1392,7 +1511,7 @@ void HtmlGenerator::generateCollisionPages()
out() << "<ul>\n";
for (int i=0; i<collisions.size(); ++i) {
InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
- Node* p = n->findChildNodeByName(*t);
+ Node* p = n->findChildNode(*t);
if (p) {
QString link = linkForNode(p,0);
QString label;
@@ -1437,31 +1556,14 @@ void HtmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
QList<Section>::const_iterator s;
QString fullTitle = dn->fullTitle();
- if (dn->subType() == Node::QmlBasicType) {
- fullTitle = "QML Basic Type: " + fullTitle;
-
- // Replace the marker with a QML code marker.
- marker = CodeMarker::markerForLanguage(QLatin1String("QML"));
- }
- else if (dn->subType() == Node::QmlClass) {
- fullTitle = fullTitle + " QML Type";
- }
-
generateHeader(fullTitle, dn, marker);
/*
Generate the TOC for the new doc format.
Don't generate a TOC for the home page.
*/
- QmlClassNode* qml_cn = 0;
- if (dn->subType() == Node::QmlClass) {
- qml_cn = static_cast<QmlClassNode*>(dn);
- sections = marker->qmlSections(qml_cn,CodeMarker::Summary);
- generateTableOfContents(dn,marker,&sections);
-
- // Replace the marker with a QML code marker.
- marker = CodeMarker::markerForLanguage(QLatin1String("QML"));
- }
- else if (dn->subType() != Node::Collision && dn->name() != QString("index.html") && dn->name() != QString("qtexamplesandtutorials.html"))
+ if ((dn->subType() != Node::Collision) &&
+ (dn->name() != QString("index.html")) &&
+ (dn->name() != QString("qtexamplesandtutorials.html")))
generateTableOfContents(dn,marker,0);
generateTitle(fullTitle,
@@ -1470,29 +1572,7 @@ void HtmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
dn,
marker);
- if (dn->subType() == Node::Module) {
- // Generate brief text and status for modules.
- generateBrief(dn, marker);
- generateStatus(dn, marker);
- generateSince(dn, marker);
-
- NodeMap nm;
- dn->getMemberNamespaces(nm);
- if (!nm.isEmpty()) {
- out() << "<a name=\"" << registerRef("namespaces") << "\"></a>" << divNavTop << '\n';
- out() << "<h2>Namespaces</h2>\n";
- generateAnnotatedList(dn, marker, nm);
- }
- nm.clear();
- dn->getMemberClasses(nm);
- if (!nm.isEmpty()) {
- out() << "<a name=\"" << registerRef("classes") << "\"></a>" << divNavTop << '\n';
- out() << "<h2>Classes</h2>\n";
- generateAnnotatedList(dn, marker, nm);
- }
- nm.clear();
- }
- else if (dn->subType() == Node::HeaderFile) {
+ if (dn->subType() == Node::HeaderFile) {
// Generate brief text and status for modules.
generateBrief(dn, marker);
generateStatus(dn, marker);
@@ -1522,88 +1602,109 @@ void HtmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
out() << "</ul>\n";
}
- else if (dn->subType() == Node::QmlClass) {
- const_cast<DocNode*>(dn)->setCurrentChild();
- ClassNode* cn = qml_cn->classNode();
- generateBrief(qml_cn, marker);
- generateQmlRequisites(qml_cn, marker);
- QString allQmlMembersLink = generateAllQmlMembersFile(qml_cn, marker);
- if (!allQmlMembersLink.isEmpty()) {
- out() << "<ul>\n";
- out() << "<li><a href=\"" << allQmlMembersLink << "\">"
- << "List of all members, including inherited members</a></li>\n";
- out() << "</ul>\n";
- }
+ sections = marker->sections(dn, CodeMarker::Summary, CodeMarker::Okay);
+ s = sections.constBegin();
+ while (s != sections.constEnd()) {
+ out() << "<a name=\"" << registerRef((*s).name) << "\"></a>" << divNavTop << '\n';
+ out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
+ generateSectionList(*s, dn, marker, CodeMarker::Summary);
+ ++s;
+ }
- s = sections.constBegin();
- while (s != sections.constEnd()) {
- out() << "<a name=\"" << registerRef((*s).name.toLower())
- << "\"></a>" << divNavTop << '\n';
- out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
- generateQmlSummary(*s,dn,marker);
- ++s;
- }
+ generateExtractionMark(dn, DetailedDescriptionMark);
+ out() << "<div class=\"descr\"> <a name=\"" << registerRef("details") << "\"></a>\n"; // QTBUG-9504
- generateExtractionMark(dn, DetailedDescriptionMark);
- out() << "<a name=\"" << registerRef("details") << "\"></a>" << divNavTop << '\n';
- out() << "<h2>" << "Detailed Description" << "</h2>\n";
- generateBody(dn, marker);
- if (cn)
- generateQmlText(cn->doc().body(), cn, marker, dn->name());
- generateAlsoList(dn, marker);
- generateExtractionMark(dn, EndMark);
+ generateBody(dn, marker);
+ out() << "</div>\n"; // QTBUG-9504
+ generateAlsoList(dn, marker);
+ generateExtractionMark(dn, EndMark);
+
+ sections = marker->sections(dn, CodeMarker::Detailed, CodeMarker::Okay);
+ s = sections.constBegin();
+ while (s != sections.constEnd()) {
//out() << "<hr />\n";
+ out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
- sections = marker->qmlSections(qml_cn,CodeMarker::Detailed);
- s = sections.constBegin();
- while (s != sections.constEnd()) {
- out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
- NodeList::ConstIterator m = (*s).members.constBegin();
- while (m != (*s).members.constEnd()) {
- generateDetailedQmlMember(*m, dn, marker);
- out() << "<br/>\n";
- ++m;
- }
- ++s;
+ NodeList::ConstIterator m = (*s).members.constBegin();
+ while (m != (*s).members.constEnd()) {
+ generateDetailedMember(*m, dn, marker);
+ ++m;
}
- generateFooter(dn);
- const_cast<DocNode*>(dn)->clearCurrentChild();
- return;
+ ++s;
}
+ generateFooter(dn);
+}
- sections = marker->sections(dn, CodeMarker::Summary, CodeMarker::Okay);
+/*!
+ Generate the HTML page for a group, module, or QML module.
+ */
+void HtmlGenerator::generateCollectionNode(CollectionNode* cn, CodeMarker* marker)
+{
+ SubTitleSize subTitleSize = LargeSubTitle;
+ QList<Section> sections;
+ QList<Section>::const_iterator s;
+ QString fullTitle = cn->fullTitle();
+
+ generateHeader(fullTitle, cn, marker);
+ generateTableOfContents(cn,marker,0);
+ generateTitle(fullTitle, Text() << cn->subTitle(), subTitleSize, cn, marker);
+
+ if (cn->isModule()) {
+ // Generate brief text and status for modules.
+ generateBrief(cn, marker);
+ generateStatus(cn, marker);
+ generateSince(cn, marker);
+
+ NodeMap nm;
+ cn->getMemberNamespaces(nm);
+ if (!nm.isEmpty()) {
+ out() << "<a name=\"" << registerRef("namespaces") << "\"></a>" << divNavTop << '\n';
+ out() << "<h2>Namespaces</h2>\n";
+ generateAnnotatedList(cn, marker, nm);
+ }
+ nm.clear();
+ cn->getMemberClasses(nm);
+ if (!nm.isEmpty()) {
+ out() << "<a name=\"" << registerRef("classes") << "\"></a>" << divNavTop << '\n';
+ out() << "<h2>Classes</h2>\n";
+ generateAnnotatedList(cn, marker, nm);
+ }
+ nm.clear();
+ }
+
+ sections = marker->sections(cn, CodeMarker::Summary, CodeMarker::Okay);
s = sections.constBegin();
while (s != sections.constEnd()) {
out() << "<a name=\"" << registerRef((*s).name) << "\"></a>" << divNavTop << '\n';
out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
- generateSectionList(*s, dn, marker, CodeMarker::Summary);
+ generateSectionList(*s, cn, marker, CodeMarker::Summary);
++s;
}
- Text brief = dn->doc().briefText();
- if (dn->subType() == Node::Module && !brief.isEmpty()) {
- generateExtractionMark(dn, DetailedDescriptionMark);
+ Text brief = cn->doc().briefText();
+ if (cn->isModule() && !brief.isEmpty()) {
+ generateExtractionMark(cn, DetailedDescriptionMark);
out() << "<a name=\"" << registerRef("details") << "\"></a>" << divNavTop << '\n';
out() << "<div class=\"descr\">\n"; // QTBUG-9504
out() << "<h2>" << "Detailed Description" << "</h2>\n";
}
else {
- generateExtractionMark(dn, DetailedDescriptionMark);
+ generateExtractionMark(cn, DetailedDescriptionMark);
out() << "<div class=\"descr\"> <a name=\"" << registerRef("details") << "\"></a>\n"; // QTBUG-9504
}
- generateBody(dn, marker);
+ generateBody(cn, marker);
out() << "</div>\n"; // QTBUG-9504
- generateAlsoList(dn, marker);
- generateExtractionMark(dn, EndMark);
+ generateAlsoList(cn, marker);
+ generateExtractionMark(cn, EndMark);
- if ((dn->subType() == Node::Group))
- generateAnnotatedList(dn, marker, dn->members());
- else if (dn->subType() == Node::QmlModule)
- generateAnnotatedList(dn, marker, dn->members());
+ if (cn->isGroup())
+ generateAnnotatedList(cn, marker, cn->members());
+ else if (cn->isQmlModule())
+ generateAnnotatedList(cn, marker, cn->members());
- sections = marker->sections(dn, CodeMarker::Detailed, CodeMarker::Okay);
+ sections = marker->sections(cn, CodeMarker::Detailed, CodeMarker::Okay);
s = sections.constBegin();
while (s != sections.constEnd()) {
//out() << "<hr />\n";
@@ -1611,12 +1712,12 @@ void HtmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
NodeList::ConstIterator m = (*s).members.constBegin();
while (m != (*s).members.constEnd()) {
- generateDetailedMember(*m, dn, marker);
+ generateDetailedMember(*m, cn, marker);
++m;
}
++s;
}
- generateFooter(dn);
+ generateFooter(cn);
}
/*!
@@ -1650,7 +1751,7 @@ void HtmlGenerator::generateNavigationBar(const QString &title,
<< Atom(Atom::AutoLink, landingpage)
<< Atom(Atom::ListItemRight);
- if (node->type() == Node::Class) {
+ if (node->isClass()) {
const ClassNode *cn = static_cast<const ClassNode *>(node);
QString name = node->moduleName();
@@ -1667,18 +1768,27 @@ void HtmlGenerator::generateNavigationBar(const QString &title,
<< Atom(Atom::String, cn->name())
<< Atom(Atom::ListItemRight);
}
- else if (node->type() == Node::Document) {
+ else if (node->isQmlType()) {
+ if (!qmltypespage.isEmpty())
+ navigationbar << Atom(Atom::ListItemLeft)
+ << Atom(Atom::Link, qmltypespage)
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << Atom(Atom::String, QLatin1String("QML Types"))
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK)
+ << Atom(Atom::ListItemRight);
+ }
+ else if (node->isQmlBasicType()) {
+ if (!qmltypespage.isEmpty())
+ navigationbar << Atom(Atom::ListItemLeft)
+ << Atom(Atom::Link, qmltypespage)
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << Atom(Atom::String, QLatin1String("QML Types"))
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK)
+ << Atom(Atom::ListItemRight);
+ }
+ else if (node->isDocNode()) {
const DocNode *dn = static_cast<const DocNode *>(node);
- if (node->subType() == Node::QmlClass || node->subType() == Node::QmlBasicType) {
- if (!qmltypespage.isEmpty())
- navigationbar << Atom(Atom::ListItemLeft)
- << Atom(Atom::Link, qmltypespage)
- << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, QLatin1String("QML Types"))
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK)
- << Atom(Atom::ListItemRight);
- }
- else if (dn && dn->isExampleFile()) {
+ if (dn && dn->isExampleFile()) {
navigationbar << Atom(Atom::ListItemLeft)
<< Atom(Atom::Link, dn->parent()->name())
<< Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
@@ -1714,13 +1824,48 @@ void HtmlGenerator::generateHeader(const QString& title,
QString shortVersion = qdb_->version();
if (shortVersion.count(QChar('.')) == 2)
shortVersion.truncate(shortVersion.lastIndexOf(QChar('.')));
- if (!project.isEmpty())
- shortVersion = QLatin1String(" | ") + project + QLatin1Char(' ') + shortVersion;
+
+ //determine the rest of the <title> element content: "title | titleSuffix version"
+ QString titleSuffix;
+ if (!landingpage.isEmpty()) {
+ //for normal pages: "title | landingpage version"
+ titleSuffix = landingpage;
+ }
+ else if (!homepage.isEmpty()) {
+ //for pages that set the homepage but not landing page: "title | homepage version"
+ if (title != homepage)
+ titleSuffix = homepage;
+ }
+ else if (!project.isEmpty()) {
+ //for projects outside of Qt or Qt 5: "title | project version"
+ if (title != project)
+ titleSuffix = project;
+ }
else
- shortVersion = QLatin1String(" | ") + QLatin1String("Qt ") + shortVersion ;
+ //default: "title | Qt version"
+ titleSuffix = QLatin1String("Qt ");
+
+ //for pages that duplicate the title and suffix (landing pages, home pages,
+ // and module landing pages, clear the duplicate
+ if (title == titleSuffix)
+ titleSuffix.clear();
+
+ //for pages that duplicate the version, clear the duplicate
+ if (title.contains(shortVersion) || titleSuffix.contains(shortVersion))
+ shortVersion.clear();
+
+ QString divider;
+ if (!titleSuffix.isEmpty() && !title.isEmpty())
+ divider = QLatin1String(" | ");
// Generating page title
- out() << " <title>" << protectEnc(title) << shortVersion << "</title>\n";
+ out() << " <title>"
+ << protectEnc(title)
+ << divider
+ << titleSuffix
+ << QLatin1Char(' ')
+ << shortVersion
+ << "</title>\n";
// Include style sheet and script links.
out() << headerStyles;
@@ -1892,7 +2037,7 @@ void HtmlGenerator::generateRequisites(InnerNode *inner, CodeMarker *marker)
if (inner->type() == Node::Class || inner->type() == Node::Namespace) {
//add the QT variable to the map
if (!inner->moduleName().isEmpty()) {
- DocNode * moduleNode = qdb_->findModule(inner->moduleName());
+ ModuleNode* moduleNode = qdb_->findModule(inner->moduleName());
if (moduleNode && !moduleNode->qtVariable().isEmpty()) {
text.clear();
text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_TELETYPE)
@@ -1923,18 +2068,20 @@ void HtmlGenerator::generateRequisites(InnerNode *inner, CodeMarker *marker)
r = classe->baseClasses().constBegin();
index = 0;
while (r != classe->baseClasses().constEnd()) {
- text << Atom(Atom::LinkNode, CodeMarker::stringForNode((*r).node))
- << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, (*r).dataTypeWithTemplateArgs)
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
-
- if ((*r).access == Node::Protected) {
- text << " (protected)";
- }
- else if ((*r).access == Node::Private) {
- text << " (private)";
+ if ((*r).node_) {
+ text << Atom(Atom::LinkNode, CodeMarker::stringForNode((*r).node_))
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << Atom(Atom::String, (*r).signature_)
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+
+ if ((*r).access_ == Node::Protected) {
+ text << " (protected)";
+ }
+ else if ((*r).access_ == Node::Private) {
+ text << " (private)";
+ }
+ text << separator(index++, classe->baseClasses().count());
}
- text << separator(index++, classe->baseClasses().count());
++r;
}
text << Atom::ParaRight;
@@ -2002,9 +2149,9 @@ void HtmlGenerator::generateQmlRequisites(QmlClassNode *qcn, CodeMarker *marker)
//add the module name and version to the map
QString qmlModuleVersion;
- DocNode* dn = qdb_->findQmlModule(qcn->qmlModuleName());
- if (dn)
- qmlModuleVersion = dn->qmlModuleVersion();
+ QmlModuleNode* qmn = qdb_->findQmlModule(qcn->qmlModuleName());
+ if (qmn)
+ qmlModuleVersion = qmn->qmlModuleVersion();
else
qmlModuleVersion = qcn->qmlModuleVersion();
text.clear();
@@ -2044,7 +2191,7 @@ void HtmlGenerator::generateQmlRequisites(QmlClassNode *qcn, CodeMarker *marker)
}
//add the inherits to the map
- const QmlClassNode* base = qcn->qmlBaseNode();
+ QmlClassNode* base = qcn->qmlBaseNode();
while (base && base->isInternal()) {
base = base->qmlBaseNode();
}
@@ -2136,7 +2283,11 @@ void HtmlGenerator::generateTableOfContents(const Node *node,
QList<Atom*> toc;
if (node->doc().hasTableOfContents())
toc = node->doc().tableOfContents();
- if (toc.isEmpty() && !sections && (node->subType() != Node::Module))
+ if (toc.isEmpty() && !sections && !node->isModule())
+ return;
+
+ //turn off table of contents if HTML.tocdepth is set to 0
+ if (tocDepth == 0)
return;
QStringList sectionNumber;
@@ -2151,7 +2302,7 @@ void HtmlGenerator::generateTableOfContents(const Node *node,
sectionNumber.append("1");
out() << "<ul>\n";
- if (node->subType() == Node::Module) {
+ if (node->isModule()) {
if (node->hasNamespaces()) {
out() << "<li class=\"level"
<< sectionNumber.size()
@@ -2178,9 +2329,7 @@ void HtmlGenerator::generateTableOfContents(const Node *node,
}
}
}
- else if (sections && ((node->type() == Node::Class) ||
- (node->type() == Node::Namespace) ||
- (node->subType() == Node::QmlClass))) {
+ else if (sections && (node->isClass() || node->isNamespace() || node->isQmlType())) {
QList<Section>::ConstIterator s = sections->constBegin();
while (s != sections->constEnd()) {
if (!s->members.isEmpty() || !s->reimpMembers.isEmpty()) {
@@ -2222,18 +2371,23 @@ void HtmlGenerator::generateTableOfContents(const Node *node,
sectionNumber.last() = QString::number(sectionNumber.last().toInt() + 1);
}
}
- int numAtoms;
- Text headingText = Text::sectionHeading(atom);
- QString s = headingText.toString();
- out() << "<li class=\"level"
- << sectionNumber.size()
- << "\">";
- out() << "<a href=\""
- << '#'
- << Doc::canonicalTitle(s)
- << "\">";
- generateAtomList(headingText.firstAtom(), node, marker, true, numAtoms);
- out() << "</a></li>\n";
+
+ //restrict the ToC depth to the one set by the HTML.tocdepth variable or
+ //print all levels if tocDepth is not set.
+ if (sectionNumber.size() <= tocDepth || tocDepth < 0) {
+ int numAtoms;
+ Text headingText = Text::sectionHeading(atom);
+ QString s = headingText.toString();
+ out() << "<li class=\"level"
+ << sectionNumber.size()
+ << "\">";
+ out() << "<a href=\""
+ << '#'
+ << Doc::canonicalTitle(s)
+ << "\">";
+ generateAtomList(headingText.firstAtom(), node, marker, true, numAtoms);
+ out() << "</a></li>\n";
+ }
}
while (!sectionNumber.isEmpty()) {
sectionNumber.removeLast();
@@ -2278,8 +2432,7 @@ QString HtmlGenerator::generateListOfAllMemberFile(const InnerNode *inner,
the members of QML class \a qml_cn, including the inherited
members. The \a marker is used for formatting stuff.
*/
-QString HtmlGenerator::generateAllQmlMembersFile(const QmlClassNode* qml_cn,
- CodeMarker* marker)
+QString HtmlGenerator::generateAllQmlMembersFile(QmlClassNode* qml_cn, CodeMarker* marker)
{
QList<Section> sections;
QList<Section>::ConstIterator s;
@@ -2448,8 +2601,8 @@ void HtmlGenerator::generateClassHierarchy(const Node *relative, NodeMap& classM
NodeMap newTop;
foreach (const RelatedClass &d, child->derivedClasses()) {
- if (d.access != Node::Private && !d.node->doc().isEmpty())
- newTop.insert(d.node->name(), d.node);
+ if (d.node_ && !d.isPrivate() && !d.node_->isInternal() && d.node_->hasDoc())
+ newTop.insert(d.node_->name(), d.node_);
}
if (!newTop.isEmpty()) {
stack.push(newTop);
@@ -2469,33 +2622,29 @@ void HtmlGenerator::generateAnnotatedList(const Node* relative,
{
if (nodeMap.isEmpty())
return;
- NodeList nl;
- NodeMap::const_iterator i = nodeMap.begin();
- while (i != nodeMap.end()) {
- nl.append(i.value());
- ++i;
- }
- generateAnnotatedList(relative, marker, nl);
+ generateAnnotatedList(relative, marker, nodeMap.values());
}
+/*!
+ */
void HtmlGenerator::generateAnnotatedList(const Node *relative,
CodeMarker *marker,
- const NodeList& nodes)
+ const NodeList& unsortedNodes)
{
+ NodeMap nm;
bool allInternal = true;
- foreach (const Node* node, nodes) {
- if (!node->isInternal() && node->status() != Node::Obsolete) {
+ foreach (Node* node, unsortedNodes) {
+ if (!node->isInternal() && !node->isObsolete()) {
allInternal = false;
+ nm.insert(node->fullName(relative), node);
}
}
if (allInternal)
return;
out() << "<table class=\"annotated\">\n";
int row = 0;
+ NodeList nodes = nm.values();
foreach (const Node* node, nodes) {
- if (node->isInternal() || node->status() == Node::Obsolete)
- continue;
-
if (++row % 2 == 1)
out() << "<tr class=\"odd topAlign\">";
else
@@ -2504,7 +2653,7 @@ void HtmlGenerator::generateAnnotatedList(const Node *relative,
generateFullName(node, relative);
out() << "</p></td>";
- if (!(node->type() == Node::Document)) {
+ if (!node->isDocNode()) {
Text brief = node->doc().trimmedBriefText(node->name());
if (!brief.isEmpty()) {
out() << "<td class=\"tblDescr\"><p>";
@@ -2585,7 +2734,7 @@ void HtmlGenerator::generateCompactList(ListType listType,
paragraphName[paragraphNr] = key[0].toUpper();
usedParagraphNames.insert(key[0].toLower().cell());
- paragraph[paragraphNr].insert(key, c.value());
+ paragraph[paragraphNr].insert(c.key(), c.value());
++c;
}
@@ -2680,7 +2829,7 @@ void HtmlGenerator::generateCompactList(ListType listType,
}
QStringList pieces;
- if (it.value()->subType() == Node::QmlClass)
+ if (it.value()->isQmlType())
pieces << it.value()->name();
else
pieces = it.value()->fullName(relative).split("::");
@@ -2786,117 +2935,105 @@ void HtmlGenerator::generateQmlItem(const Node *node,
marked.remove("<@type>");
marked.remove("</@type>");
}
- out() << highlightedCode(marked, relative, false, node);
+ out() << highlightedCode(marked, relative, false);
}
-void HtmlGenerator::generateOverviewList(const Node *relative)
+void HtmlGenerator::generateList(const Node* relative, CodeMarker* marker, const QString& selector)
{
- QMap<const DocNode *, QMap<QString, DocNode *> > docNodeMap;
- QMap<QString, const DocNode *> groupTitlesMap;
- QMap<QString, DocNode *> uncategorizedNodeMap;
+ NodeList nl;
+ CollectionList cl;
QRegExp singleDigit("\\b([0-9])\\b");
- const NodeList children = qdb_->treeRoot()->childNodes();
- foreach (Node *child, children) {
- if (child->type() == Node::Document && child != relative) {
- DocNode *docNode = static_cast<DocNode *>(child);
-
- // Check whether the page is part of a group or is the group
- // definition page.
- QString group;
- bool isGroupPage = false;
- if (docNode->doc().metaCommandsUsed().contains("group")) {
- group = docNode->doc().metaCommandArgs("group")[0].first;
- isGroupPage = true;
- }
-
- // there are too many examples; they would clutter the list
- if (docNode->subType() == Node::Example)
- continue;
-
- // not interested either in individual (Qt Designer etc.) manual chapters
- if (docNode->links().contains(Node::ContentsLink))
- continue;
-
- // Discard external nodes.
- if (docNode->subType() == Node::ExternalPage)
- continue;
-
- QString sortKey = docNode->fullTitle().toLower();
- if (sortKey.startsWith("the "))
- sortKey.remove(0, 4);
- sortKey.replace(singleDigit, "0\\1");
-
- if (!group.isEmpty()) {
- if (isGroupPage) {
- // If we encounter a group definition page, we add all
- // the pages in that group to the list for that group.
- foreach (Node *member, docNode->members()) {
- if (member->isInternal() || member->type() != Node::Document)
- continue;
- DocNode *page = static_cast<DocNode *>(member);
- if (page) {
- QString sortKey = page->fullTitle().toLower();
- if (sortKey.startsWith("the "))
- sortKey.remove(0, 4);
- sortKey.replace(singleDigit, "0\\1");
- docNodeMap[const_cast<const DocNode *>(docNode)].insert(sortKey, page);
- groupTitlesMap[docNode->fullTitle()] = const_cast<const DocNode *>(docNode);
- }
- }
- }
- else if (!isGroupPage) {
- // If we encounter a page that belongs to a group then
- // we add that page to the list for that group.
- const DocNode* gn = qdb_->getGroup(group);
- if (gn && !docNode->isInternal())
- docNodeMap[gn].insert(sortKey, docNode);
- }
- }
+ if (selector == "overviews") {
+ CNMap groups;
+ qdb_->mergeCollections(Node::Group, groups, relative);
+ cl = groups.values();
+ foreach (CollectionNode* cn, cl)
+ nl.append(cn);
+ generateAnnotatedList(relative, marker, nl);
+ }
+ else if (selector == "cpp-modules") {
+ CNMap modules;
+ qdb_->mergeCollections(Node::Module, modules, relative);
+ cl = modules.values();
+ foreach (CollectionNode* cn, cl)
+ nl.append(cn);
+ generateAnnotatedList(relative, marker, nl);
+ }
+ else if (selector == "qml-modules") {
+ CNMap qmlModules;
+ qdb_->mergeCollections(Node::QmlModule, qmlModules, relative);
+ cl = qmlModules.values();
+ foreach (CollectionNode* cn, cl)
+ nl.append(cn);
+ generateAnnotatedList(relative, marker, nl);
+ }
+ else {
+ /*
+ \generatelist {selector} is only allowed in a
+ comment where the topic is \group, \module, or
+ \qmlmodule.
+ */
+ if (!relative || !relative->isCollectionNode()) {
+ relative->doc().location().warning(tr("\\generatelist {%1} is only allowed in \\group, \\module, and \\qmlmodule comments.").arg(selector));
+ return;
+ }
+ if (selector == "related") {
+ Node* n = const_cast<Node*>(relative);
+ CollectionNode* cn = static_cast<CollectionNode*>(n);
+ qdb_->mergeCollections(cn);
+ generateAnnotatedList(cn, marker, cn->members());
+ }
+ else {
+ Node* n = const_cast<Node*>(relative);
+ CollectionNode* cn = static_cast<CollectionNode*>(n);
+ qdb_->mergeCollections(cn);
+ generateAnnotatedList(cn, marker, cn->members());
}
}
- // We now list all the pages found that belong to groups.
- // If only certain pages were found for a group, but the definition page
- // for that group wasn't listed, the list of pages will be intentionally
- // incomplete. However, if the group definition page was listed, all the
- // pages in that group are listed for completeness.
-
- if (!docNodeMap.isEmpty()) {
- foreach (const QString &groupTitle, groupTitlesMap.keys()) {
- const DocNode *groupNode = groupTitlesMap[groupTitle];
+#if 0
+ QStringList keys = groups.uniqueKeys();
+ foreach (QString key, keys) {
+ GroupNode* gn = static_cast<GroupNode*>(groups.value(key));
+ if (gn) {
out() << QString("<h3><a href=\"%1\">%2</a></h3>\n").arg(
- linkForNode(groupNode, relative)).arg(
- protectEnc(groupNode->fullTitle()));
-
- if (docNodeMap[groupNode].count() == 0)
+ linkForNode(gn, relative)).arg(
+ protectEnc(gn->fullTitle()));
+#if 0
+ if (gn->members().isEmpty())
continue;
- out() << "<ul>\n";
+ NodeMap nm;
+ foreach (Node* member, gn->members()) {
+ if (member->isInternal() || member->isExample() || member->isExternalPage() ||
+ member->isObsolete())
+ continue;
+ // not interested either in individual (Qt Designer etc.) manual chapters
+ if (member->links().contains(Node::ContentsLink))
+ continue;
+ QString sortKey = member->fullTitle().toLower();
+ if (sortKey.startsWith("the "))
+ sortKey.remove(0, 4);
+ sortKey.replace(singleDigit, "0\\1");
+ nm.insert(sortKey, member);
+ }
- foreach (const DocNode *docNode, docNodeMap[groupNode]) {
- QString title = docNode->fullTitle();
+ out() << "<ul>\n";
+ QStringList titles = nm.keys();
+ foreach (QString t, titles) {
+ Node* member = nm.value(t);
+ QString title = member->fullTitle();
if (title.startsWith("The "))
title.remove(0, 4);
- out() << "<li><a href=\"" << linkForNode(docNode, relative) << "\">"
+ out() << "<li><a href=\"" << linkForNode(member, relative) << "\">"
<< protectEnc(title) << "</a></li>\n";
}
out() << "</ul>\n";
+#endif
}
}
-
- if (!uncategorizedNodeMap.isEmpty()) {
- out() << QString("<h3>Miscellaneous</h3>\n");
- out() << "<ul>\n";
- foreach (const DocNode *docNode, uncategorizedNodeMap) {
- QString title = docNode->fullTitle();
- if (title.startsWith("The "))
- title.remove(0, 4);
- out() << "<li><a href=\"" << linkForNode(docNode, relative) << "\">"
- << protectEnc(title) << "</a></li>\n";
- }
- out() << "</ul>\n";
- }
+#endif
}
void HtmlGenerator::generateSection(const NodeList& nl,
@@ -3099,8 +3236,7 @@ void HtmlGenerator::generateSynopsis(const Node *node,
QString HtmlGenerator::highlightedCode(const QString& markedCode,
const Node* relative,
- bool alignNames,
- const Node* self)
+ bool alignNames)
{
QString src = markedCode;
QString html;
@@ -3148,8 +3284,7 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode,
if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
i += 2;
if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) {
-
- const Node* n = qdb_->resolveTarget(par1.toString(), relative);
+ const Node* n = qdb_->resolveFunctionTarget(par1.toString(), relative);
QString link = linkForNode(n, relative);
addLink(link, arg, &html);
par1 = QStringRef();
@@ -3164,7 +3299,7 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode,
}
}
- // replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)" tags
+ // replace all "(<@(type|headerfile)(?: +[^>]*)?>)(.*)(</@\\2>)" tags
src = html;
html = QString();
@@ -3174,10 +3309,10 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode,
bool handled = false;
if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) {
par1 = QStringRef();
- const Node* n = qdb_->resolveTarget(arg.toString(), relative, self);
+ const Node* n = qdb_->resolveType(arg.toString(), relative);
html += QLatin1String("<span class=\"type\">");
- if (n && n->subType() == Node::QmlBasicType) {
- if (relative && relative->subType() == Node::QmlClass)
+ if (n && n->isQmlBasicType()) {
+ if (relative && relative->isQmlType())
addLink(linkForNode(n,relative), arg, &html);
else
html += arg.toString();
@@ -3189,17 +3324,18 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode,
}
else if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) {
par1 = QStringRef();
- const Node* n = qdb_->resolveTarget(arg.toString(), relative);
- addLink(linkForNode(n,relative), arg, &html);
- handled = true;
- }
- else if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) {
- par1 = QStringRef();
- const Node* n = qdb_->resolveTarget(arg.toString(), relative);
- addLink(linkForNode(n,relative), arg, &html);
+ if (arg.at(0) == QChar('&'))
+ html += arg.toString();
+ else {
+ // zzz resolveClassTarget()
+ const Node* n = qdb_->resolveTarget(arg.toString(), relative);
+ if (n)
+ addLink(linkForNode(n,relative), arg, &html);
+ else
+ html += arg.toString();
+ }
handled = true;
}
-
if (!handled) {
html += charLangle;
html += charAt;
@@ -3518,6 +3654,112 @@ QString HtmlGenerator::refForNode(const Node *node)
#define DEBUG_ABSTRACT 0
/*!
+ This function is called for links, i.e. for words that
+ are marked with the qdoc link command. For autolinks
+ that are not marked with the qdoc link command, the
+ getAutoLink() function is called
+
+ It returns the string for a link found by using the data
+ in the \a atom to search the database. It also sets \a node
+ to point to the target node for that link. \a relative points
+ to the node holding the qdoc comment where the link command
+ was found.
+ */
+QString HtmlGenerator::getLink(const Atom *atom, const Node *relative, const Node** node)
+{
+ const QString& t = atom->string();
+ if (t.at(0) == QChar('h')) {
+ if (t.startsWith("http:") || t.startsWith("https:"))
+ return t;
+ }
+ else if (t.at(0) == QChar('f')) {
+ if (t.startsWith("file:") || t.startsWith("ftp:"))
+ return t;
+ }
+ else if (t.at(0) == QChar('m')) {
+ if (t.startsWith("mailto:"))
+ return t;
+ }
+
+ QString ref;
+
+ *node = qdb_->findNode(atom, relative, ref);
+ if (!(*node))
+ return QString();
+
+ QString url = (*node)->url();
+ if (!url.isEmpty()) {
+ if (ref.isEmpty())
+ return url;
+ int hashtag = url.lastIndexOf(QChar('#'));
+ if (hashtag != -1)
+ url.truncate(hashtag);
+ return url + "#" + ref;
+ }
+ /*
+ Given that *node is not null, we now cconstruct a link
+ to the page that *node represents, and then if we found
+ a target on that page, we connect the target to the link
+ with '#'.
+ */
+ QString link = linkForNode(*node, relative);
+ if (*node && (*node)->subType() == Node::Image)
+ link = "images/used-in-examples/" + link;
+ if (!ref.isEmpty())
+ link += QLatin1Char('#') + ref;
+ return link;
+}
+
+/*!
+ This function is called for autolinks, i.e. for words that
+ are not marked with the qdoc link command that qdoc has
+ reason to believe should be links. For links marked with
+ the qdoc link command, the getLink() function is called.
+
+ It returns the string for a link found by using the data
+ in the \a atom to search the database. It also sets \a node
+ to point to the target node for that link. \a relative points
+ to the node holding the qdoc comment where the link command
+ was found.
+ */
+QString HtmlGenerator::getAutoLink(const Atom *atom, const Node *relative, const Node** node)
+{
+ QString ref;
+ QString link;
+ QString target = atom->string().trimmed();
+ *node = 0;
+
+ if (target.endsWith("()")) { // The target is a C++ function or QML method.
+ *node = qdb_->resolveFunctionTarget(target, relative);
+ }
+ else {
+ *node = qdb_->resolveTarget(target, relative);
+ if (!(*node)) {
+ *node = qdb_->findDocNodeByTitle(target);
+ }
+ if (!(*node)) {
+ *node = qdb_->findUnambiguousTarget(target, ref);
+ if (*node && !(*node)->url().isEmpty() && !ref.isEmpty()) {
+ QString final = (*node)->url() + "#" + ref;
+ return final;
+ }
+ }
+ }
+
+ if (!(*node))
+ return link; // empty
+
+ if (!(*node)->url().isEmpty())
+ return (*node)->url();
+
+ link = linkForNode(*node, relative);
+ if (!ref.isEmpty())
+ link += QLatin1Char('#') + ref;
+ return link;
+}
+
+
+/*!
Construct the link string for the \a node and return it.
The \a relative node is use to decide the link we are
generating is in the same file as the target. Note the
@@ -3537,7 +3779,7 @@ QString HtmlGenerator::linkForNode(const Node *node, const Node *relative)
QString fn = fileName(node);
if (node && relative && node->parent() != relative) {
- if (node->parent()->subType() == Node::QmlClass && relative->subType() == Node::QmlClass) {
+ if (node->parent()->isQmlType() && relative->isQmlType()) {
if (node->parent()->isAbstract()) {
/*
This is a bit of a hack. What we discover with
@@ -3680,6 +3922,8 @@ int HtmlGenerator::hOffset(const Node *node)
case Node::Namespace:
case Node::Class:
return 2;
+ case Node::QmlBasicType:
+ case Node::QmlType:
case Node::Document:
return 1;
case Node::Enum:
@@ -3715,131 +3959,6 @@ const QPair<QString,QString> HtmlGenerator::anchorForNode(const Node *node)
return anchorPair;
}
-QString HtmlGenerator::getLink(const Atom *atom, const Node *relative, const Node** node)
-{
- QString link;
- *node = 0;
- inObsoleteLink = false;
-
- if (atom->string().contains(QLatin1Char(':')) &&
- (atom->string().startsWith("file:")
- || atom->string().startsWith("http:")
- || atom->string().startsWith("https:")
- || atom->string().startsWith("ftp:")
- || atom->string().startsWith("mailto:"))) {
-
- link = atom->string();
- }
- else {
- QStringList path;
- if (atom->string().contains('#')) {
- path = atom->string().split('#');
- }
- else {
- path.append(atom->string());
- }
-
- QString ref;
- QString first = path.first().trimmed();
- if (first.isEmpty()) {
- *node = relative;
- }
- else if (first.endsWith(".html")) {
- /*
- This is not a recursive search. That's ok in
- this case, because we are searching for a page
- node, which must be a direct child of the tree
- root.
- */
- *node = qdb_->treeRoot()->findChildNodeByNameAndType(first, Node::Document);
- }
- else {
- *node = qdb_->resolveTarget(first, relative);
- if (!*node) {
- *node = qdb_->findDocNodeByTitle(first, relative);
- }
- if (!*node) {
- *node = qdb_->findUnambiguousTarget(first, ref, relative);
- if (*node && !(*node)->url().isEmpty() && !ref.isEmpty()) {
- QString final = (*node)->url() + "#" + ref;
- return final;
- }
- }
- }
- if (*node) {
- if (!(*node)->url().isEmpty()) {
- return (*node)->url();
- }
- else {
- path.removeFirst();
- }
- }
- else {
- *node = relative;
- }
-
- if (*node) {
- if ((*node)->status() == Node::Obsolete) {
- if (relative) {
- if (relative->parent() != *node) {
- if (relative->status() != Node::Obsolete) {
- bool porting = false;
- if (relative->type() == Node::Document) {
- const DocNode* dn = static_cast<const DocNode*>(relative);
- if (dn->title().startsWith("Porting"))
- porting = true;
- }
- QString name = relative->plainFullName();
- if (!porting && !name.startsWith("Q3")) {
- if (obsoleteLinks) {
- relative->doc().location().warning(tr("Link to obsolete item '%1' in %2")
- .arg(atom->string())
- .arg(name));
- }
- inObsoleteLink = true;
- }
- }
- }
- }
- else {
- qDebug() << "Link to Obsolete entity"
- << (*node)->name() << "no relative";
- }
- }
- }
-
- /*
- This loop really only makes sense if *node is not 0.
- In that case, The node *node points to represents a
- qdoc page, so the link will ultimately point to some
- target on that page. This loop finds that target on
- the page that *node represents. ref is that target.
- */
- while (!path.isEmpty()) {
- ref = qdb_->findTarget(path.first(), *node);
- if (ref.isEmpty())
- break;
- path.removeFirst();
- }
-
- /*
- Given that *node is not null, we now cconstruct a link
- to the page that *node represents, and then if there is
- a target on that page, we connect the target to the link
- with '#'.
- */
- if (path.isEmpty()) {
- link = linkForNode(*node, relative);
- if (*node && (*node)->subType() == Node::Image)
- link = "images/used-in-examples/" + link;
- if (!ref.isEmpty()) {
- link += QLatin1Char('#') + ref;
- }
- }
- }
- return link;
-}
-
void HtmlGenerator::generateStatus(const Node *node, CodeMarker *marker)
{
Text text;
@@ -3861,19 +3980,7 @@ void HtmlGenerator::generateStatus(const Node *node, CodeMarker *marker)
<< "We strongly advise against "
<< "using it in new code. See ";
- const DocNode *docNode = qdb_->findDocNodeByTitle("Porting To Qt 4");
- QString ref;
- if (docNode && node->type() == Node::Class) {
- QString oldName(node->name());
- oldName.remove(QLatin1Char('3'));
- ref = qdb_->findTarget(oldName, docNode);
- }
-
- if (!ref.isEmpty()) {
- text << Atom(Atom::Link, linkForNode(docNode, node) + QLatin1Char('#') + ref);
- }
- else
- text << Atom(Atom::Link, "Porting to Qt 4");
+ text << Atom(Atom::Link, "Porting to Qt 4");
text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
<< Atom(Atom::String, "Porting to Qt 4")
@@ -4018,7 +4125,7 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node,
out() << "<td class=\"tblQmlPropNode\"><p>";
out() << "<a name=\"" + refForNode(qpn) + "\"></a>";
- if (!qpn->isWritable(qdb_))
+ if (!qpn->isWritable())
out() << "<span class=\"qmlreadonly\">read-only</span>";
if (qpn->isDefault())
out() << "<span class=\"qmldefault\">default</span>";
@@ -4039,7 +4146,7 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node,
out() << "<a name=\"" + refForNode(qpn) + "\"></a>";
if (!qpn->isReadOnlySet()) {
if (qpn->declarativeCppNode())
- qpn->setReadOnly(!qpn->isWritable(qdb_));
+ qpn->setReadOnly(!qpn->isWritable());
}
if (qpn->isReadOnly())
out() << "<span class=\"qmlreadonly\">read-only</span>";
@@ -4101,11 +4208,11 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node,
Output the "Inherits" line for the QML element,
if there should be one.
*/
-void HtmlGenerator::generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker)
+void HtmlGenerator::generateQmlInherits(QmlClassNode* qcn, CodeMarker* marker)
{
if (!qcn)
return;
- const QmlClassNode* base = qcn->qmlBaseNode();
+ QmlClassNode* base = qcn->qmlBaseNode();
while (base && base->isInternal()) {
base = base->qmlBaseNode();
}
@@ -4229,7 +4336,7 @@ void HtmlGenerator::generateManifestFiles()
{
generateManifestFile("examples", "example");
generateManifestFile("demos", "demo");
- ExampleNode::exampleNodeMap.clear();
+ qdb_->exampleNodeMap().clear();
manifestMetaContent.clear();
}
@@ -4240,7 +4347,8 @@ void HtmlGenerator::generateManifestFiles()
*/
void HtmlGenerator::generateManifestFile(QString manifest, QString element)
{
- if (ExampleNode::exampleNodeMap.isEmpty())
+ ExampleNodeMap& exampleNodeMap = qdb_->exampleNodeMap();
+ if (exampleNodeMap.isEmpty())
return;
QString fileName = manifest +"-manifest.xml";
QFile file(outputDir() + QLatin1Char('/') + fileName);
@@ -4251,8 +4359,8 @@ void HtmlGenerator::generateManifestFile(QString manifest, QString element)
demos = true;
bool proceed = false;
- ExampleNodeMap::Iterator i = ExampleNode::exampleNodeMap.begin();
- while (i != ExampleNode::exampleNodeMap.end()) {
+ ExampleNodeMap::Iterator i = exampleNodeMap.begin();
+ while (i != exampleNodeMap.end()) {
const ExampleNode* en = i.value();
if (demos) {
if (en->name().startsWith("demos")) {
@@ -4276,8 +4384,8 @@ void HtmlGenerator::generateManifestFile(QString manifest, QString element)
writer.writeAttribute("module", project);
writer.writeStartElement(manifest);
- i = ExampleNode::exampleNodeMap.begin();
- while (i != ExampleNode::exampleNodeMap.end()) {
+ i = exampleNodeMap.begin();
+ while (i != exampleNodeMap.end()) {
const ExampleNode* en = i.value();
if (demos) {
if (!en->name().startsWith("demos")) {
@@ -4508,6 +4616,16 @@ void HtmlGenerator::reportOrphans(const InnerNode* parent)
break;
case Node::Class:
break;
+ case Node::QmlType:
+ break;
+ case Node::QmlBasicType:
+ break;
+ case Node::Group:
+ break;
+ case Node::Module:
+ break;
+ case Node::QmlModule:
+ break;
case Node::Document:
switch (child->subType()) {
case Node::Example:
@@ -4518,20 +4636,10 @@ void HtmlGenerator::reportOrphans(const InnerNode* parent)
break;
case Node::Image:
break;
- case Node::Group:
- break;
- case Node::Module:
- break;
case Node::Page:
break;
case Node::ExternalPage:
break;
- case Node::QmlClass:
- break;
- case Node::QmlBasicType:
- break;
- case Node::QmlModule:
- break;
case Node::Collision:
break;
default:
diff --git a/src/tools/qdoc/htmlgenerator.h b/src/tools/qdoc/htmlgenerator.h
index ae16f3c54f..ef569b38ce 100644
--- a/src/tools/qdoc/htmlgenerator.h
+++ b/src/tools/qdoc/htmlgenerator.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the tools applications of the Qt Toolkit.
@@ -88,7 +88,7 @@ public:
virtual void initializeGenerator(const Config& config);
virtual void terminateGenerator();
virtual QString format();
- virtual void generateTree();
+ virtual void generateDocs();
void generateCollisionPages();
void generateManifestFiles();
@@ -102,7 +102,10 @@ protected:
const Node *relative,
CodeMarker *marker);
virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker);
+ virtual void generateQmlTypePage(QmlClassNode* qcn, CodeMarker* marker);
+ virtual void generateQmlBasicTypePage(QmlBasicTypeNode* qbtn, CodeMarker* marker);
virtual void generateDocNode(DocNode* dn, CodeMarker* marker);
+ virtual void generateCollectionNode(CollectionNode* cn, CodeMarker* marker);
virtual QString fileExtension() const;
virtual QString refForNode(const Node *node);
virtual QString linkForNode(const Node *node, const Node *relative);
@@ -152,8 +155,7 @@ private:
QList<Section>* sections = 0);
QString generateListOfAllMemberFile(const InnerNode *inner,
CodeMarker *marker);
- QString generateAllQmlMembersFile(const QmlClassNode* qml_cn,
- CodeMarker* marker);
+ QString generateAllQmlMembersFile(QmlClassNode* qml_cn, CodeMarker* marker);
QString generateLowStatusMemberFile(InnerNode *inner,
CodeMarker *marker,
CodeMarker::Status status);
@@ -167,7 +169,7 @@ private:
QString commonPrefix);
void generateFunctionIndex(const Node *relative);
void generateLegaleseList(const Node *relative, CodeMarker *marker);
- void generateOverviewList(const Node *relative);
+ void generateList(const Node* relative, CodeMarker* marker, const QString& selector);
void generateSectionList(const Section& section,
const Node *relative,
CodeMarker *marker,
@@ -182,7 +184,7 @@ private:
void generateDetailedQmlMember(Node *node,
const InnerNode *relative,
CodeMarker *marker);
- void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker);
+ void generateQmlInherits(QmlClassNode* qcn, CodeMarker* marker);
void generateQmlInstantiates(QmlClassNode* qcn, CodeMarker* marker);
void generateInstantiatedBy(ClassNode* cn, CodeMarker* marker);
@@ -200,8 +202,7 @@ private:
void generateSectionInheritedList(const Section& section, const Node *relative);
QString highlightedCode(const QString& markedCode,
const Node* relative,
- bool alignNames = false,
- const Node* self = 0);
+ bool alignNames = false);
void generateFullName(const Node *apparentNode, const Node *relative, const Node *actualNode = 0);
void generateDetailedMember(const Node *node,
@@ -210,12 +211,14 @@ private:
void generateLink(const Atom *atom, CodeMarker *marker);
void generateStatus(const Node *node, CodeMarker *marker);
+ QString getLink(const Atom *atom, const Node *relative, const Node** node);
+ QString getAutoLink(const Atom *atom, const Node *relative, const Node** node);
+
QString registerRef(const QString& ref);
virtual QString fileBase(const Node *node) const;
QString fileName(const Node *node);
static int hOffset(const Node *node);
static bool isThreeColumnEnumValueTable(const Atom *atom);
- QString getLink(const Atom *atom, const Node *relative, const Node** node);
#ifdef GENERATE_MAC_REFS
void generateMacRef(const Node *node, CodeMarker *marker);
#endif
@@ -263,6 +266,7 @@ private:
QString qmltypespage;
QString buildversion;
QString qflagsHref_;
+ int tocDepth;
public:
static bool debugging_on;
@@ -276,6 +280,7 @@ public:
#define HTMLGENERATOR_POSTPOSTHEADER "postpostheader"
#define HTMLGENERATOR_NONAVIGATIONBAR "nonavigationbar"
#define HTMLGENERATOR_NOSUBDIRS "nosubdirs"
+#define HTMLGENERATOR_TOCDEPTH "tocdepth"
QT_END_NAMESPACE
diff --git a/src/tools/qdoc/location.cpp b/src/tools/qdoc/location.cpp
index cdecb59626..073b1cb174 100644
--- a/src/tools/qdoc/location.cpp
+++ b/src/tools/qdoc/location.cpp
@@ -52,7 +52,7 @@
QT_BEGIN_NAMESPACE
-QT_STATIC_CONST_IMPL Location Location::null;
+const Location Location::null;
int Location::tabSize;
QString Location::programName;
diff --git a/src/tools/qdoc/location.h b/src/tools/qdoc/location.h
index 0c113bcbeb..d5ea5a6af0 100644
--- a/src/tools/qdoc/location.h
+++ b/src/tools/qdoc/location.h
@@ -90,7 +90,7 @@ public:
void fatal(const QString& message,
const QString& details = QString()) const;
- QT_STATIC_CONST Location null;
+ static const Location null;
static void initialize(const Config& config);
static void terminate();
diff --git a/src/tools/qdoc/main.cpp b/src/tools/qdoc/main.cpp
index 8998a27081..758918e2b6 100644
--- a/src/tools/qdoc/main.cpp
+++ b/src/tools/qdoc/main.cpp
@@ -63,6 +63,8 @@
#ifndef QT_BOOTSTRAPPED
# include "qcoreapplication.h"
#endif
+#include "qcommandlineoption.h"
+#include "qcommandlineparser.h"
#include <algorithm>
@@ -78,6 +80,7 @@ static bool highlighting = false;
static bool showInternal = false;
static bool redirectDocumentationToDevNull = false;
static bool noLinkErrors = false;
+static bool autolinkErrors = false;
static bool obsoleteLinks = false;
static QStringList defines;
static QStringList dependModules;
@@ -85,55 +88,6 @@ static QStringList indexDirs;
static QString currentDir;
static QString prevCurrentDir;
-/*!
- Print the help message to \c stdout.
- */
-static void printHelp()
-{
- Location::information(QCoreApplication::translate("QDoc", "Usage: qdoc [options] file1.qdocconf ...\n"
- "Options:\n"
- " -D<name> "
- "Define <name> as a macro while parsing sources\n"
- " -depends "
- "Specify dependent modules\n"
- " -help "
- "Display this information and exit\n"
- " -highlighting "
- "Turn on syntax highlighting (makes qdoc run slower)\n"
- " -indexdir "
- "Specify a directory where QDoc should search for index files to load\n"
- " -installdir "
- "Specify the directory where the output will be after running \"make install\"\n"
- " -no-examples "
- "Do not generate documentation for examples\n"
- " -no-link-errors "
- "Do not print link errors (i.e. missing targets)\n"
- " -obsoletelinks "
- "Report links from obsolete items to non-obsolete items\n"
- " -outputdir "
- "Specify output directory, overrides setting in qdocconf file\n"
- " -outputformat "
- "Specify output format, overrides setting in qdocconf file\n"
- " -prepare "
- "Run qdoc only to generate an index file, not the docs\n"
- " -generate "
- "Run qdoc to read the index files and generate the docs\n"
- " -showinternal "
- "Include content marked internal\n"
- " -redirect-documentation-to-dev-null "
- "Save all documentation content to /dev/null. Useful if someone is interested in qdoc errors only.\n"
- " -version "
- "Display version of qdoc and exit\n") );
-}
-
-/*!
- Prints the qdoc version number to stdout.
- */
-static void printVersion()
-{
- QString s = QCoreApplication::translate("QDoc", "qdoc version %1").arg(QT_VERSION_STR);
- Location::information(s);
-}
static void loadIndexFiles(Config& config)
{
@@ -141,9 +95,18 @@ static void loadIndexFiles(Config& config)
/*
Read some XML indexes containing definitions from other documentation sets.
*/
- QStringList indexFiles = config.getStringList(CONFIG_INDEXES);
+ QStringList indexFiles;
+ QStringList configIndexes = config.getStringList(CONFIG_INDEXES);
+ foreach (const QString &index, configIndexes) {
+ QFileInfo fi(index);
+ if (fi.exists() && fi.isFile())
+ indexFiles << index;
+ else if (Generator::runGenerateOnly())
+ qDebug() << "warning: Index file not found:" << index;
+ }
dependModules += config.getStringList(CONFIG_DEPENDS);
+ dependModules.removeDuplicates();
bool noOutputSubdirs = false;
QString singleOutputSubdir;
@@ -275,6 +238,7 @@ static void processQdocconfFile(const QString &fileName)
config.setStringList(CONFIG_SHOWINTERNAL, QStringList(showInternal ? "true" : "false"));
config.setStringList(CONFIG_REDIRECTDOCUMENTATIONTODEVNULL, QStringList(redirectDocumentationToDevNull ? "true" : "false"));
config.setStringList(CONFIG_NOLINKERRORS, QStringList(noLinkErrors ? "true" : "false"));
+ config.setStringList(CONFIG_AUTOLINKERRORS, QStringList(autolinkErrors ? "true" : "false"));
config.setStringList(CONFIG_OBSOLETELINKS, QStringList(obsoleteLinks ? "true" : "false"));
/*
@@ -289,7 +253,8 @@ static void processQdocconfFile(const QString &fileName)
currentDir = QFileInfo(fileName).path();
Location::initialize(config);
config.load(fileName);
-
+ QString project = config.getString(CONFIG_PROJECT).toLower();
+ //qDebug() << "\nStart project:" << project;
/*
Add the defines to the configuration variables.
*/
@@ -363,7 +328,11 @@ static void processQdocconfFile(const QString &fileName)
Location outputFormatsLocation = config.lastLocation();
//if (!Generator::runPrepareOnly())
+ Generator::debug(" loading index files");
loadIndexFiles(config);
+ qdb->newPrimaryTree(config.getString(CONFIG_PROJECT));
+ qdb->setSearchOrder();
+ Generator::debug(" done loading index files");
QSet<QString> excludedDirs;
QSet<QString> excludedFiles;
@@ -372,7 +341,7 @@ static void processQdocconfFile(const QString &fileName)
QStringList excludedDirsList;
QStringList excludedFilesList;
- Generator::debugSegfault("Reading excludedirs");
+ Generator::debug("Reading excludedirs");
excludedDirsList = config.getCanonicalPathList(CONFIG_EXCLUDEDIRS);
foreach (const QString &excludeDir, excludedDirsList) {
QString p = QDir::fromNativeSeparators(excludeDir);
@@ -381,14 +350,14 @@ static void processQdocconfFile(const QString &fileName)
excludedDirs.insert(p);
}
- Generator::debugSegfault("Reading excludefiles");
- excludedFilesList = config.getCleanPathList(CONFIG_EXCLUDEFILES);
+ Generator::debug("Reading excludefiles");
+ excludedFilesList = config.getCanonicalPathList(CONFIG_EXCLUDEFILES);
foreach (const QString& excludeFile, excludedFilesList) {
QString p = QDir::fromNativeSeparators(excludeFile);
excludedFiles.insert(p);
}
- Generator::debugSegfault("Reading headerdirs");
+ Generator::debug("Reading headerdirs");
headerList = config.getAllFiles(CONFIG_HEADERS,CONFIG_HEADERDIRS,excludedDirs,excludedFiles);
QMap<QString,QString> headers;
QMultiMap<QString,QString> headerFileNames;
@@ -402,7 +371,7 @@ static void processQdocconfFile(const QString &fileName)
headerFileNames.insert(t,t);
}
- Generator::debugSegfault("Reading sourcedirs");
+ Generator::debug("Reading sourcedirs");
sourceList = config.getAllFiles(CONFIG_SOURCES,CONFIG_SOURCEDIRS,excludedDirs,excludedFiles);
QMap<QString,QString> sources;
QMultiMap<QString,QString> sourceFileNames;
@@ -419,7 +388,7 @@ static void processQdocconfFile(const QString &fileName)
Find all the qdoc files in the example dirs, and add
them to the source files to be parsed.
*/
- Generator::debugSegfault("Reading exampledirs");
+ Generator::debug("Reading exampledirs");
QStringList exampleQdocList = config.getExampleQdocFiles(excludedDirs, excludedFiles);
for (int i=0; i<exampleQdocList.size(); ++i) {
if (!sources.contains(exampleQdocList[i])) {
@@ -429,7 +398,7 @@ static void processQdocconfFile(const QString &fileName)
}
}
- Generator::debugSegfault("Adding doc/image dirs found in exampledirs to imagedirs");
+ Generator::debug("Adding doc/image dirs found in exampledirs to imagedirs");
QSet<QString> exampleImageDirs;
QStringList exampleImageList = config.getExampleImageFiles(excludedDirs, excludedFiles);
for (int i=0; i<exampleImageList.size(); ++i) {
@@ -448,13 +417,14 @@ static void processQdocconfFile(const QString &fileName)
*/
QSet<CodeParser *> usedParsers;
- Generator::debugSegfault("Parsing header files");
+ Generator::debug("Parsing header files");
int parsed = 0;
QMap<QString,QString>::ConstIterator h = headers.constBegin();
while (h != headers.constEnd()) {
CodeParser *codeParser = CodeParser::parserForHeaderFile(h.key());
if (codeParser) {
++parsed;
+ Generator::debug(QString("Parsing " + h.key()));
codeParser->parseHeaderFile(config.location(), h.key());
usedParsers.insert(codeParser);
}
@@ -465,22 +435,26 @@ static void processQdocconfFile(const QString &fileName)
codeParser->doneParsingHeaderFiles();
usedParsers.clear();
+ qdb->resolveInheritance();
+
/*
Parse each source text file in the set using the appropriate parser and
add it to the big tree.
*/
parsed = 0;
- Generator::debugSegfault("Parsing source files");
+ Generator::debug("Parsing source files");
QMap<QString,QString>::ConstIterator s = sources.constBegin();
while (s != sources.constEnd()) {
CodeParser *codeParser = CodeParser::parserForSourceFile(s.key());
if (codeParser) {
++parsed;
+ Generator::debug(QString("Parsing " + s.key()));
codeParser->parseSourceFile(config.location(), s.key());
usedParsers.insert(codeParser);
}
++s;
}
+ Generator::debug(QString("Parsing done."));
foreach (CodeParser *codeParser, usedParsers)
codeParser->doneParsingSourceFiles();
@@ -490,7 +464,7 @@ static void processQdocconfFile(const QString &fileName)
source files. Resolve all the class names, function names,
targets, URLs, links, and other stuff that needs resolving.
*/
- Generator::debugSegfault("Resolving stuff prior to generating docs");
+ Generator::debug("Resolving stuff prior to generating docs");
qdb->resolveIssues();
/*
@@ -499,19 +473,21 @@ static void processQdocconfFile(const QString &fileName)
documentation output. More than one output format can be
requested. The tree is traversed for each one.
*/
- Generator::debugSegfault("Generating docs");
+ Generator::debug("Generating docs");
QSet<QString>::ConstIterator of = outputFormats.constBegin();
while (of != outputFormats.constEnd()) {
Generator* generator = Generator::generatorForFormat(*of);
if (generator == 0)
outputFormatsLocation.fatal(QCoreApplication::translate("QDoc", "Unknown output format '%1'").arg(*of));
- generator->generateTree();
+ generator->generateDocs();
++of;
}
//Generator::writeOutFileNames();
- Generator::debugSegfault("Shutting down qdoc");
+ Generator::debug("Shutting down qdoc");
+ if (Generator::debugging())
+ Generator::stopDebugging(project);
QDocDatabase::qdocDB()->setVersion(QString());
Generator::terminate();
@@ -532,7 +508,7 @@ static void processQdocconfFile(const QString &fileName)
#ifdef DEBUG_SHUTDOWN_CRASH
qDebug() << "main(): qdoc database deleted";
#endif
- Generator::debugSegfault("qdoc finished!");
+ Generator::debug("qdoc finished!");
}
extern Q_CORE_EXPORT QBasicAtomicInt qt_qhash_seed;
@@ -544,8 +520,9 @@ int main(int argc, char **argv)
#ifndef QT_BOOTSTRAPPED
qt_qhash_seed.testAndSetRelaxed(-1, 0); // set the hash seed to 0 if it wasn't set yet
- QCoreApplication app(argc, argv);
#endif
+ QCoreApplication app(argc, argv);
+ app.setApplicationVersion(QStringLiteral(QT_VERSION_STR));
/*
Create code parsers for the languages to be parsed,
@@ -567,93 +544,124 @@ int main(int argc, char **argv)
HtmlGenerator htmlGenerator;
DitaXmlGenerator ditaxmlGenerator;
- QStringList qdocFiles;
- QString opt;
- int i = 1;
-
- while (i < argc) {
- opt = argv[i++];
-
- if (opt == "-help") {
- printHelp();
- return EXIT_SUCCESS;
- }
- else if (opt == "-version") {
- printVersion();
- return EXIT_SUCCESS;
- }
- else if (opt == "--") {
- while (i < argc)
- qdocFiles.append(argv[i++]);
- }
- else if (opt.startsWith("-D")) {
- QString define = opt.mid(2);
- defines += define;
- }
- else if (opt == "-depends") {
- dependModules += argv[i];
- i++;
- }
- else if (opt == "-highlighting") {
- highlighting = true;
- }
- else if (opt == "-showinternal") {
- showInternal = true;
- }
- else if (opt == "-redirect-documentation-to-dev-null") {
- redirectDocumentationToDevNull = true;
- }
- else if (opt == "-no-examples") {
- Config::generateExamples = false;
- }
- else if (opt == "-indexdir") {
- if (QFile::exists(argv[i])) {
- indexDirs += argv[i];
- }
- else {
- qDebug() << "Cannot find index directory" << argv[i];
- }
- i++;
- }
- else if (opt == "-installdir") {
- Config::installDir = argv[i];
- i++;
- }
- else if (opt == "-obsoletelinks") {
- obsoleteLinks = true;
- }
- else if (opt == "-outputdir") {
- Config::overrideOutputDir = argv[i];
- i++;
- }
- else if (opt == "-outputformat") {
- Config::overrideOutputFormats.insert(argv[i]);
- i++;
- }
- else if (opt == "-no-link-errors") {
- noLinkErrors = true;
- }
- else if (opt == "-debug") {
- Generator::setDebugSegfaultFlag(true);
- }
- else if (opt == "-prepare") {
- Generator::setQDocPass(Generator::Prepare);
- }
- else if (opt == "-generate") {
- Generator::setQDocPass(Generator::Generate);
- }
- else if (opt == "-log-progress") {
- Location::startLoggingProgress();
- }
- else {
- qdocFiles.append(opt);
- }
- }
-
- if (qdocFiles.isEmpty()) {
- printHelp();
- return EXIT_FAILURE;
+ QCommandLineParser parser;
+ parser.setApplicationDescription(QCoreApplication::translate("qdoc", "Qt documentation generator"));
+ parser.addHelpOption();
+ parser.addVersionOption();
+
+ parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
+
+ parser.addPositionalArgument("file1.qdocconf ...", QCoreApplication::translate("qdoc", "Input files"));
+
+ QCommandLineOption defineOption(QStringList() << QStringLiteral("D"));
+ defineOption.setDescription(QCoreApplication::translate("qdoc", "Define the argument as a macro while parsing sources"));
+ defineOption.setValueName(QStringLiteral("macro[=def]"));
+ parser.addOption(defineOption);
+
+ QCommandLineOption dependsOption(QStringList() << QStringLiteral("depends"));
+ dependsOption.setDescription(QCoreApplication::translate("qdoc", "Specify dependent modules"));
+ dependsOption.setValueName(QStringLiteral("module"));
+ parser.addOption(dependsOption);
+
+ QCommandLineOption highlightingOption(QStringList() << QStringLiteral("highlighting"));
+ highlightingOption.setDescription(QCoreApplication::translate("qdoc", "Turn on syntax highlighting (makes qdoc run slower)"));
+ parser.addOption(highlightingOption);
+
+ QCommandLineOption showInternalOption(QStringList() << QStringLiteral("showinternal"));
+ showInternalOption.setDescription(QCoreApplication::translate("qdoc", "Include content marked internal"));
+ parser.addOption(showInternalOption);
+
+ QCommandLineOption redirectDocumentationToDevNullOption(QStringList() << QStringLiteral("redirect-documentation-to-dev-null"));
+ redirectDocumentationToDevNullOption.setDescription(QCoreApplication::translate("qdoc", "Save all documentation content to /dev/null. Useful if someone is interested in qdoc errors only."));
+ parser.addOption(redirectDocumentationToDevNullOption);
+
+ QCommandLineOption noExamplesOption(QStringList() << QStringLiteral("no-examples"));
+ noExamplesOption.setDescription(QCoreApplication::translate("qdoc", "Do not generate documentation for examples"));
+ parser.addOption(noExamplesOption);
+
+ QCommandLineOption indexDirOption(QStringList() << QStringLiteral("indexdir"));
+ indexDirOption.setDescription(QCoreApplication::translate("qdoc", "Specify a directory where QDoc should search for index files to load"));
+ indexDirOption.setValueName(QStringLiteral("dir"));
+ parser.addOption(indexDirOption);
+
+ QCommandLineOption installDirOption(QStringList() << QStringLiteral("installdir"));
+ installDirOption.setDescription(QCoreApplication::translate("qdoc", "Specify the directory where the output will be after running \"make install\""));
+ installDirOption.setValueName(QStringLiteral("dir"));
+ parser.addOption(installDirOption);
+
+ QCommandLineOption obsoleteLinksOption(QStringList() << QStringLiteral("obsoletelinks"));
+ obsoleteLinksOption.setDescription(QCoreApplication::translate("qdoc", "Report links from obsolete items to non-obsolete items"));
+ parser.addOption(obsoleteLinksOption);
+
+ QCommandLineOption outputDirOption(QStringList() << QStringLiteral("outputdir"));
+ outputDirOption.setDescription(QCoreApplication::translate("qdoc", "Specify output directory, overrides setting in qdocconf file"));
+ outputDirOption.setValueName(QStringLiteral("dir"));
+ parser.addOption(outputDirOption);
+
+ QCommandLineOption outputFormatOption(QStringList() << QStringLiteral("outputformat"));
+ outputFormatOption.setDescription(QCoreApplication::translate("qdoc", "Specify output format, overrides setting in qdocconf file"));
+ outputFormatOption.setValueName(QStringLiteral("format"));
+ parser.addOption(outputFormatOption);
+
+ QCommandLineOption noLinkErrorsOption(QStringList() << QStringLiteral("no-link-errors"));
+ noLinkErrorsOption.setDescription(QCoreApplication::translate("qdoc", "Do not print link errors (i.e. missing targets)"));
+ parser.addOption(noLinkErrorsOption);
+
+ QCommandLineOption autoLinkErrorsOption(QStringList() << QStringLiteral("autolink-errors"));
+ autoLinkErrorsOption.setDescription(QCoreApplication::translate("qdoc", "Show errors when automatic linking fails"));
+ parser.addOption(autoLinkErrorsOption);
+
+ QCommandLineOption debugOption(QStringList() << QStringLiteral("debug"));
+ debugOption.setDescription(QCoreApplication::translate("qdoc", "Enable debug output"));
+ parser.addOption(debugOption);
+
+ QCommandLineOption prepareOption(QStringList() << QStringLiteral("prepare"));
+ prepareOption.setDescription(QCoreApplication::translate("qdoc", "Run qdoc only to generate an index file, not the docs"));
+ parser.addOption(prepareOption);
+
+ QCommandLineOption generateOption(QStringList() << QStringLiteral("generate"));
+ generateOption.setDescription(QCoreApplication::translate("qdoc", "Run qdoc to read the index files and generate the docs"));
+ parser.addOption(generateOption);
+
+ QCommandLineOption logProgressOption(QStringList() << QStringLiteral("log-progress"));
+ logProgressOption.setDescription(QCoreApplication::translate("qdoc", "Log progress on stderr."));
+ parser.addOption(logProgressOption);
+
+ parser.process(app);
+
+ defines += parser.values(defineOption);
+ dependModules += parser.values(dependsOption);
+ highlighting = parser.isSet(highlightingOption);
+ showInternal = parser.isSet(showInternalOption);
+ redirectDocumentationToDevNull = parser.isSet(redirectDocumentationToDevNullOption);
+ Config::generateExamples = !parser.isSet(noExamplesOption);
+ foreach (const QString &indexDir, parser.values(indexDirOption)) {
+ if (QFile::exists(indexDir))
+ indexDirs += indexDir;
+ else
+ qDebug() << "Cannot find index directory" << indexDir;
}
+ if (parser.isSet(installDirOption))
+ Config::installDir = parser.value(installDirOption);
+ obsoleteLinks = parser.isSet(obsoleteLinksOption);
+ if (parser.isSet(outputDirOption))
+ Config::overrideOutputDir = parser.value(outputDirOption);
+ foreach (const QString &format, parser.values(outputFormatOption))
+ Config::overrideOutputFormats.insert(format);
+ noLinkErrors = parser.isSet(noLinkErrorsOption);
+ autolinkErrors = parser.isSet(autoLinkErrorsOption);
+ if (parser.isSet(debugOption))
+ Generator::startDebugging(QString("command line"));
+ if (parser.isSet(prepareOption))
+ Generator::setQDocPass(Generator::Prepare);
+ if (parser.isSet(generateOption))
+ Generator::setQDocPass(Generator::Generate);
+ if (parser.isSet(logProgressOption))
+ Location::startLoggingProgress();
+
+ const QStringList qdocFiles = parser.positionalArguments();
+ if (qdocFiles.isEmpty())
+ parser.showHelp();
/*
Main loop.
diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp
index c88ebfc760..03b798cbb3 100644
--- a/src/tools/qdoc/node.cpp
+++ b/src/tools/qdoc/node.cpp
@@ -50,8 +50,39 @@
QT_BEGIN_NAMESPACE
int Node::propertyGroupCount_ = 0;
-ExampleNodeMap ExampleNode::exampleNodeMap;
QStringMap Node::operators_;
+QMap<QString,Node::Type> Node::goals_;
+
+/*!
+ Initialize the map of search goals. This is called once
+ by QDocDatabase::initializeDB(). The map key is a string
+ representing a value in the enum Node::Type. The map value
+ is the enum value.
+
+ There should be an entry in the map for each value in the
+ Type enum.
+ */
+void Node::initialize()
+{
+ goals_.insert("class", Node::Class);
+ goals_.insert("qmltype", Node::QmlType);
+ goals_.insert("page", Node::Document);
+ goals_.insert("function", Node::Function);
+ goals_.insert("property", Node::Property);
+ goals_.insert("variable", Node::Variable);
+ goals_.insert("group", Node::Group);
+ goals_.insert("module", Node::Module);
+ goals_.insert("qmlmodule", Node::QmlModule);
+ goals_.insert("qmppropertygroup", Node::QmlPropertyGroup);
+ goals_.insert("qmlproperty", Node::QmlProperty);
+ goals_.insert("qmlsignal", Node::QmlSignal);
+ goals_.insert("qmlsignalhandler", Node::QmlSignalHandler);
+ goals_.insert("qmlmethod", Node::QmlMethod);
+ goals_.insert("qmlbasictype", Node::QmlBasicType);
+ goals_.insert("enum", Node::Enum);
+ goals_.insert("typedef", Node::Typedef);
+ goals_.insert("namespace", Node::Namespace);
+}
/*!
Increment the number of property groups seen in the current
@@ -127,14 +158,14 @@ QString Node::plainFullName(const Node* relative) const
*/
QString Node::fullName(const Node* relative) const
{
- if (type() == Node::Document) {
+ if (isDocNode() || isCollectionNode()) {
const DocNode* dn = static_cast<const DocNode*>(this);
// Only print modulename::type on collision pages.
if (!dn->qmlModuleName().isEmpty() && relative != 0 && relative->isCollisionNode())
return dn->qmlModuleName() + "::" + dn->title();
return dn->title();
}
- else if (type() == Node::Class) {
+ else if (isClass()) {
const ClassNode* cn = static_cast<const ClassNode*>(this);
if (!cn->serviceName().isEmpty())
return cn->serviceName();
@@ -143,6 +174,31 @@ QString Node::fullName(const Node* relative) const
}
/*!
+ Try to match this node's type and subtype with one of the
+ pairs in \a types. If a match is found, return true. If no
+ match is found, return false.
+
+ \a types is a list of type/subtype pairs, where the first
+ value in the pair is a Node::Type, and the second value is
+ a Node::SubType. The second value is used in the match if
+ this node's type is Node::Document.
+ */
+bool Node::match(const NodeTypeList& types) const
+{
+ for (int i=0; i<types.size(); ++i) {
+ if (type() == types.at(i).first) {
+ if (type() == Node::Document) {
+ if (subType() == types.at(i).second)
+ return true;
+ }
+ else
+ return true;
+ }
+ }
+ return false;
+}
+
+/*!
Sets this Node's Doc to \a doc. If \a replace is false and
this Node already has a Doc, a warning is reported that the
Doc is being overridden, and it reports where the previous
@@ -170,7 +226,6 @@ Node::Node(Type type, InnerNode *parent, const QString& name)
pageType_(NoPageType),
status_(Commendable),
indexNodeFlag_(false),
- seen_(true),
parent_(parent),
relatesTo_(0),
name_(name)
@@ -224,21 +279,13 @@ Node::Node(Type type, InnerNode *parent, const QString& name)
}
}
-/*!
+/*! \fn QString Node::url() const
Returns the node's URL.
*/
-QString Node::url() const
-{
- return url_;
-}
-/*!
+/*! \fn void Node::setUrl(const QString &url)
Sets the node's URL to \a url
*/
-void Node::setUrl(const QString &url)
-{
- url_ = url;
-}
/*!
Returns this node's page type as a string, for use as an
@@ -309,6 +356,16 @@ QString Node::nodeTypeString(unsigned t)
return "property";
case Variable:
return "variable";
+ case Group:
+ return "group";
+ case Module:
+ return "module";
+ case QmlType:
+ return "QML type";
+ case QmlBasicType:
+ return "QML basic type";
+ case QmlModule:
+ return "QML module";
case QmlProperty:
return "QML property";
case QmlPropertyGroup:
@@ -351,20 +408,10 @@ QString Node::nodeSubtypeString(unsigned t)
return "file";
case Image:
return "image";
- case Group:
- return "group";
- case Module:
- return "module";
case Page:
return "page";
case ExternalPage:
return "external page";
- case QmlClass:
- return "QML type";
- case QmlBasicType:
- return "QML basic type";
- case QmlModule:
- return "QML module";
case DitaMap:
return "ditamap";
case Collision:
@@ -515,7 +562,7 @@ QString Node::extractClassName(const QString &string) const
*/
QString RelatedClass::accessString() const
{
- switch (access) {
+ switch (access_) {
case Node::Protected:
return "protected";
case Node::Private:
@@ -601,9 +648,9 @@ QmlClassNode* Node::qmlClassNode()
{
if (isQmlNode()) {
Node* n = this;
- while (n && n->subType() != Node::QmlClass)
+ while (n && !n->isQmlType())
n = n->parent();
- if (n && n->subType() == Node::QmlClass)
+ if (n && n->isQmlType())
return static_cast<QmlClassNode*>(n);
}
return 0;
@@ -640,97 +687,33 @@ bool Node::isInternal() const
}
/*!
- \class InnerNode
- */
-
-/*!
- The inner node destructor deletes the children and removes
- this node from its related nodes.
- */
-InnerNode::~InnerNode()
-{
- deleteChildren();
- removeFromRelated();
-}
-
-/*!
- Returns \c true if this node's members coolection is not empty.
- */
-bool InnerNode::hasMembers() const
-{
- return !members_.isEmpty();
-}
-
-/*!
- Appends \a node to the members list, if and only if it
- isn't already in the members list.
+ Returns a pointer to the Tree this node is in.
*/
-void InnerNode::addMember(Node* node)
+Tree* Node::tree() const
{
- if (!members_.contains(node))
- members_.append(node);
+ return (parent() ? parent()->tree() : 0);
}
/*!
- Returns \c true if this node's members collection contains at
- least one namespace node.
+ Returns a pointer to the root of the Tree this node is in.
*/
-bool InnerNode::hasNamespaces() const
+const Node* Node::root() const
{
- if (!members_.isEmpty()) {
- NodeList::const_iterator i = members_.begin();
- while (i != members_.end()) {
- if ((*i)->isNamespace())
- return true;
- ++i;
- }
- }
- return false;
+ return (parent() ? parent()->root() : this);
}
/*!
- Returns \c true if this node's members collection contains at
- least one class node.
- */
-bool InnerNode::hasClasses() const
-{
- if (!members_.isEmpty()) {
- NodeList::const_iterator i = members_.begin();
- while (i != members_.end()) {
- if ((*i)->isClass())
- return true;
- ++i;
- }
- }
- return false;
-}
-
-/*!
- Loads \a out with all this node's member nodes that are namespace nodes.
+ \class InnerNode
*/
-void InnerNode::getMemberNamespaces(NodeMap& out)
-{
- out.clear();
- NodeList::const_iterator i = members_.begin();
- while (i != members_.end()) {
- if ((*i)->isNamespace())
- out.insert((*i)->name(),(*i));
- ++i;
- }
-}
/*!
- Loads \a out with all this node's member nodes that are class nodes.
+ The inner node destructor deletes the children and removes
+ this node from its related nodes.
*/
-void InnerNode::getMemberClasses(NodeMap& out)
+InnerNode::~InnerNode()
{
- out.clear();
- NodeList::const_iterator i = members_.begin();
- while (i != members_.end()) {
- if ((*i)->isClass())
- out.insert((*i)->name(),(*i));
- ++i;
- }
+ deleteChildren();
+ removeFromRelated();
}
/*!
@@ -739,16 +722,16 @@ void InnerNode::getMemberClasses(NodeMap& out)
sure to also look in the children of its property
group nodes. Return the matching node or 0.
*/
-Node *InnerNode::findChildNodeByName(const QString& name)
+Node *InnerNode::findChildNode(const QString& name) const
{
Node *node = childMap.value(name);
- if (node && node->type() != QmlPropertyGroup)
+ if (node && !node->isQmlPropertyGroup())
return node;
- if ((type() == Document) && (subType() == QmlClass)) {
+ if (isQmlType()) {
for (int i=0; i<children_.size(); ++i) {
Node* n = children_.at(i);
- if (n->type() == QmlPropertyGroup) {
- node = static_cast<InnerNode*>(n)->findChildNodeByName(name);
+ if (n->isQmlPropertyGroup()) {
+ node = static_cast<InnerNode*>(n)->findChildNode(name);
if (node)
return node;
}
@@ -756,58 +739,6 @@ Node *InnerNode::findChildNodeByName(const QString& name)
}
return primaryFunctionMap.value(name);
}
-void InnerNode::findNodes(const QString& name, QList<Node*>& n)
-{
- n.clear();
- Node* node = 0;
- QList<Node*> nodes = childMap.values(name);
- /*
- <sigh> If this node's child map contains no nodes named
- name, then if this node is a QML class, seach each of its
- property group nodes for a node named name. If a match is
- found, append it to the output list and return immediately.
- */
- if (nodes.isEmpty()) {
- if ((type() == Document) && (subType() == QmlClass)) {
- for (int i=0; i<children_.size(); ++i) {
- node = children_.at(i);
- if (node->type() == QmlPropertyGroup) {
- node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
- if (node) {
- n.append(node);
- return;
- }
- }
- }
- }
- }
- else {
- /*
- If the childMap does contain one or more nodes named
- name, traverse the list of matching nodes. Append each
- matching node that is not a property group node to the
- output list. Search each property group node for a node
- named name and append that node to the output list.
- This is overkill, I think, but should produce a useful
- list.
- */
- for (int i=0; i<nodes.size(); ++i) {
- node = nodes.at(i);
- if (node->type() != QmlPropertyGroup)
- n.append(node);
- else {
- node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
- if (node)
- n.append(node);
- }
- }
- }
- if (!n.isEmpty())
- return;
- node = primaryFunctionMap.value(name);
- if (node)
- n.append(node);
-}
/*!
Find the node in this node's children that has the given \a name. If
@@ -819,7 +750,7 @@ void InnerNode::findNodes(const QString& name, QList<Node*>& n)
returns \c true. If \a qml is false, only match a node for which
node->isQmlNode() returns \c false.
*/
-Node* InnerNode::findChildNodeByName(const QString& name, bool qml)
+Node* InnerNode::findChildNode(const QString& name, bool qml) const
{
QList<Node*> nodes = childMap.values(name);
if (!nodes.isEmpty()) {
@@ -829,15 +760,15 @@ Node* InnerNode::findChildNodeByName(const QString& name, bool qml)
if (!node->isQmlNode())
return node;
}
- else if (node->isQmlNode() && (node->type() != QmlPropertyGroup))
+ else if (node->isQmlNode())
return node;
}
}
- if (qml && (type() == Document) && (subType() == QmlClass)) {
+ if (qml && isQmlType()) {
for (int i=0; i<children_.size(); ++i) {
Node* node = children_.at(i);
- if (node->type() == QmlPropertyGroup) {
- node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
+ if (node->isQmlPropertyGroup()) {
+ node = static_cast<InnerNode*>(node)->findChildNode(name);
if (node)
return node;
}
@@ -847,7 +778,7 @@ Node* InnerNode::findChildNodeByName(const QString& name, bool qml)
}
/*!
- This function is like findChildNodeByName(), but if a node
+ This function is like findChildNode(), but if a node
with the specified \a name is found but it is not of the
specified \a type, 0 is returned.
@@ -857,7 +788,7 @@ Node* InnerNode::findChildNodeByName(const QString& name, bool qml)
node because it looks up \a name in the child map, not the
list.
*/
-Node* InnerNode::findChildNodeByNameAndType(const QString& name, Type type)
+Node* InnerNode::findChildNode(const QString& name, Type type)
{
if (type == Function)
return primaryFunctionMap.value(name);
@@ -873,10 +804,65 @@ Node* InnerNode::findChildNodeByNameAndType(const QString& name, Type type)
}
/*!
+ */
+void InnerNode::findNodes(const QString& name, QList<Node*>& n)
+{
+ n.clear();
+ Node* node = 0;
+ QList<Node*> nodes = childMap.values(name);
+ /*
+ <sigh> If this node's child map contains no nodes named
+ name, then if this node is a QML class, search each of its
+ property group nodes for a node named name. If a match is
+ found, append it to the output list and return immediately.
+ */
+ if (nodes.isEmpty()) {
+ if (isQmlType()) {
+ for (int i=0; i<children_.size(); ++i) {
+ node = children_.at(i);
+ if (node->isQmlPropertyGroup()) {
+ node = static_cast<InnerNode*>(node)->findChildNode(name);
+ if (node) {
+ n.append(node);
+ return;
+ }
+ }
+ }
+ }
+ }
+ else {
+ /*
+ If the childMap does contain one or more nodes named
+ name, traverse the list of matching nodes. Append each
+ matching node that is not a property group node to the
+ output list. Search each property group node for a node
+ named name and append that node to the output list.
+ This is overkill, I think, but should produce a useful
+ list.
+ */
+ for (int i=0; i<nodes.size(); ++i) {
+ node = nodes.at(i);
+ if (!node->isQmlPropertyGroup())
+ n.append(node);
+ else {
+ node = static_cast<InnerNode*>(node)->findChildNode(name);
+ if (node)
+ n.append(node);
+ }
+ }
+ }
+ if (!n.isEmpty())
+ return;
+ node = primaryFunctionMap.value(name);
+ if (node)
+ n.append(node);
+}
+
+/*!
Find a function node that is a child of this nose, such
that the function node has the specified \a name.
*/
-FunctionNode *InnerNode::findFunctionNode(const QString& name)
+FunctionNode *InnerNode::findFunctionNode(const QString& name) const
{
return static_cast<FunctionNode *>(primaryFunctionMap.value(name));
}
@@ -985,19 +971,6 @@ void InnerNode::makeUndocumentedChildrenInternal()
}
/*!
- In each child node that is a collision node,
- clear the current child pointer.
- */
-void InnerNode::clearCurrentChildPointers()
-{
- foreach (Node* child, childNodes()) {
- if (child->subType() == Collision) {
- child->clearCurrentChild();
- }
- }
-}
-
-/*!
*/
void InnerNode::normalizeOverloads()
{
@@ -1092,64 +1065,17 @@ bool Node::isWrapper() const
}
/*!
- */
-const Node *InnerNode::findChildNodeByName(const QString& name) const
-{
- InnerNode *that = (InnerNode *) this;
- return that->findChildNodeByName(name);
-}
-
-/*!
- If \a qml is true, only match a node for which node->isQmlNode()
- returns \c true. If \a qml is false, only match a node for which
- node->isQmlNode() returns \c false.
- */
-const Node* InnerNode::findChildNodeByName(const QString& name, bool qml) const
-{
- InnerNode*that = (InnerNode*) this;
- return that->findChildNodeByName(name, qml);
-}
-
-/*!
- Searches this node's children for a child named \a name
- with the specified node \a type.
- */
-const Node* InnerNode::findChildNodeByNameAndType(const QString& name, Type type) const
-{
- InnerNode *that = (InnerNode *) this;
- return that->findChildNodeByNameAndType(name, type);
-}
-
-/*!
- Find a function node that is a child of this nose, such
- that the function node has the specified \a name. This
- function calls the non-const version of itself.
- */
-const FunctionNode *InnerNode::findFunctionNode(const QString& name) const
-{
- InnerNode *that = (InnerNode *) this;
- return that->findFunctionNode(name);
-}
-
-/*!
- Find the function node that is a child of this node, such
- that the function has the same name and signature as the
- \a clone node. This function calls the non-const version.
- */
-const FunctionNode *InnerNode::findFunctionNode(const FunctionNode *clone) const
-{
- InnerNode *that = (InnerNode *) this;
- return that->findFunctionNode(clone);
-}
-
-/*!
+ Finds the enum type node that has \a enumValue as one of
+ its enum values and returns a pointer to it. Returns 0 if
+ no enum type node is found that has \a enumValue as one
+ of its values.
*/
const EnumNode *InnerNode::findEnumNodeForValue(const QString &enumValue) const
{
foreach (const Node *node, enumChildren_) {
- const EnumNode *enume = static_cast<const EnumNode *>(node);
- if (enume->hasItem(enumValue))
- return enume;
+ const EnumNode *en = static_cast<const EnumNode *>(node);
+ if (en->hasItem(enumValue))
+ return en;
}
return 0;
}
@@ -1194,6 +1120,7 @@ InnerNode::InnerNode(Type type, InnerNode *parent, const QString& name)
{
switch (type) {
case Class:
+ case QmlType:
case Namespace:
setPageType(ApiPage);
break;
@@ -1278,6 +1205,17 @@ void InnerNode::addChild(Node *child)
}
/*!
+ Adds the \a child to this node's child map using \a title
+ as the key. The \a child is not added to the child list
+ again, because it is presumed to already be there. We just
+ want to be able to find the child by its \a title.
+ */
+void InnerNode::addChild(Node* child, const QString& title)
+{
+ childMap.insertMulti(title, child);
+}
+
+/*!
*/
void InnerNode::removeChild(Node *child)
{
@@ -1307,6 +1245,16 @@ void InnerNode::removeChild(Node *child)
}
++ent;
}
+ if (child->title().isEmpty())
+ return;
+ ent = childMap.find(child->title());
+ while (ent != childMap.end() && ent.key() == child->title()) {
+ if (*ent == child) {
+ childMap.erase(ent);
+ break;
+ }
+ ++ent;
+ }
}
/*!
@@ -1381,7 +1329,7 @@ QmlPropertyNode* InnerNode::hasQmlProperty(const QString& n) const
if (child->name() == n)
return static_cast<QmlPropertyNode*>(child);
}
- else if (child->type() == Node::QmlPropertyGroup) {
+ else if (child->isQmlPropertyGroup()) {
QmlPropertyNode* t = child->hasQmlProperty(n);
if (t)
return t;
@@ -1414,6 +1362,7 @@ LeafNode::LeafNode(Type type, InnerNode *parent, const QString& name)
case QmlSignal:
case QmlSignalHandler:
case QmlMethod:
+ case QmlBasicType:
setPageType(ApiPage);
break;
default:
@@ -1457,7 +1406,7 @@ LeafNode::LeafNode(InnerNode* parent, Type type, const QString& name)
Constructs a namespace node.
*/
NamespaceNode::NamespaceNode(InnerNode *parent, const QString& name)
- : InnerNode(Namespace, parent, name)
+ : InnerNode(Namespace, parent, name), tree_(0)
{
setPageType(ApiPage);
}
@@ -1480,13 +1429,36 @@ ClassNode::ClassNode(InnerNode *parent, const QString& name)
}
/*!
+ Adds the base class \a node to this class's list of base
+ classes. The base class has the specified \a access. This
+ is a resolved base class.
*/
-void ClassNode::addBaseClass(Access access,
- ClassNode *node,
- const QString &dataTypeWithTemplateArgs)
+void ClassNode::addResolvedBaseClass(Access access, ClassNode* node)
{
- bases.append(RelatedClass(access, node, dataTypeWithTemplateArgs));
- node->derived.append(RelatedClass(access, this));
+ bases_.append(RelatedClass(access, node));
+ node->derived_.append(RelatedClass(access, this));
+}
+
+/*!
+ Adds the derived class \a node to this class's list of derived
+ classes. The derived class inherits this class with \a access.
+ */
+void ClassNode::addDerivedClass(Access access, ClassNode* node)
+{
+ derived_.append(RelatedClass(access, node));
+}
+
+/*!
+ Add an unresolved base class to this class node's list of
+ base classes. The unresolved base class will be resolved
+ before the generate phase of qdoc. In an unresolved base
+ class, the pointer to the base class node is 0.
+ */
+void ClassNode::addUnresolvedBaseClass(Access access,
+ const QStringList& path,
+ const QString& signature)
+{
+ bases_.append(RelatedClass(access, path, signature));
}
/*!
@@ -1498,15 +1470,15 @@ void ClassNode::fixBaseClasses()
QSet<ClassNode *> found;
// Remove private and duplicate base classes.
- while (i < bases.size()) {
- ClassNode* bc = bases.at(i).node;
- if (bc->access() == Node::Private || found.contains(bc)) {
- RelatedClass rc = bases.at(i);
- bases.removeAt(i);
- ignoredBases.append(rc);
+ while (i < bases_.size()) {
+ ClassNode* bc = bases_.at(i).node_;
+ if (bc && (bc->access() == Node::Private || found.contains(bc))) {
+ RelatedClass rc = bases_.at(i);
+ bases_.removeAt(i);
+ ignoredBases_.append(rc);
const QList<RelatedClass> &bb = bc->baseClasses();
for (int j = bb.size() - 1; j >= 0; --j)
- bases.insert(i, bb.at(j));
+ bases_.insert(i, bb.at(j));
}
else {
++i;
@@ -1515,13 +1487,13 @@ void ClassNode::fixBaseClasses()
}
i = 0;
- while (i < derived.size()) {
- ClassNode* dc = derived.at(i).node;
- if (dc->access() == Node::Private) {
- derived.removeAt(i);
+ while (i < derived_.size()) {
+ ClassNode* dc = derived_.at(i).node_;
+ if (dc && dc->access() == Node::Private) {
+ derived_.removeAt(i);
const QList<RelatedClass> &dd = dc->derivedClasses();
for (int j = dd.size() - 1; j >= 0; --j)
- derived.insert(i, dd.at(j));
+ derived_.insert(i, dd.at(j));
}
else {
++i;
@@ -1530,12 +1502,34 @@ void ClassNode::fixBaseClasses()
}
/*!
+ Not sure why this is needed.
+ */
+void ClassNode::fixPropertyUsingBaseClasses(PropertyNode* pn)
+{
+ QList<RelatedClass>::const_iterator bc = baseClasses().constBegin();
+ while (bc != baseClasses().constEnd()) {
+ ClassNode* cn = bc->node_;
+ if (cn) {
+ Node* n = cn->findChildNode(pn->name(), Node::Property);
+ if (n) {
+ PropertyNode* baseProperty = static_cast<PropertyNode*>(n);
+ cn->fixPropertyUsingBaseClasses(baseProperty);
+ pn->setOverriddenFrom(baseProperty);
+ }
+ else
+ cn->fixPropertyUsingBaseClasses(pn);
+ }
+ ++bc;
+ }
+}
+
+/*!
Search the child list to find the property node with the
specified \a name.
*/
PropertyNode* ClassNode::findPropertyNode(const QString& name)
{
- Node* n = findChildNodeByNameAndType(name, Node::Property);
+ Node* n = findChildNode(name, Node::Property);
if (n)
return static_cast<PropertyNode*>(n);
@@ -1545,19 +1539,23 @@ PropertyNode* ClassNode::findPropertyNode(const QString& name)
const QList<RelatedClass> &bases = baseClasses();
if (!bases.isEmpty()) {
for (int i = 0; i < bases.size(); ++i) {
- ClassNode* cn = bases[i].node;
- pn = cn->findPropertyNode(name);
- if (pn)
- break;
+ ClassNode* cn = bases[i].node_;
+ if (cn) {
+ pn = cn->findPropertyNode(name);
+ if (pn)
+ break;
+ }
}
}
const QList<RelatedClass>& ignoredBases = ignoredBaseClasses();
if (!ignoredBases.isEmpty()) {
for (int i = 0; i < ignoredBases.size(); ++i) {
- ClassNode* cn = ignoredBases[i].node;
- pn = cn->findPropertyNode(name);
- if (pn)
- break;
+ ClassNode* cn = ignoredBases[i].node_;
+ if (cn) {
+ pn = cn->findPropertyNode(name);
+ if (pn)
+ break;
+ }
}
}
@@ -1577,13 +1575,13 @@ QmlClassNode* ClassNode::findQmlBaseNode()
if (!bases.isEmpty()) {
for (int i = 0; i < bases.size(); ++i) {
- ClassNode* cn = bases[i].node;
+ ClassNode* cn = bases[i].node_;
if (cn && cn->qmlElement()) {
return cn->qmlElement();
}
}
for (int i = 0; i < bases.size(); ++i) {
- ClassNode* cn = bases[i].node;
+ ClassNode* cn = bases[i].node_;
if (cn) {
result = cn->findQmlBaseNode();
if (result != 0) {
@@ -1614,17 +1612,6 @@ DocNode::DocNode(InnerNode* parent, const QString& name, SubType subtype, Node::
case DitaMap:
setPageType(ptype);
break;
- case Module:
- case Group:
- setPageType(OverviewPage);
- break;
- case QmlModule:
- setPageType(OverviewPage);
- break;
- case QmlClass:
- case QmlBasicType:
- setPageType(ApiPage);
- break;
case Example:
setPageType(ExamplePage);
break;
@@ -1636,12 +1623,17 @@ DocNode::DocNode(InnerNode* parent, const QString& name, SubType subtype, Node::
}
}
-/*!
+/*! \fn QString DocNode::title() const
Returns the document node's title. This is used for the page title.
*/
-QString DocNode::title() const
+
+/*!
+ Sets the document node's \a title. This is used for the page title.
+ */
+void DocNode::setTitle(const QString &title)
{
- return title_;
+ title_ = title;
+ parent()->addChild(this, title);
}
/*!
@@ -1693,16 +1685,6 @@ QString DocNode::subTitle() const
}
/*!
- The constructor calls the DocNode constructor with
- \a parent, \a name, and Node::Example.
- */
-ExampleNode::ExampleNode(InnerNode* parent, const QString& name)
- : DocNode(parent, name, Node::Example, Node::ExamplePage)
-{
- // nothing
-}
-
-/*!
\class EnumNode
*/
@@ -2115,18 +2097,17 @@ bool QmlClassNode::qmlOnly = false;
QMultiMap<QString,Node*> QmlClassNode::inheritedBy;
/*!
- Constructs a Qml class node (i.e. a Document node with the
- subtype QmlClass. The new node has the given \a parent
- and \a name.
+ Constructs a Qml class node. The new node has the given
+ \a parent and \a name.
*/
QmlClassNode::QmlClassNode(InnerNode *parent, const QString& name)
- : DocNode(parent, name, QmlClass, Node::ApiPage),
+ : InnerNode(QmlType, parent, name),
abstract_(false),
cnodeRequired_(false),
wrapper_(false),
cnode_(0),
qmlModule_(0),
- baseNode_(0)
+ qmlBaseNode_(0)
{
int i = 0;
if (name.startsWith("QML:")) {
@@ -2134,6 +2115,7 @@ QmlClassNode::QmlClassNode(InnerNode *parent, const QString& name)
i = 4;
}
setTitle(name.mid(i));
+ setPageType(Node::ApiPage);
}
/*!
@@ -2198,6 +2180,14 @@ void QmlModuleNode::setQmlModuleInfo(const QString& arg)
}
}
+QmlClassNode* QmlClassNode::qmlBaseNode()
+{
+ if (!qmlBaseNode_ && !qmlBaseName_.isEmpty()) {
+ qmlBaseNode_ = QDocDatabase::qdocDB()->findQmlType(qmlBaseName_);
+ }
+ return qmlBaseNode_;
+}
+
/*!
If this QML type node has a base type node,
return the fully qualified name of that QML
@@ -2206,45 +2196,13 @@ void QmlModuleNode::setQmlModuleInfo(const QString& arg)
QString QmlClassNode::qmlFullBaseName() const
{
QString result;
- if (baseNode_) {
- result = baseNode_->qmlModuleName() + "::" + baseNode_->name();
+ if (qmlBaseNode_) {
+ result = qmlBaseNode_->qmlModuleName() + "::" + qmlBaseNode_->name();
}
return result;
}
/*!
- The name of this QML class node might be the same as the
- name of some other QML class node. If so, then this node's
- parent will be a NameCollisionNode.This function sets the
- NameCollisionNode's current child to this node. This is
- important when outputting the documentation for this node,
- when, for example, the documentation contains a link to
- the page being output. We don't want to generate a link
- to the disambiguation page if we can avoid it, and to be
- able to avoid it, the NameCollisionNode must maintain the
- current child pointer. That's the purpose of this function.
- */
-void QmlClassNode::setCurrentChild()
-{
- if (parent()) {
- InnerNode* n = parent();
- if (n->subType() == Node::Collision)
- n->setCurrentChild(this);
- }
-}
-
-/*!
- */
-void QmlClassNode::clearCurrentChild()
-{
- if (parent()) {
- InnerNode* n = parent();
- if (n->subType() == Node::Collision)
- n->clearCurrentChild();
- }
-}
-
-/*!
If the QML type's QML module pointer is set, return the QML
module name from the QML module node. Otherwise, return the
empty string.
@@ -2275,13 +2233,12 @@ QString QmlClassNode::qmlModuleIdentifier() const
}
/*!
- Constructs a Qml basic type node (i.e. a Document node with
- the subtype QmlBasicType. The new node has the given
+ Constructs a Qml basic type node. The new node has the given
\a parent and \a name.
*/
QmlBasicTypeNode::QmlBasicTypeNode(InnerNode *parent,
const QString& name)
- : DocNode(parent, name, QmlBasicType, Node::ApiPage)
+ : InnerNode(QmlBasicType, parent, name)
{
setTitle(name);
}
@@ -2345,7 +2302,7 @@ QmlPropertyNode::QmlPropertyNode(InnerNode* parent,
...because the tokenizer gets confused on \e{explicit}.
*/
-bool QmlPropertyNode::isWritable(QDocDatabase* qdb)
+bool QmlPropertyNode::isWritable()
{
if (readOnly_ != FlagValueDefault)
return !fromFlagValue(readOnly_, false);
@@ -2354,7 +2311,7 @@ bool QmlPropertyNode::isWritable(QDocDatabase* qdb)
if (qcn) {
if (qcn->cppClassRequired()) {
if (qcn->classNode()) {
- PropertyNode* pn = correspondingProperty(qdb);
+ PropertyNode* pn = findCorrespondingCppProperty();
if (pn)
return pn->isWritable();
else
@@ -2377,49 +2334,63 @@ bool QmlPropertyNode::isWritable(QDocDatabase* qdb)
Returns a pointer this QML property's corresponding C++
property, if it has one.
*/
-PropertyNode* QmlPropertyNode::correspondingProperty(QDocDatabase* qdb)
+PropertyNode* QmlPropertyNode::findCorrespondingCppProperty()
{
PropertyNode* pn;
-
Node* n = parent();
- while (n && n->subType() != Node::QmlClass)
+ while (n && !n->isQmlType())
n = n->parent();
if (n) {
QmlClassNode* qcn = static_cast<QmlClassNode*>(n);
ClassNode* cn = qcn->classNode();
if (cn) {
+ /*
+ If there is a dot in the property name, first
+ find the C++ property corresponding to the QML
+ property group.
+ */
QStringList dotSplit = name().split(QChar('.'));
pn = cn->findPropertyNode(dotSplit[0]);
if (pn) {
+ /*
+ Now find the C++ property corresponding to
+ the QML property in the QML property group,
+ <group>.<property>.
+ */
if (dotSplit.size() > 1) {
- // Find the C++ property corresponding to the QML property in
- // the property group, <group>.<property>.
-
QStringList path(extractClassName(pn->qualifiedDataType()));
- Node* nn = qdb->findClassNode(path);
+ Node* nn = QDocDatabase::qdocDB()->findClassNode(path);
if (nn) {
ClassNode* cn = static_cast<ClassNode*>(nn);
PropertyNode *pn2 = cn->findPropertyNode(dotSplit[1]);
- if (pn2)
- return pn2; // Return the property for the QML property.
- else
- return pn; // Return the property for the QML group.
+ /*
+ If found, return the C++ property
+ corresponding to the QML property.
+ Otherwise, return the C++ property
+ corresponding to the QML property
+ group.
+ */
+ return (pn2 ? pn2 : pn);
}
}
else
return pn;
}
- else {
- pn = cn->findPropertyNode(dotSplit[0]);
- if (pn)
- return pn;
- }
}
}
-
return 0;
}
+/*!
+ This returns the name of the owning QML type.
+ */
+QString QmlPropertyNode::element() const
+{
+ if (parent()->isQmlPropertyGroup())
+ return parent()->element();
+ return parent()->name();
+}
+
/*! \class NameCollisionNode
An instance of this node is inserted in the tree
@@ -2437,7 +2408,6 @@ NameCollisionNode::NameCollisionNode(InnerNode* child)
{
setTitle("Name Collision: " + child->name());
addCollision(child);
- current = 0;
}
/*!
@@ -2463,28 +2433,11 @@ NameCollisionNode::~NameCollisionNode()
// nothing.
}
-/*! \fn const InnerNode* NameCollisionNode::currentChild() const
- Returns a pointer to the current child, which may be 0.
- */
-
-/*! \fn void NameCollisionNode::setCurrentChild(InnerNode* child)
- Sets the current child to \a child. The current child is
- valid only within the file where it is defined.
- */
-
-/*! \fn void NameCollisionNode::clearCurrentChild()
- Sets the current child to 0. This should be called at the
- end of each file, because the current child is only valid
- within the file where the child is defined.
- */
-
/*!
Returns \c true if this collision node's current node is a QML node.
*/
bool NameCollisionNode::isQmlNode() const
{
- if (current)
- return current->isQmlNode();
return false;
}
@@ -2494,10 +2447,6 @@ bool NameCollisionNode::isQmlNode() const
*/
InnerNode* NameCollisionNode::findAny(Node::Type t, Node::SubType st)
{
- if (current) {
- if (current->type() == t && current->subType() == st)
- return current;
- }
const NodeList& cn = childNodes();
NodeList::ConstIterator i = cn.constBegin();
while (i != cn.constEnd()) {
@@ -2520,7 +2469,7 @@ const Node* NameCollisionNode::applyModuleName(const Node* origin) const
const NodeList& cn = childNodes();
NodeList::ConstIterator i = cn.constBegin();
while (i != cn.constEnd()) {
- if ((*i)->type() == Node::Document && (*i)->subType() == Node::QmlClass) {
+ if ((*i)->isQmlType()) {
if (origin->qmlModuleName() == (*i)->qmlModuleName())
return (*i);
}
@@ -2531,6 +2480,49 @@ const Node* NameCollisionNode::applyModuleName(const Node* origin) const
}
/*!
+ First, find all the colliding nodes that have the correct
+ type \a t and subtype \a st. If there is only one node
+ having the correct type and subtype, return that one.
+ If there is more than one node having the correct type
+ and subtype, then, in that subset, if there is only one
+ non-index node, return that one. If there are multiple
+ non-index nodes, return this collision node because we
+ can't disambiguate. Otherwise, if there are multiple
+ nodes having the correct type and subtype, return this
+ collision node because, again, we can't disambiguate.
+ But if there are no nodes at all that have the correct
+ type and subtype, return 0.
+ */
+Node* NameCollisionNode::disambiguate(Type t, SubType st)
+{
+ NodeList nl;
+ const NodeList& cn = childNodes();
+ NodeList::ConstIterator i = cn.constBegin();
+ while (i != cn.constEnd()) {
+ if ((*i)->type() == t) {
+ if ((st == NoSubType) || ((*i)->subType() == st))
+ nl.append((*i));
+ }
+ ++i;
+ }
+ Node* n = 0;
+ if (!nl.isEmpty()) {
+ i = nl.constBegin();
+ if (nl.size() == 1)
+ return (*i);
+ while (i != nl.constEnd()) {
+ if (!(*i)->isIndexNode()) {
+ if (n)
+ return this;
+ n = (*i);
+ }
+ ++i;
+ }
+ }
+ return n;
+}
+
+/*!
Construct the full document name for this node and return it.
*/
QString Node::fullDocumentName() const
@@ -2539,15 +2531,17 @@ QString Node::fullDocumentName() const
const Node* n = this;
do {
- if (!n->name().isEmpty() && n->type() != Node::QmlPropertyGroup)
+ if (!n->name().isEmpty() && !n->isQmlPropertyGroup())
pieces.insert(0, n->name());
- if (n->type() == Node::Document) {
- if ((n->subType() == Node::QmlClass) && !n->qmlModuleName().isEmpty())
- pieces.insert(0, n->qmlModuleName());
+ if (n->isQmlType() && !n->qmlModuleName().isEmpty()) {
+ pieces.insert(0, n->qmlModuleName());
break;
}
+ if (n->isDocNode())
+ break;
+
// Examine the parent node if one exists.
if (n->parent())
n = n->parent();
@@ -2557,7 +2551,7 @@ QString Node::fullDocumentName() const
// Create a name based on the type of the ancestor node.
QString concatenator = "::";
- if ((n->type() == Node::Document) && (n->subType() != Node::QmlClass))
+ if (n->isDocNode())
concatenator = QLatin1Char('#');
return pieces.join(concatenator);
@@ -2732,16 +2726,15 @@ QString Node::idForNode() const
}
}
else if (parent_) {
- if (parent_->type() == Class)
+ if (parent_->isClass())
str = "class-member-" + func->name();
- else if (parent_->type() == Namespace)
+ else if (parent_->isNamespace())
str = "namespace-member-" + func->name();
+ else if (parent_->isQmlType())
+ str = "qml-method-" + parent_->name().toLower() + "-" + func->name();
else if (parent_->type() == Document) {
- if (parent_->subType() == QmlClass)
- str = "qml-method-" + parent_->name().toLower() + "-" + func->name();
- else
- qDebug() << "qdoc internal error: Node subtype not handled:"
- << parent_->subType() << func->name();
+ qDebug() << "qdoc internal error: Node subtype not handled:"
+ << parent_->subType() << func->name();
}
else
qDebug() << "qdoc internal error: Node type not handled:"
@@ -2752,15 +2745,16 @@ QString Node::idForNode() const
str += QLatin1Char('-') + QString::number(func->overloadNumber());
}
break;
+ case Node::QmlType:
+ str = "qml-class-" + name();
+ break;
+ case Node::QmlBasicType:
+ str = "qml-basic-type-" + name();
+ break;
case Node::Document:
{
switch (subType()) {
- case Node::QmlClass:
- str = "qml-class-" + name();
- break;
case Node::Page:
- case Node::Group:
- case Node::Module:
case Node::HeaderFile:
str = title();
if (str.isEmpty()) {
@@ -2778,12 +2772,6 @@ QString Node::idForNode() const
str = name();
str.replace(QLatin1Char('/'), QLatin1Char('-'));
break;
- case Node::QmlBasicType:
- str = "qml-basic-type-" + name();
- break;
- case Node::QmlModule:
- str = "qml-module-" + name();
- break;
case Node::Collision:
str = title();
str.replace(": ","-");
@@ -2795,6 +2783,19 @@ QString Node::idForNode() const
}
}
break;
+ case Node::Group:
+ case Node::Module:
+ str = title();
+ if (str.isEmpty()) {
+ str = name();
+ if (str.endsWith(".html"))
+ str.remove(str.size()-5,5);
+ }
+ str.replace(QLatin1Char('/'), QLatin1Char('-'));
+ break;
+ case Node::QmlModule:
+ str = "qml-module-" + name();
+ break;
case Node::QmlProperty:
str = "qml-property-" + name();
break;
@@ -2855,10 +2856,93 @@ void InnerNode::printChildren(const QString& title)
}
/*!
- Prints the inner node's list of members.
+ Returns \c true if the collection node's member list is
+ not empty.
+ */
+bool CollectionNode::hasMembers() const
+{
+ return !members_.isEmpty();
+}
+
+/*!
+ Appends \a node to the collection node's member list, if
+ and only if it isn't already in the member list.
+ */
+void CollectionNode::addMember(Node* node)
+{
+ if (!members_.contains(node))
+ members_.append(node);
+}
+
+/*!
+ Returns \c true if this collection node contains at least
+ one namespace node.
+ */
+bool CollectionNode::hasNamespaces() const
+{
+ if (!members_.isEmpty()) {
+ NodeList::const_iterator i = members_.begin();
+ while (i != members_.end()) {
+ if ((*i)->isNamespace())
+ return true;
+ ++i;
+ }
+ }
+ return false;
+}
+
+/*!
+ Returns \c true if this collection node contains at least
+ one class node.
+ */
+bool CollectionNode::hasClasses() const
+{
+ if (!members_.isEmpty()) {
+ NodeList::const_iterator i = members_.begin();
+ while (i != members_.end()) {
+ if ((*i)->isClass())
+ return true;
+ ++i;
+ }
+ }
+ return false;
+}
+
+/*!
+ Loads \a out with all this collection node's members that
+ are namespace nodes.
+ */
+void CollectionNode::getMemberNamespaces(NodeMap& out)
+{
+ out.clear();
+ NodeList::const_iterator i = members_.begin();
+ while (i != members_.end()) {
+ if ((*i)->isNamespace())
+ out.insert((*i)->name(),(*i));
+ ++i;
+ }
+}
+
+/*!
+ Loads \a out with all this collection node's members that
+ are class nodes.
+ */
+void CollectionNode::getMemberClasses(NodeMap& out)
+{
+ out.clear();
+ NodeList::const_iterator i = members_.begin();
+ while (i != members_.end()) {
+ if ((*i)->isClass())
+ out.insert((*i)->name(),(*i));
+ ++i;
+ }
+}
+
+/*!
+ Prints the collection node's list of members.
For debugging only.
*/
-void InnerNode::printMembers(const QString& title)
+void CollectionNode::printMembers(const QString& title)
{
qDebug() << title << name() << members_.size();
if (members_.size() > 0) {
@@ -2869,4 +2953,13 @@ void InnerNode::printMembers(const QString& title)
}
}
+/*!
+ Sets the document node's \a title. This is used for the page title.
+ */
+void CollectionNode::setTitle(const QString& title)
+{
+ title_ = title;
+ parent()->addChild(this, title);
+}
+
QT_END_NAMESPACE
diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h
index 236b495bd0..4f9097d774 100644
--- a/src/tools/qdoc/node.h
+++ b/src/tools/qdoc/node.h
@@ -49,24 +49,32 @@
#include "codechunk.h"
#include "doc.h"
-#include "location.h"
-#include "text.h"
QT_BEGIN_NAMESPACE
class Node;
+class Tree;
+class EnumNode;
class ClassNode;
class InnerNode;
class ExampleNode;
+class TypedefNode;
class QmlClassNode;
class QDocDatabase;
+class FunctionNode;
+class PropertyNode;
class QmlModuleNode;
+class CollectionNode;
class QmlPropertyNode;
+class NameCollisionNode;
typedef QList<Node*> NodeList;
typedef QMap<QString, Node*> NodeMap;
typedef QMultiMap<QString, Node*> NodeMultiMap;
-typedef QMultiMap<QString, const ExampleNode*> ExampleNodeMap;
+typedef QPair<int, int> NodeTypePair;
+typedef QList<NodeTypePair> NodeTypeList;
+typedef QMap<QString, CollectionNode*> CNMap;
+typedef QMultiMap<QString, CollectionNode*> CNMultiMap;
class Node
{
@@ -74,6 +82,7 @@ class Node
public:
enum Type {
+ NoType,
Namespace,
Class,
Document,
@@ -82,11 +91,16 @@ public:
Function,
Property,
Variable,
+ Group,
+ Module,
+ QmlType,
+ QmlModule,
QmlPropertyGroup,
QmlProperty,
QmlSignal,
QmlSignalHandler,
QmlMethod,
+ QmlBasicType,
LastType
};
@@ -96,13 +110,8 @@ public:
HeaderFile,
File,
Image,
- Group,
- Module,
Page,
ExternalPage,
- QmlClass,
- QmlBasicType,
- QmlModule,
DitaMap,
Collision,
LastSubtype
@@ -165,10 +174,11 @@ public:
QString plainName() const;
QString plainFullName(const Node* relative = 0) const;
QString fullName(const Node* relative=0) const;
- const QString& baseName() const { return baseName_; }
- bool hasBaseName() const { return !baseName_.isEmpty(); }
- void setBaseName(const QString& bn) { baseName_ = bn; }
+ const QString& fileNameBase() const { return fileNameBase_; }
+ bool hasFileNameBase() const { return !fileNameBase_.isEmpty(); }
+ void setFileNameBase(const QString& t) { fileNameBase_ = t; }
+
void setAccess(Access access) { access_ = access; }
void setLocation(const Location& location) { loc_ = location; }
void setDoc(const Doc& doc, bool replace = false);
@@ -181,8 +191,7 @@ public:
void setSince(const QString &since);
void setRelates(InnerNode* pseudoParent);
void setModuleName(const QString &name) { moduleName_ = name; }
- void setLink(LinkType linkType, const QString &link, const QString &desc);
- void setUrl(const QString &url);
+ void setUrl(const QString& url) { url_ = url; }
void setTemplateStuff(const QString &templateStuff) { templateStuff_ = templateStuff; }
void setReconstitutedBrief(const QString &t) { reconstitutedBrief_ = t; }
void setPageType(PageType t) { pageType_ = t; }
@@ -190,14 +199,18 @@ public:
void setParent(InnerNode* n) { parent_ = n; }
void setIndexNodeFlag() { indexNodeFlag_ = true; }
virtual void setOutputFileName(const QString& ) { }
- void markSeen() { seen_ = true; }
- void markNotSeen() { seen_ = false; }
virtual bool isInnerNode() const = 0;
+ virtual bool isDocNode() const { return false; }
+ virtual bool isCollectionNode() const { return false; }
+ virtual bool isGroup() const { return false; }
+ virtual bool isModule() const { return false; }
virtual bool isQmlModule() const { return false; }
virtual bool isQmlType() const { return false; }
+ virtual bool isQmlBasicType() const { return false; }
virtual bool isExample() const { return false; }
virtual bool isExampleFile() const { return false; }
+ virtual bool isHeaderFile() const { return false; }
virtual bool isLeaf() const { return false; }
virtual bool isReimp() const { return false; }
virtual bool isFunction() const { return false; }
@@ -210,7 +223,6 @@ public:
virtual bool isCollisionNode() const { return false; }
virtual bool isAttached() const { return false; }
virtual bool isAlias() const { return false; }
- virtual bool isGroup() const { return false; }
virtual bool isWrapper() const;
virtual bool isReadOnly() const { return false; }
virtual bool isDefault() const { return false; }
@@ -221,34 +233,50 @@ public:
virtual bool hasClasses() const { return false; }
virtual void setAbstract(bool ) { }
virtual void setWrapper() { }
- virtual QString title() const { return QString(); }
+ virtual QString title() const { return name(); }
+ virtual QString fullTitle() const { return name(); }
+ virtual QString subTitle() const { return QString(); }
+ virtual void setTitle(const QString& ) { }
+ virtual void setSubTitle(const QString& ) { }
virtual QmlPropertyNode* hasQmlProperty(const QString& ) const { return 0; }
virtual void getMemberNamespaces(NodeMap& ) { }
virtual void getMemberClasses(NodeMap& ) { }
virtual bool isInternal() const;
virtual void setDataType(const QString& ) { }
virtual void setReadOnly(bool ) { }
+ virtual Node* disambiguate(Type , SubType ) { return this; }
+ virtual bool wasSeen() const { return false; }
+ virtual void appendGroupName(const QString& ) { }
+ virtual QString element() const { return QString(); }
+ virtual Tree* tree() const;
bool isIndexNode() const { return indexNodeFlag_; }
- bool wasSeen() const { return seen_; }
Type type() const { return nodeType_; }
virtual SubType subType() const { return NoSubType; }
+ bool match(const NodeTypeList& types) const;
InnerNode* parent() const { return parent_; }
+ const Node* root() const;
InnerNode* relates() const { return relatesTo_; }
const QString& name() const { return name_; }
- const QMap<LinkType, QPair<QString,QString> >& links() const { return linkMap_; }
QString moduleName() const;
- QString url() const;
+ QString url() const { return url_; }
virtual QString nameForLists() const { return name_; }
virtual QString outputFileName() const { return QString(); }
virtual QString obsoleteLink() const { return QString(); }
virtual void setObsoleteLink(const QString& ) { };
+ virtual void setQtVariable(const QString& ) { }
+ virtual QString qtVariable() const { return QString(); }
+
+ const QMap<LinkType, QPair<QString,QString> >& links() const { return linkMap_; }
+ void setLink(LinkType linkType, const QString &link, const QString &desc);
Access access() const { return access_; }
QString accessString() const;
const Location& location() const { return loc_; }
const Doc& doc() const { return doc_; }
+ bool hasDoc() const { return !doc_.isEmpty(); }
Status status() const { return status_; }
Status inheritedStatus() const;
+ bool isObsolete() const { return (status_ == Obsolete); }
ThreadSafeness threadSafeness() const;
ThreadSafeness inheritedThreadSafeness() const;
QString since() const { return since_; }
@@ -274,7 +302,6 @@ public:
virtual void setQmlModule(QmlModuleNode* ) { }
virtual ClassNode* classNode() { return 0; }
virtual void setClassNode(ClassNode* ) { }
- virtual void clearCurrentChild() { }
virtual const Node* applyModuleName(const Node* ) const { return 0; }
virtual QString idNumber() { return "0"; }
QmlClassNode* qmlClassNode();
@@ -293,6 +320,8 @@ public:
static QString nodeSubtypeString(unsigned t);
static int incPropertyGroupCount();
static void clearPropertyGroupCount();
+ static void initialize();
+ static Type goal(const QString& t) { return goals_.value(t); }
protected:
Node(Type type, InnerNode* parent, const QString& name);
@@ -305,7 +334,6 @@ private:
PageType pageType_;
Status status_;
bool indexNodeFlag_;
- bool seen_;
InnerNode* parent_;
InnerNode* relatesTo_;
@@ -313,7 +341,7 @@ private:
Location loc_;
Doc doc_;
QMap<LinkType, QPair<QString, QString> > linkMap_;
- QString baseName_;
+ QString fileNameBase_;
QString moduleName_;
QString url_;
QString since_;
@@ -323,51 +351,34 @@ private:
QString outSubDir_;
static QStringMap operators_;
static int propertyGroupCount_;
+ static QMap<QString,Node::Type> goals_;
};
-class FunctionNode;
-class EnumNode;
-class NameCollisionNode;
-
class InnerNode : public Node
{
public:
virtual ~InnerNode();
- Node* findChildNodeByName(const QString& name);
- Node* findChildNodeByName(const QString& name, bool qml);
- Node* findChildNodeByNameAndType(const QString& name, Type type);
+ Node* findChildNode(const QString& name) const;
+ Node* findChildNode(const QString& name, bool qml) const;
+ Node* findChildNode(const QString& name, Type type);
void findNodes(const QString& name, QList<Node*>& n);
- FunctionNode* findFunctionNode(const QString& name);
+ FunctionNode* findFunctionNode(const QString& name) const;
FunctionNode* findFunctionNode(const FunctionNode* clone);
void addInclude(const QString &include);
void setIncludes(const QStringList &includes);
void setOverload(const FunctionNode* func, bool overlode);
void normalizeOverloads();
void makeUndocumentedChildrenInternal();
- void clearCurrentChildPointers();
void deleteChildren();
void removeFromRelated();
virtual bool isInnerNode() const { return true; }
virtual bool isLeaf() const { return false; }
- const Node* findChildNodeByName(const QString& name) const;
- const Node* findChildNodeByName(const QString& name, bool qml) const;
- const Node* findChildNodeByNameAndType(const QString& name, Type type) const;
- const FunctionNode* findFunctionNode(const QString& name) const;
- const FunctionNode* findFunctionNode(const FunctionNode* clone) const;
const EnumNode* findEnumNodeForValue(const QString &enumValue) const;
const NodeList & childNodes() const { return children_; }
const NodeList & relatedNodes() const { return related_; }
- virtual void addMember(Node* node);
- const NodeList& members() const { return members_; }
- virtual bool hasMembers() const;
- virtual bool hasNamespaces() const;
- virtual bool hasClasses() const;
- virtual void getMemberNamespaces(NodeMap& out);
- virtual void getMemberClasses(NodeMap& out);
-
int count() const { return children_.size(); }
int overloadNumber(const FunctionNode* func) const;
NodeList overloads(const QString &funcName) const;
@@ -377,14 +388,13 @@ public:
QStringList secondaryKeys();
const QStringList& pageKeywords() const { return pageKeywds; }
virtual void addPageKeywords(const QString& t) { pageKeywds << t; }
- virtual void setCurrentChild() { }
- virtual void setCurrentChild(InnerNode* ) { }
virtual void setOutputFileName(const QString& f) { outputFileName_ = f; }
virtual QString outputFileName() const { return outputFileName_; }
virtual QmlPropertyNode* hasQmlProperty(const QString& ) const;
-
+ void addChild(Node* child, const QString& title);
+ const QStringList& groupNames() const { return groupNames_; }
+ virtual void appendGroupName(const QString& t) { groupNames_.append(t); }
void printChildren(const QString& title);
- void printMembers(const QString& title);
protected:
InnerNode(Type type, InnerNode* parent, const QString& name);
@@ -401,8 +411,8 @@ private:
QString outputFileName_;
QStringList pageKeywds;
QStringList includes_;
+ QStringList groupNames_;
NodeList children_;
- NodeList members_;
NodeList enumChildren_;
NodeList related_;
QMap<QString, Node*> childMap;
@@ -430,28 +440,31 @@ public:
NamespaceNode(InnerNode* parent, const QString& name);
virtual ~NamespaceNode() { }
virtual bool isNamespace() const { return true; }
-};
+ virtual Tree* tree() const { return (parent() ? parent()->tree() : tree_); }
+ void setTree(Tree* t) { tree_ = t; }
-class ClassNode;
+ private:
+ Tree* tree_;
+};
struct RelatedClass
{
RelatedClass() { }
- RelatedClass(Node::Access access0,
- ClassNode* node0,
- const QString& dataTypeWithTemplateArgs0 = QString())
- : access(access0),
- node(node0),
- dataTypeWithTemplateArgs(dataTypeWithTemplateArgs0) { }
+ // constructor for resolved base class
+ RelatedClass(Node::Access access, ClassNode* node)
+ : access_(access), node_(node) { }
+ // constructor for unresolved base class
+ RelatedClass(Node::Access access, const QStringList& path, const QString& signature)
+ : access_(access), node_(0), path_(path), signature_(signature) { }
QString accessString() const;
+ bool isPrivate() const { return (access_ == Node::Private); }
- Node::Access access;
- ClassNode* node;
- QString dataTypeWithTemplateArgs;
+ Node::Access access_;
+ ClassNode* node_;
+ QStringList path_;
+ QString signature_;
};
-class PropertyNode;
-
class ClassNode : public InnerNode
{
public:
@@ -463,14 +476,19 @@ public:
virtual void setObsoleteLink(const QString& t) { obsoleteLink_ = t; }
virtual void setWrapper() { wrapper_ = true; }
- void addBaseClass(Access access,
- ClassNode* node,
- const QString &dataTypeWithTemplateArgs = QString());
+ void addResolvedBaseClass(Access access, ClassNode* node);
+ void addDerivedClass(Access access, ClassNode* node);
+ void addUnresolvedBaseClass(Access access, const QStringList& path, const QString& signature);
void fixBaseClasses();
+ void fixPropertyUsingBaseClasses(PropertyNode* pn);
- const QList<RelatedClass> &baseClasses() const { return bases; }
- const QList<RelatedClass> &derivedClasses() const { return derived; }
- const QList<RelatedClass> &ignoredBaseClasses() const { return ignoredBases; }
+ QList<RelatedClass>& baseClasses() { return bases_; }
+ QList<RelatedClass>& derivedClasses() { return derived_; }
+ QList<RelatedClass>& ignoredBaseClasses() { return ignoredBases_; }
+
+ const QList<RelatedClass> &baseClasses() const { return bases_; }
+ const QList<RelatedClass> &derivedClasses() const { return derived_; }
+ const QList<RelatedClass> &ignoredBaseClasses() const { return ignoredBases_; }
QString serviceName() const { return sname; }
void setServiceName(const QString& value) { sname = value; }
@@ -482,9 +500,9 @@ public:
QmlClassNode* findQmlBaseNode();
private:
- QList<RelatedClass> bases;
- QList<RelatedClass> derived;
- QList<RelatedClass> ignoredBases;
+ QList<RelatedClass> bases_;
+ QList<RelatedClass> derived_;
+ QList<RelatedClass> ignoredBases_;
bool abstract_;
bool wrapper_;
QString sname;
@@ -502,49 +520,26 @@ public:
PageType ptype);
virtual ~DocNode() { }
- void setQtVariable(const QString &variable) { qtVariable_ = variable; }
- void setTitle(const QString &title) { title_ = title; }
- void setSubTitle(const QString &subTitle) { subtitle_ = subTitle; }
+ virtual void setTitle(const QString &title);
+ virtual void setSubTitle(const QString &subTitle) { subtitle_ = subTitle; }
- QString qtVariable() const { return qtVariable_; }
SubType subType() const { return nodeSubtype_; }
- virtual QString title() const;
+ virtual QString title() const { return title_; }
virtual QString fullTitle() const;
virtual QString subTitle() const;
virtual QString imageFileName() const { return QString(); }
virtual QString nameForLists() const { return title(); }
virtual void setImageFileName(const QString& ) { }
- virtual bool isGroup() const { return (subType() == Node::Group); }
+ virtual bool isHeaderFile() const { return (subType() == Node::HeaderFile); }
virtual bool isExample() const { return (subType() == Node::Example); }
virtual bool isExampleFile() const { return (parent() && parent()->isExample()); }
virtual bool isExternalPage() const { return nodeSubtype_ == ExternalPage; }
+ virtual bool isDocNode() const { return true; }
protected:
SubType nodeSubtype_;
QString title_;
QString subtitle_;
-
-private:
- QString qtVariable_;
-};
-
-class QmlModuleNode : public DocNode
-{
- public:
- QmlModuleNode(InnerNode* parent, const QString& name)
- : DocNode(parent, name, Node::QmlModule, Node::OverviewPage) { }
- virtual ~QmlModuleNode() { }
-
- virtual bool isQmlModule() const { return true; }
- virtual QString qmlModuleName() const { return qmlModuleName_; }
- virtual QString qmlModuleVersion() const { return qmlModuleVersionMajor_ + "." + qmlModuleVersionMinor_; }
- virtual QString qmlModuleIdentifier() const { return qmlModuleName_ + qmlModuleVersionMajor_; }
- virtual void setQmlModuleInfo(const QString& );
-
- private:
- QString qmlModuleName_;
- QString qmlModuleVersionMajor_;
- QString qmlModuleVersionMinor_;
};
class NameCollisionNode : public DocNode
@@ -552,35 +547,28 @@ class NameCollisionNode : public DocNode
public:
NameCollisionNode(InnerNode* child);
~NameCollisionNode();
- const InnerNode* currentChild() const { return current; }
- virtual void setCurrentChild(InnerNode* child) { current = child; }
- virtual void clearCurrentChild() { current = 0; }
virtual bool isQmlNode() const;
virtual bool isCollisionNode() const { return true; }
virtual const Node* applyModuleName(const Node* origin) const;
+ virtual Node* disambiguate(Type t, SubType st);
InnerNode* findAny(Node::Type t, Node::SubType st);
void addCollision(InnerNode* child);
const QMap<QString,QString>& linkTargets() const { return targets; }
void addLinkTarget(const QString& t, const QString& v) { targets.insert(t,v); }
private:
- InnerNode* current;
QMap<QString,QString> targets;
};
class ExampleNode : public DocNode
{
public:
- ExampleNode(InnerNode* parent, const QString& name);
+ ExampleNode(InnerNode* parent, const QString& name)
+ : DocNode(parent, name, Node::Example, Node::ExamplePage) { }
virtual ~ExampleNode() { }
virtual QString imageFileName() const { return imageFileName_; }
virtual void setImageFileName(const QString& ifn) { imageFileName_ = ifn; }
- static void terminate() { exampleNodeMap.clear(); }
-
-public:
- static ExampleNodeMap exampleNodeMap;
-
private:
QString imageFileName_;
};
@@ -605,7 +593,7 @@ struct ImportRec {
typedef QList<ImportRec> ImportList;
-class QmlClassNode : public DocNode
+class QmlClassNode : public InnerNode
{
public:
QmlClassNode(InnerNode* parent, const QString& name);
@@ -615,8 +603,6 @@ public:
virtual bool isQtQuickNode() const { return (qmlModuleName() == QLatin1String("QtQuick")); }
virtual ClassNode* classNode() { return cnode_; }
virtual void setClassNode(ClassNode* cn) { cnode_ = cn; }
- virtual void setCurrentChild();
- virtual void clearCurrentChild();
virtual bool isAbstract() const { return abstract_; }
virtual bool isWrapper() const { return wrapper_; }
virtual void setAbstract(bool b) { abstract_ = b; }
@@ -632,10 +618,11 @@ public:
virtual void setQmlModule(QmlModuleNode* t) { qmlModule_ = t; }
const ImportList& importList() const { return importList_; }
void setImportList(const ImportList& il) { importList_ = il; }
- const QString& qmlBaseName() const { return baseName_; }
- void setQmlBaseName(const QString& name) { baseName_ = name; }
- const QmlClassNode* qmlBaseNode() const { return baseNode_; }
- void setQmlBaseNode(QmlClassNode* b) { baseNode_ = b; }
+ const QString& qmlBaseName() const { return qmlBaseName_; }
+ void setQmlBaseName(const QString& name) { qmlBaseName_ = name; }
+ bool qmlBaseNodeNotSet() const { return (qmlBaseNode_ == 0); }
+ QmlClassNode* qmlBaseNode();
+ void setQmlBaseNode(QmlClassNode* b) { qmlBaseNode_ = b; }
void requireCppClass() { cnodeRequired_ = true; }
bool cppClassRequired() const { return cnodeRequired_; }
static void addInheritedBy(const QString& base, Node* sub);
@@ -651,20 +638,21 @@ private:
bool cnodeRequired_;
bool wrapper_;
ClassNode* cnode_;
- QString baseName_;
+ QString qmlBaseName_;
QString obsoleteLink_;
QmlModuleNode* qmlModule_;
- QmlClassNode* baseNode_;
+ QmlClassNode* qmlBaseNode_;
ImportList importList_;
};
-class QmlBasicTypeNode : public DocNode
+class QmlBasicTypeNode : public InnerNode
{
public:
QmlBasicTypeNode(InnerNode* parent,
const QString& name);
virtual ~QmlBasicTypeNode() { }
virtual bool isQmlNode() const { return true; }
+ virtual bool isQmlBasicType() const { return true; }
};
class QmlPropertyGroupNode : public InnerNode
@@ -681,14 +669,12 @@ public:
virtual QString idNumber();
virtual bool isQmlPropertyGroup() const { return true; }
- const QString& element() const { return parent()->name(); }
+ virtual QString element() const { return parent()->name(); }
private:
int idNumber_;
};
-class QmlPropertyNode;
-
class QmlPropertyNode : public LeafNode
{
Q_DECLARE_TR_FUNCTIONS(QDoc::QmlPropertyNode)
@@ -711,7 +697,7 @@ public:
bool isReadOnlySet() const { return (readOnly_ != FlagValueDefault); }
bool isStored() const { return fromFlagValue(stored_,true); }
bool isDesignable() const { return fromFlagValue(designable_,false); }
- bool isWritable(QDocDatabase* qdb);
+ bool isWritable();
virtual bool isDefault() const { return isdefault_; }
virtual bool isReadOnly() const { return fromFlagValue(readOnly_,false); }
virtual bool isAlias() const { return isAlias_; }
@@ -722,10 +708,10 @@ public:
virtual QString qmlModuleName() const { return parent()->qmlModuleName(); }
virtual QString qmlModuleVersion() const { return parent()->qmlModuleVersion(); }
virtual QString qmlModuleIdentifier() const { return parent()->qmlModuleIdentifier(); }
+ virtual QString element() const;
- PropertyNode* correspondingProperty(QDocDatabase* qdb);
-
- const QString& element() const { return static_cast<QmlPropertyGroupNode*>(parent())->element(); }
+ private:
+ PropertyNode* findCorrespondingCppProperty();
private:
QString type_;
@@ -743,21 +729,15 @@ public:
EnumItem() { }
EnumItem(const QString& name, const QString& value)
: nam(name), val(value) { }
- EnumItem(const QString& name, const QString& value, const Text &txt)
- : nam(name), val(value), txt(txt) { }
const QString& name() const { return nam; }
const QString& value() const { return val; }
- const Text &text() const { return txt; }
private:
QString nam;
QString val;
- Text txt;
};
-class TypedefNode;
-
class EnumNode : public LeafNode
{
public:
@@ -831,8 +811,6 @@ private:
QString def;
};
-class PropertyNode;
-
class FunctionNode : public LeafNode
{
public:
@@ -886,7 +864,7 @@ public:
QStringList reconstructParams(bool values = false) const;
QString signature(bool values = false) const;
- const QString& element() const { return parent()->name(); }
+ virtual QString element() const { return parent()->name(); }
virtual bool isAttached() const { return attached_; }
virtual bool isQmlNode() const {
return ((type() == QmlSignal) ||
@@ -1049,6 +1027,94 @@ public:
const DitaRefList& map() const { return doc().ditamap(); }
};
+class CollectionNode : public InnerNode
+{
+ public:
+ CollectionNode(Type type, InnerNode* parent, const QString& name)
+ : InnerNode(type, parent, name), seen_(false) {
+ setPageType(Node::OverviewPage);
+ }
+ virtual ~CollectionNode() { }
+
+ virtual bool isCollectionNode() const { return true; }
+ virtual void addMember(Node* node);
+ virtual bool hasMembers() const;
+ virtual bool hasNamespaces() const;
+ virtual bool hasClasses() const;
+ virtual void getMemberNamespaces(NodeMap& out);
+ virtual void getMemberClasses(NodeMap& out);
+ virtual bool wasSeen() const { return seen_; }
+ virtual QString title() const { return title_; }
+ virtual QString subTitle() const { return subtitle_; }
+ virtual QString fullTitle() const { return title_; }
+ virtual QString nameForLists() const { return title_; }
+ virtual void setTitle(const QString &title);
+ virtual void setSubTitle(const QString &subTitle) { subtitle_ = subTitle; }
+
+ const NodeList& members() const { return members_; }
+ void printMembers(const QString& title);
+
+ void markSeen() { seen_ = true; }
+ void markNotSeen() { seen_ = false; }
+
+ private:
+ bool seen_;
+ QString title_;
+ QString subtitle_;
+ NodeList members_;
+};
+
+class GroupNode : public CollectionNode
+{
+ public:
+ GroupNode(InnerNode* parent, const QString& name)
+ : CollectionNode(Node::Group, parent, name) { }
+ virtual ~GroupNode() { }
+
+ virtual bool isGroup() const { return true; }
+};
+
+class ModuleNode : public CollectionNode
+{
+ public:
+ ModuleNode(InnerNode* parent, const QString& name)
+ : CollectionNode(Node::Module, parent, name) { }
+ virtual ~ModuleNode() { }
+
+ virtual bool isModule() const { return true; }
+ virtual void setQtVariable(const QString& v) { qtVariable_ = v; }
+ virtual QString qtVariable() const { return qtVariable_; }
+
+ private:
+ QString qtVariable_;
+};
+
+class QmlModuleNode : public CollectionNode
+{
+ public:
+ QmlModuleNode(InnerNode* parent, const QString& name)
+ : CollectionNode(Node::QmlModule, parent, name) { }
+ virtual ~QmlModuleNode() { }
+
+ virtual bool isQmlModule() const { return true; }
+ virtual QString qmlModuleName() const { return qmlModuleName_; }
+ virtual QString qmlModuleVersion() const {
+ return qmlModuleVersionMajor_ + "." + qmlModuleVersionMinor_;
+ }
+ virtual QString qmlModuleIdentifier() const {
+ return qmlModuleName_ + qmlModuleVersionMajor_;
+ }
+ virtual void setQmlModuleInfo(const QString& );
+ virtual void setQtVariable(const QString& v) { qtVariable_ = v; }
+ virtual QString qtVariable() const { return qtVariable_; }
+
+ private:
+ QString qmlModuleName_;
+ QString qmlModuleVersionMajor_;
+ QString qmlModuleVersionMinor_;
+ QString qtVariable_;
+};
+
QT_END_NAMESPACE
#endif
diff --git a/src/tools/qdoc/puredocparser.cpp b/src/tools/qdoc/puredocparser.cpp
index 644fe05438..e8292e787e 100644
--- a/src/tools/qdoc/puredocparser.cpp
+++ b/src/tools/qdoc/puredocparser.cpp
@@ -202,7 +202,7 @@ bool PureDocParser::processQdocComments()
}
}
- Node* treeRoot = QDocDatabase::qdocDB()->treeRoot();
+ Node* treeRoot = QDocDatabase::qdocDB()->primaryTreeRoot();
NodeList::Iterator n = nodes.begin();
QList<Doc>::Iterator d = docs.begin();
while (n != nodes.end()) {
diff --git a/src/tools/qdoc/puredocparser.h b/src/tools/qdoc/puredocparser.h
index 0174af7a4e..b664367527 100644
--- a/src/tools/qdoc/puredocparser.h
+++ b/src/tools/qdoc/puredocparser.h
@@ -56,7 +56,6 @@ QT_BEGIN_NAMESPACE
class Config;
class Node;
class QString;
-class Tree;
class PureDocParser : public CppCodeParser
{
diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp
index 1011a3ac97..d43fdf4970 100644
--- a/src/tools/qdoc/qdocdatabase.cpp
+++ b/src/tools/qdoc/qdocdatabase.cpp
@@ -51,46 +51,434 @@ QT_BEGIN_NAMESPACE
static NodeMap emptyNodeMap_;
static NodeMultiMap emptyNodeMultiMap_;
+bool QDocDatabase::debug = false;
+
+/*! \class QDocForest
+ This class manages a collection of trees. Each tree is an
+ instance of class Tree, which is a private class.
+
+ The forest is populated as each index file is loaded.
+ Each index file adds a tree to the forest. Each tree
+ is named with the name of the module it represents.
+
+ The search order is created by searchOrder(), if it has
+ not already been created. The search order and module
+ names arrays have parallel structure, i.e. modulNames_[i]
+ is the module name of the Tree at searchOrder_[i].
+ */
+
+/*!
+ Destroys the qdoc forest. This requires deleting
+ each Tree in the forest. Note that the forest has
+ been transferred into the search order array, so
+ what is really being used to destroy the forest
+ is the search order array.
+ */
+QDocForest::~QDocForest()
+{
+ for (int i=0; i<searchOrder_.size(); ++i)
+ delete searchOrder_.at(i);
+ forest_.clear();
+ searchOrder_.clear();
+ indexSearchOrder_.clear();
+ moduleNames_.clear();
+ primaryTree_ = 0;
+}
+
+/*!
+ Initializes the forest prior to a traversal and
+ returns a pointer to the root node of the primary
+ tree. If the forest is empty, it return 0
+ */
+NamespaceNode* QDocForest::firstRoot()
+{
+ currentIndex_ = 0;
+ return (!searchOrder().isEmpty() ? searchOrder()[0]->root() : 0);
+}
+
+/*!
+ Increments the forest's current tree index. If the current
+ tree index is still within the forest, the function returns
+ the root node of the current tree. Otherwise it returns 0.
+ */
+NamespaceNode* QDocForest::nextRoot()
+{
+ ++currentIndex_;
+ return (currentIndex_ < searchOrder().size() ? searchOrder()[currentIndex_]->root() : 0);
+}
+
+/*!
+ Initializes the forest prior to a traversal and
+ returns a pointer to the primary tree. If the
+ forest is empty, it returns 0.
+ */
+Tree* QDocForest::firstTree()
+{
+ currentIndex_ = 0;
+ return (!searchOrder().isEmpty() ? searchOrder()[0] : 0);
+}
+
+/*!
+ Increments the forest's current tree index. If the current
+ tree index is still within the forest, the function returns
+ the pointer to the current tree. Otherwise it returns 0.
+ */
+Tree* QDocForest::nextTree()
+{
+ ++currentIndex_;
+ return (currentIndex_ < searchOrder().size() ? searchOrder()[currentIndex_] : 0);
+}
+
+/*!
+ \fn Tree* QDocForest::primaryTree()
+
+ Returns the pointer to the primary tree.
+ */
+
+/*!
+ If the search order array is empty, create the search order.
+ If the search order array is not empty, do nothing.
+ */
+void QDocForest::setSearchOrder()
+{
+ if (!searchOrder_.isEmpty())
+ return;
+ QString primaryName = primaryTree()->moduleName();
+ searchOrder_.clear();
+ searchOrder_.reserve(forest_.size()+1);
+ moduleNames_.reserve(forest_.size()+1);
+ searchOrder_.append(primaryTree_);
+ moduleNames_.append(primaryName);
+ QMap<QString, Tree*>::iterator i;
+ if (primaryName != "QtCore") {
+ i = forest_.find("QtCore");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtCore");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtGui") {
+ i = forest_.find("QtGui");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtGui");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtNetwork") {
+ i = forest_.find("QtNetwork");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtNetwork");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtOpenGL") {
+ i = forest_.find("QtOpenGL");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtOpenGL");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtWidgets") {
+ i = forest_.find("QtWidgets");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtWidgets");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtSql") {
+ i = forest_.find("QtSql");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtSql");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtXml") {
+ i = forest_.find("QtXml");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtXml");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtSvg") {
+ i = forest_.find("QtSvg");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtSvg");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtDoc") {
+ i = forest_.find("QtDoc");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtDoc");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtQuick") {
+ i = forest_.find("QtQuick");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtQuick");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtQml") {
+ i = forest_.find("QtQml");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtQml");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtPrintSupport") {
+ i = forest_.find("QtPrintSupport");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtPrintSupport");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtGraphicalEffects") {
+ i = forest_.find("QtGraphicalEffects");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtGraphicalEffects");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtConcurrent") {
+ i = forest_.find("QtConcurrent");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtConcurrent");
+ forest_.erase(i);
+ }
+ }
+#if 0
+ if (primaryName != "zzz") {
+ i = forest_.find("zzz");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("zzz");
+ forest_.erase(i);
+ }
+ }
+#endif
+ /*
+ If any trees remain in the forest, just add them
+ to the search order sequentially, because we don't
+ know any better at this point.
+ */
+ if (!forest_.isEmpty()) {
+ i = forest_.begin();
+ while (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append(i.key());
+ ++i;
+ }
+ forest_.clear();
+ }
+
+ /*
+ Rebuild the forest after constructing the search order.
+ It was destroyed during construction of the search order,
+ but it is needed for module-specific searches.
+ */
+ for (int i=0; i<searchOrder_.size(); ++i) {
+ forest_.insert(moduleNames_.at(i).toLower(), searchOrder_.at(i));
+ }
+
+#if 0
+ qDebug() << " SEARCH ORDER:";
+ for (int i=0; i<moduleNames_.size(); ++i)
+ qDebug() << " " << i+1 << "." << moduleNames_.at(i);
+#endif
+}
+
+/*!
+ Returns an ordered array of Tree pointers that represents
+ the order in which the trees should be searched. The first
+ Tree in the array is the tree for the current module, i.e.
+ the module for which qdoc is generating documentation.
+
+ The other Tree pointers in the array represent the index
+ files that were loaded in preparation for generating this
+ module's documentation. Each Tree pointer represents one
+ index file. The index file Tree points have been ordered
+ heuristically to, hopefully, minimize searching. Thr order
+ will probably be changed.
+
+ If the search order array is empty, this function calls
+ indexSearchOrder(). The search order array is empty while
+ the index files are being loaded, but some searches must
+ be performed during this time, notably searches for base
+ class nodes. These searches require a temporary search
+ order. The temporary order changes throughout the loading
+ of the index files, but it is always the tree for the
+ current index file first, followed by the trees for the
+ index files that have already been loaded. The only
+ ordering required in this temporary search order is that
+ the current tree must be searched first.
+ */
+const QVector<Tree*>& QDocForest::searchOrder()
+{
+ if (searchOrder_.isEmpty())
+ return indexSearchOrder();
+ return searchOrder_;
+}
+
+/*!
+ There are two search orders used by qdoc when searching for
+ things. The normal search order is returned by searchOrder(),
+ but this normal search order is not known until all the index
+ files have been read. At that point, setSearchOrder() is
+ called.
+
+ During the reading of the index files, the vector holding
+ the normal search order remains empty. Whenever the search
+ order is requested, if that vector is empty, this function
+ is called to return a temporary search order, which includes
+ all the index files that have been read so far, plus the
+ one being read now. That one is prepended to the front of
+ the vector.
+ */
+const QVector<Tree*>& QDocForest::indexSearchOrder()
+{
+ if (forest_.size() > indexSearchOrder_.size())
+ indexSearchOrder_.prepend(primaryTree_);
+ return indexSearchOrder_;
+}
+
+/*!
+ Create a new Tree for the index file for the specified
+ \a module and add it to the forest. Return the pointer
+ to its root.
+ */
+NamespaceNode* QDocForest::newIndexTree(const QString& module)
+{
+ primaryTree_ = new Tree(module, qdb_);
+ forest_.insert(module, primaryTree_);
+ return primaryTree_->root();
+}
+
+/*!
+ Create a new Tree for use as the primary tree. This tree
+ will represent the primary module.
+ */
+void QDocForest::newPrimaryTree(const QString& module)
+{
+ primaryTree_ = new Tree(module, qdb_);
+}
+
+/*!
+ Searches the trees for a node named \a target and returns
+ a pointer to it if found. The \a relative node is the starting
+ point, but it only makes sense in the primary tree, which is
+ searched first. After the primary tree is searched, \a relative
+ is set to 0 for searching the index trees. When relative is 0,
+ the root nodes of the index trees are the starting points.
+ */
+const Node* QDocForest::resolveTarget(const QString& target, const Node* relative)
+{
+ QStringList path = target.split("::");
+ int flags = SearchBaseClasses | SearchEnumValues | NonFunction;
+
+ foreach (Tree* t, searchOrder()) {
+ const Node* n = t->findNode(path, relative, flags);
+ if (n)
+ return n;
+ relative = 0;
+ }
+ return 0;
+}
+
+/*!
+ Searches the Tree \a t for a type node named by the \a path
+ and returns a pointer to it if found. The \a relative node
+ is the starting point, but it only makes sense when searching
+ the primary tree. Therefore, when this function is called with
+ \a t being an index tree, \a relative is 0. When relative is 0,
+ the root node of \a t is the starting point.
+ */
+const Node* QDocForest::resolveTypeHelper(const QStringList& path, const Node* relative, Tree* t)
+{
+ int flags = SearchBaseClasses | SearchEnumValues | NonFunction;
+ return t->findNode(path, relative, flags);
+}
+
+/*!
+ This function merges all the collection maps for collection
+ nodes of node type \a t into the collection multimap \a cnmm,
+ which is cleared before starting.
+
+ This is mainly useful for groups, which often cross module
+ boundaries. It might be true that neither modules nor QML
+ modules cross module boundaries, but this function works for
+ those cases as well.
+ */
+void QDocForest::mergeCollectionMaps(Node::Type nt, CNMultiMap& cnmm)
+{
+ foreach (Tree* t, searchOrder()) {
+ const CNMap& cnm = t->getCollections(nt);
+ if (!cnm.isEmpty()) {
+ CNMap::const_iterator i = cnm.begin();
+ while (i != cnm.end()) {
+ if (!i.value()->isInternal())
+ cnmm.insert(i.key(), i.value());
+ ++i;
+ }
+ }
+ }
+}
/*! \class QDocDatabase
+ This class provides exclusive access to the qdoc database,
+ which consists of a forrest of trees and a lot of maps and
+ other useful data structures.
*/
QDocDatabase* QDocDatabase::qdocDB_ = NULL;
+NodeMap QDocDatabase::typeNodeMap_;
/*!
- Constructs the singleton qdoc database object.
- It constructs a singleton Tree object with this
- qdoc database pointer.
+ Constructs the singleton qdoc database object. The singleton
+ constructs the \a forest_ object, which is also a singleton.
+ \a showInternal_ is normally false. If it is true, qdoc will
+ write documentation for nodes marked \c internal.
*/
-QDocDatabase::QDocDatabase() : showInternal_(false)
+QDocDatabase::QDocDatabase() : showInternal_(false), forest_(this)
{
- tree_ = new Tree(this);
+ // nothing
}
/*!
- Destroys the qdoc database object. This requires deleting
- the tree of nodes, which deletes each node.
+ Destroys the qdoc database object. This requires destroying
+ the forest object, which contains an array of tree pointers.
+ Each tree is deleted.
*/
QDocDatabase::~QDocDatabase()
{
- masterMap_.clear();
- delete tree_;
+ // nothing.
}
-/*! \fn Tree* QDocDatabase::tree()
- Returns the pointer to the tree. This function is for compatibility
- with the current qdoc. It will be removed when the QDocDatabase class
- replaces the current structures.
- */
-
/*!
Creates the singleton. Allows only one instance of the class
to be created. Returns a pointer to the singleton.
*/
QDocDatabase* QDocDatabase::qdocDB()
{
- if (!qdocDB_)
+ if (!qdocDB_) {
qdocDB_ = new QDocDatabase;
+ initializeDB();
+ }
return qdocDB_;
}
@@ -106,36 +494,192 @@ void QDocDatabase::destroyQdocDB()
}
/*!
- \fn const DocNodeMap& QDocDatabase::groups() const
+ Initialize data structures in the singleton qdoc database.
+
+ In particular, the type node map is initialized with a lot
+ type names that don't refer to documented types. For example,
+ the C++ standard types are included. These might be documented
+ here at some point, but for now they are not. Other examples
+ include \c array and \c data, which are just generic names
+ used as place holders in function signatures that appear in
+ the documentation.
+
+ Also calls Node::initialize() to initialize the search goal map.
+ */
+void QDocDatabase::initializeDB()
+{
+ Node::initialize();
+ typeNodeMap_.insert( "accepted", 0);
+ typeNodeMap_.insert( "actionPerformed", 0);
+ typeNodeMap_.insert( "activated", 0);
+ typeNodeMap_.insert( "alias", 0);
+ typeNodeMap_.insert( "anchors", 0);
+ typeNodeMap_.insert( "any", 0);
+ typeNodeMap_.insert( "array", 0);
+ typeNodeMap_.insert( "autoSearch", 0);
+ typeNodeMap_.insert( "axis", 0);
+ typeNodeMap_.insert( "backClicked", 0);
+ typeNodeMap_.insert( "bool", 0);
+ typeNodeMap_.insert( "boomTime", 0);
+ typeNodeMap_.insert( "border", 0);
+ typeNodeMap_.insert( "buttonClicked", 0);
+ typeNodeMap_.insert( "callback", 0);
+ typeNodeMap_.insert( "char", 0);
+ typeNodeMap_.insert( "clicked", 0);
+ typeNodeMap_.insert( "close", 0);
+ typeNodeMap_.insert( "closed", 0);
+ typeNodeMap_.insert( "color", 0);
+ typeNodeMap_.insert( "cond", 0);
+ typeNodeMap_.insert( "data", 0);
+ typeNodeMap_.insert( "dataReady", 0);
+ typeNodeMap_.insert( "dateString", 0);
+ typeNodeMap_.insert( "dateTimeString", 0);
+ typeNodeMap_.insert( "datetime", 0);
+ typeNodeMap_.insert( "day", 0);
+ typeNodeMap_.insert( "deactivated", 0);
+ typeNodeMap_.insert( "double", 0);
+ typeNodeMap_.insert( "drag", 0);
+ typeNodeMap_.insert( "easing", 0);
+ typeNodeMap_.insert( "enumeration", 0);
+ typeNodeMap_.insert( "error", 0);
+ typeNodeMap_.insert( "exposure", 0);
+ typeNodeMap_.insert( "fatalError", 0);
+ typeNodeMap_.insert( "fileSelected", 0);
+ typeNodeMap_.insert( "flags", 0);
+ typeNodeMap_.insert( "float", 0);
+ typeNodeMap_.insert( "focus", 0);
+ typeNodeMap_.insert( "focusZone", 0);
+ typeNodeMap_.insert( "format", 0);
+ typeNodeMap_.insert( "framePainted", 0);
+ typeNodeMap_.insert( "from", 0);
+ typeNodeMap_.insert( "frontClicked", 0);
+ typeNodeMap_.insert( "function", 0);
+ typeNodeMap_.insert( "hasOpened", 0);
+ typeNodeMap_.insert( "hovered", 0);
+ typeNodeMap_.insert( "hoveredTitle", 0);
+ typeNodeMap_.insert( "hoveredUrl", 0);
+ typeNodeMap_.insert( "imageCapture", 0);
+ typeNodeMap_.insert( "imageProcessing", 0);
+ typeNodeMap_.insert( "index", 0);
+ typeNodeMap_.insert( "initialized", 0);
+ typeNodeMap_.insert( "int", 0);
+ typeNodeMap_.insert( "isLoaded", 0);
+ typeNodeMap_.insert( "item", 0);
+ typeNodeMap_.insert( "jsdict", 0);
+ typeNodeMap_.insert( "jsobject", 0);
+ typeNodeMap_.insert( "key", 0);
+ typeNodeMap_.insert( "keysequence", 0);
+ typeNodeMap_.insert( "list", 0);
+ typeNodeMap_.insert( "listViewClicked", 0);
+ typeNodeMap_.insert( "loadRequest", 0);
+ typeNodeMap_.insert( "locale", 0);
+ typeNodeMap_.insert( "location", 0);
+ typeNodeMap_.insert( "long", 0);
+ typeNodeMap_.insert( "message", 0);
+ typeNodeMap_.insert( "messageReceived", 0);
+ typeNodeMap_.insert( "mode", 0);
+ typeNodeMap_.insert( "month", 0);
+ typeNodeMap_.insert( "name", 0);
+ typeNodeMap_.insert( "number", 0);
+ typeNodeMap_.insert( "object", 0);
+ typeNodeMap_.insert( "offset", 0);
+ typeNodeMap_.insert( "ok", 0);
+ typeNodeMap_.insert( "openCamera", 0);
+ typeNodeMap_.insert( "openImage", 0);
+ typeNodeMap_.insert( "openVideo", 0);
+ typeNodeMap_.insert( "padding", 0);
+ typeNodeMap_.insert( "parent", 0);
+ typeNodeMap_.insert( "path", 0);
+ typeNodeMap_.insert( "photoModeSelected", 0);
+ typeNodeMap_.insert( "position", 0);
+ typeNodeMap_.insert( "precision", 0);
+ typeNodeMap_.insert( "presetClicked", 0);
+ typeNodeMap_.insert( "preview", 0);
+ typeNodeMap_.insert( "previewSelected", 0);
+ typeNodeMap_.insert( "progress", 0);
+ typeNodeMap_.insert( "puzzleLost", 0);
+ typeNodeMap_.insert( "qmlSignal", 0);
+ typeNodeMap_.insert( "real", 0);
+ typeNodeMap_.insert( "rectangle", 0);
+ typeNodeMap_.insert( "request", 0);
+ typeNodeMap_.insert( "requestId", 0);
+ typeNodeMap_.insert( "section", 0);
+ typeNodeMap_.insert( "selected", 0);
+ typeNodeMap_.insert( "send", 0);
+ typeNodeMap_.insert( "settingsClicked", 0);
+ typeNodeMap_.insert( "shoe", 0);
+ typeNodeMap_.insert( "short", 0);
+ typeNodeMap_.insert( "signed", 0);
+ typeNodeMap_.insert( "sizeChanged", 0);
+ typeNodeMap_.insert( "size_t", 0);
+ typeNodeMap_.insert( "sockaddr", 0);
+ typeNodeMap_.insert( "someOtherSignal", 0);
+ typeNodeMap_.insert( "sourceSize", 0);
+ typeNodeMap_.insert( "startButtonClicked", 0);
+ typeNodeMap_.insert( "state", 0);
+ typeNodeMap_.insert( "std::initializer_list", 0);
+ typeNodeMap_.insert( "std::list", 0);
+ typeNodeMap_.insert( "std::map", 0);
+ typeNodeMap_.insert( "std::pair", 0);
+ typeNodeMap_.insert( "std::string", 0);
+ typeNodeMap_.insert( "std::vector", 0);
+ typeNodeMap_.insert( "string", 0);
+ typeNodeMap_.insert( "stringlist", 0);
+ typeNodeMap_.insert( "swapPlayers", 0);
+ typeNodeMap_.insert( "symbol", 0);
+ typeNodeMap_.insert( "t", 0);
+ typeNodeMap_.insert( "T", 0);
+ typeNodeMap_.insert( "tagChanged", 0);
+ typeNodeMap_.insert( "timeString", 0);
+ typeNodeMap_.insert( "timeout", 0);
+ typeNodeMap_.insert( "to", 0);
+ typeNodeMap_.insert( "toggled", 0);
+ typeNodeMap_.insert( "type", 0);
+ typeNodeMap_.insert( "unsigned", 0);
+ typeNodeMap_.insert( "urllist", 0);
+ typeNodeMap_.insert( "va_list", 0);
+ typeNodeMap_.insert( "value", 0);
+ typeNodeMap_.insert( "valueEmitted", 0);
+ typeNodeMap_.insert( "videoFramePainted", 0);
+ typeNodeMap_.insert( "videoModeSelected", 0);
+ typeNodeMap_.insert( "videoRecorder", 0);
+ typeNodeMap_.insert( "void", 0);
+ typeNodeMap_.insert( "volatile", 0);
+ typeNodeMap_.insert( "wchar_t", 0);
+ typeNodeMap_.insert( "x", 0);
+ typeNodeMap_.insert( "y", 0);
+ typeNodeMap_.insert( "zoom", 0);
+ typeNodeMap_.insert( "zoomTo", 0);
+}
+
+/*! \fn NamespaceNode* QDocDatabase::primaryTreeRoot()
+ Returns a pointer to the root node of the primary tree.
+ */
+
+/*!
+ \fn const GroupMap& QDocDatabase::groups()
Returns a const reference to the collection of all
- group nodes.
+ group nodes in the primary tree.
*/
/*!
- \fn const DocNodeMap& QDocDatabase::modules() const
+ \fn const ModuleMap& QDocDatabase::modules()
Returns a const reference to the collection of all
- module nodes.
+ module nodes in the primary tree.
*/
/*!
- \fn const DocNodeMap& QDocDatabase::qmlModules() const
+ \fn const QmlModuleMap& QDocDatabase::qmlModules()
Returns a const reference to the collection of all
- QML module nodes.
+ QML module nodes in the primary tree.
*/
-/*!
+/*! \fn GroupNode* QDocDatabase::getGroup(const QString& name)
Find the group node named \a name and return a pointer
to it. If a matching node is not found, return 0.
*/
-DocNode* QDocDatabase::getGroup(const QString& name)
-{
- DocNodeMap::const_iterator i = groups_.find(name);
- if (i != groups_.end())
- return i.value();
- return 0;
-}
-/*!
+/*! \fn GroupNode* QDocDatabase::findGroup(const QString& name)
Find the group node named \a name and return a pointer
to it. If a matching node is not found, add a new group
node named \a name and return a pointer to that one.
@@ -143,20 +687,8 @@ DocNode* QDocDatabase::getGroup(const QString& name)
If a new group node is added, its parent is the tree root,
and the new group node is marked \e{not seen}.
*/
-DocNode* QDocDatabase::findGroup(const QString& name)
-{
- DocNodeMap::const_iterator i = groups_.find(name);
- if (i != groups_.end())
- return i.value();
- DocNode* dn = new DocNode(tree_->root(), name, Node::Group, Node::OverviewPage);
- dn->markNotSeen();
- groups_.insert(name,dn);
- if (!masterMap_.contains(name,dn))
- masterMap_.insert(name,dn);
- return dn;
-}
-/*!
+/*! \fn ModuleNode* QDocDatabase::findModule(const QString& name)
Find the module node named \a name and return a pointer
to it. If a matching node is not found, add a new module
node named \a name and return a pointer to that one.
@@ -164,20 +696,8 @@ DocNode* QDocDatabase::findGroup(const QString& name)
If a new module node is added, its parent is the tree root,
and the new module node is marked \e{not seen}.
*/
-DocNode* QDocDatabase::findModule(const QString& name)
-{
- DocNodeMap::const_iterator i = modules_.find(name);
- if (i != modules_.end())
- return i.value();
- DocNode* dn = new DocNode(tree_->root(), name, Node::Module, Node::OverviewPage);
- dn->markNotSeen();
- modules_.insert(name,dn);
- if (!masterMap_.contains(name,dn))
- masterMap_.insert(name,dn);
- return dn;
-}
-/*!
+/*! \fn QmlModuleNode* QDocDatabase::findQmlModule(const QString& name)
Find the QML module node named \a name and return a pointer
to it. If a matching node is not found, add a new QML module
node named \a name and return a pointer to that one.
@@ -185,68 +705,32 @@ DocNode* QDocDatabase::findModule(const QString& name)
If a new QML module node is added, its parent is the tree root,
and the new QML module node is marked \e{not seen}.
*/
-QmlModuleNode* QDocDatabase::findQmlModule(const QString& name)
-{
- if (qmlModules_.contains(name))
- return static_cast<QmlModuleNode*>(qmlModules_.value(name));
-
- QmlModuleNode* qmn = new QmlModuleNode(tree_->root(), name);
- qmn->markNotSeen();
- qmn->setQmlModuleInfo(name);
- qmlModules_.insert(name, qmn);
- masterMap_.insert(name, qmn);
- return qmn;
-}
-/*!
- Looks up the group node named \a name in the collection
- of all group nodes. If a match is found, a pointer to the
- node is returned. Otherwise, a new group node named \a name
- is created and inserted into the collection, and the pointer
- to that node is returned. The group node is marked \e{seen}
- in either case.
+/*! \fn GroupNode* QDocDatabase::addGroup(const QString& name)
+ Looks up the group named \a name in the primary tree. If
+ a match is found, a pointer to the node is returned.
+ Otherwise, a new group node named \a name is created and
+ inserted into the collection, and the pointer to that node
+ is returned.
*/
-DocNode* QDocDatabase::addGroup(const QString& name)
-{
- DocNode* group = findGroup(name);
- group->markSeen();
- return group;
-}
-/*!
- Looks up the module node named \a name in the collection
- of all module nodes. If a match is found, a pointer to the
- node is returned. Otherwise, a new module node named \a name
- is created and inserted into the collection, and the pointer
- to that node is returned. The module node is marked \e{seen}
- in either case.
+/*! \fn ModuleNode* QDocDatabase::addModule(const QString& name)
+ Looks up the module named \a name in the primary tree. If
+ a match is found, a pointer to the node is returned.
+ Otherwise, a new module node named \a name is created and
+ inserted into the collection, and the pointer to that node
+ is returned.
*/
-DocNode* QDocDatabase::addModule(const QString& name)
-{
- DocNode* module = findModule(name);
- module->markSeen();
- return module;
-}
-/*!
- Looks up the QML module node named \a name in the collection
- of all QML module nodes. If a match is found, a pointer to the
- node is returned. Otherwise, a new QML module node named \a name
- is created and inserted into the collection, and the pointer
- to that node is returned. The QML module node is marked \e{seen}
- in either case.
- */
-QmlModuleNode* QDocDatabase::addQmlModule(const QString& name)
-{
- QStringList blankSplit = name.split(QLatin1Char(' '));
- QmlModuleNode* qmn = findQmlModule(blankSplit[0]);
- qmn->setQmlModuleInfo(name);
- qmn->markSeen();
- //masterMap_.insert(qmn->qmlModuleIdentifier(),qmn);
- return qmn;
-}
+/*! \fn QmlModuleNode* QDocDatabase::addQmlModule(const QString& name)
+ Looks up the QML module named \a name in the primary tree.
+ If a match is found, a pointer to the node is returned.
+ Otherwise, a new QML module node named \a name is created
+ and inserted into the collection, and the pointer to that
+ node is returned.
+ */
-/*!
+/*! \fn GroupNode* QDocDatabase::addToGroup(const QString& name, Node* node)
Looks up the group node named \a name in the collection
of all group nodes. If a match is not found, a new group
node named \a name is created and inserted into the collection.
@@ -255,62 +739,31 @@ QmlModuleNode* QDocDatabase::addQmlModule(const QString& name)
\a node is not changed by this function. Returns a pointer to
the group node.
*/
-DocNode* QDocDatabase::addToGroup(const QString& name, Node* node)
-{
- DocNode* dn = findGroup(name);
- dn->addMember(node);
- node->addMember(dn);
- return dn;
-}
-/*!
+/*! \fn ModuleNode* QDocDatabase::addToModule(const QString& name, Node* node)
Looks up the module node named \a name in the collection
of all module nodes. If a match is not found, a new module
node named \a name is created and inserted into the collection.
Then append \a node to the module's members list. The parent of
\a node is not changed by this function. Returns the module node.
*/
-DocNode* QDocDatabase::addToModule(const QString& name, Node* node)
-{
- DocNode* dn = findModule(name);
- dn->addMember(node);
- node->setModuleName(name);
- return dn;
-}
-/*!
+/*! \fn QmlModuleNode* QDocDatabase::addToQmlModule(const QString& name, Node* node)
Looks up the QML module named \a name. If it isn't there,
create it. Then append \a node to the QML module's member
list. The parent of \a node is not changed by this function.
*/
-void QDocDatabase::addToQmlModule(const QString& name, Node* node)
-{
- QStringList qmid;
- QStringList dotSplit;
- QStringList blankSplit = name.split(QLatin1Char(' '));
- qmid.append(blankSplit[0]);
- if (blankSplit.size() > 1) {
- qmid.append(blankSplit[0] + blankSplit[1]);
- dotSplit = blankSplit[1].split(QLatin1Char('.'));
- qmid.append(blankSplit[0] + dotSplit[0]);
- }
- QmlModuleNode* qmn = findQmlModule(blankSplit[0]);
- qmn->addMember(node);
- node->setQmlModule(qmn);
-
- if (node->subType() == Node::QmlClass) {
- QmlClassNode* n = static_cast<QmlClassNode*>(node);
- for (int i=0; i<qmid.size(); ++i) {
- QString key = qmid[i] + "::" + node->name();
- if (!qmlTypeMap_.contains(key))
- qmlTypeMap_.insert(key,n);
- if (!masterMap_.contains(key))
- masterMap_.insert(key,node);
- }
- if (!masterMap_.contains(node->name(),node))
- masterMap_.insert(node->name(),node);
- }
+/*!
+ Looks up the QML type node identified by the qualified Qml
+ type \a name and returns a pointer to the QML type node.
+ */
+QmlClassNode* QDocDatabase::findQmlType(const QString& name)
+{
+ QmlClassNode* qcn = forest_.lookupQmlType(name);
+ if (qcn)
+ return qcn;
+ return 0;
}
/*!
@@ -321,20 +774,24 @@ void QDocDatabase::addToQmlModule(const QString& name, Node* node)
If the QML module id is empty, it looks up the QML type by
\a name only.
*/
-QmlClassNode* QDocDatabase::findQmlType(const QString& qmid, const QString& name) const
+QmlClassNode* QDocDatabase::findQmlType(const QString& qmid, const QString& name)
{
- if (!qmid.isEmpty())
- return qmlTypeMap_.value(qmid + "::" + name);
+ if (!qmid.isEmpty()) {
+ QString t = qmid + "::" + name;
+ QmlClassNode* qcn = forest_.lookupQmlType(t);
+ if (qcn)
+ return qcn;
+ }
QStringList path(name);
- Node* n = tree_->findNodeByNameAndType(path, Node::Document, Node::QmlClass, 0, true);
+ Node* n = forest_.findNodeByNameAndType(path, Node::QmlType);
if (n) {
- if (n->subType() == Node::QmlClass)
+ if (n->isQmlType())
return static_cast<QmlClassNode*>(n);
- else if (n->subType() == Node::Collision) {
+ else if (n->isCollisionNode()) {
NameCollisionNode* ncn;
ncn = static_cast<NameCollisionNode*>(n);
- return static_cast<QmlClassNode*>(ncn->findAny(Node::Document,Node::QmlClass));
+ return static_cast<QmlClassNode*>(ncn->findAny(Node::QmlType, Node::NoSubType));
}
}
return 0;
@@ -346,7 +803,7 @@ QmlClassNode* QDocDatabase::findQmlType(const QString& qmid, const QString& name
QML type \a name and returns a pointer to the QML type node.
If a QML type node is not found, 0 is returned.
*/
-QmlClassNode* QDocDatabase::findQmlType(const ImportRec& import, const QString& name) const
+QmlClassNode* QDocDatabase::findQmlType(const ImportRec& import, const QString& name)
{
if (!import.isEmpty()) {
QStringList dotSplit;
@@ -358,7 +815,7 @@ QmlClassNode* QDocDatabase::findQmlType(const ImportRec& import, const QString&
qmName = import.importUri_;
for (int i=0; i<dotSplit.size(); ++i) {
QString qualifiedName = qmName + "::" + dotSplit[i];
- QmlClassNode* qcn = qmlTypeMap_.value(qualifiedName);
+ QmlClassNode* qcn = forest_.lookupQmlType(qualifiedName);
if (qcn)
return qcn;
}
@@ -367,59 +824,169 @@ QmlClassNode* QDocDatabase::findQmlType(const ImportRec& import, const QString&
}
/*!
- For debugging only.
+ This function calls \a func for each tree in the forest.
*/
-void QDocDatabase::printModules() const
+void QDocDatabase::processForest(void (QDocDatabase::*func) (InnerNode*))
{
- DocNodeMap::const_iterator i = modules_.begin();
- while (i != modules_.end()) {
- qDebug() << " " << i.key();
- ++i;
+ Tree* t = forest_.firstTree();
+ while (t) {
+ (this->*(func))(t->root());
+ t = forest_.nextTree();
}
}
/*!
- For debugging only.
+ Constructs the collection of legalese texts, if it has not
+ already been constructed and returns a reference to it.
*/
-void QDocDatabase::printQmlModules() const
+TextToNodeMap& QDocDatabase::getLegaleseTexts()
{
- DocNodeMap::const_iterator i = qmlModules_.begin();
- while (i != qmlModules_.end()) {
- qDebug() << " " << i.key();
- ++i;
- }
+ if (legaleseTexts_.isEmpty())
+ processForest(&QDocDatabase::findAllLegaleseTexts);
+ return legaleseTexts_;
}
/*!
- Traverses the database to construct useful data structures
- for use when outputting certain significant collections of
- things, C++ classes, QML types, "since" lists, and other
- stuff.
+ Construct the data structures for obsolete things, if they
+ have not already been constructed. Returns a reference to
+ the map of C++ classes with obsolete members.
*/
-void QDocDatabase::buildCollections()
+NodeMap& QDocDatabase::getClassesWithObsoleteMembers()
{
- nonCompatClasses_.clear();
- mainClasses_.clear();
- compatClasses_.clear();
- obsoleteClasses_.clear();
- funcIndex_.clear();
- legaleseTexts_.clear();
- serviceClasses_.clear();
- qmlClasses_.clear();
-
- findAllClasses(treeRoot());
- findAllFunctions(treeRoot());
- findAllLegaleseTexts(treeRoot());
- findAllNamespaces(treeRoot());
- findAllSince(treeRoot());
- findAllObsoleteThings(treeRoot());
+ if (obsoleteClasses_.isEmpty() && obsoleteQmlTypes_.isEmpty())
+ processForest(&QDocDatabase::findAllObsoleteThings);
+ return classesWithObsoleteMembers_;
+}
+
+/*!
+ Construct the data structures for obsolete things, if they
+ have not already been constructed. Returns a reference to
+ the map of obsolete QML types.
+ */
+NodeMap& QDocDatabase::getObsoleteQmlTypes()
+{
+ if (obsoleteClasses_.isEmpty() && obsoleteQmlTypes_.isEmpty())
+ processForest(&QDocDatabase::findAllObsoleteThings);
+ return obsoleteQmlTypes_;
+}
+
+/*!
+ Construct the data structures for obsolete things, if they
+ have not already been constructed. Returns a reference to
+ the map of QML types with obsolete members.
+ */
+NodeMap& QDocDatabase::getQmlTypesWithObsoleteMembers()
+{
+ if (obsoleteClasses_.isEmpty() && obsoleteQmlTypes_.isEmpty())
+ processForest(&QDocDatabase::findAllObsoleteThings);
+ return qmlTypesWithObsoleteMembers_;
+}
+
+/*!
+ Constructs the C++ namespace data structure, if it has not
+ already been constructed. Returns a reference to it.
+ */
+NodeMap& QDocDatabase::getNamespaces()
+{
+ if (namespaceIndex_.isEmpty())
+ processForest(&QDocDatabase::findAllNamespaces);
+ return namespaceIndex_;
+}
+
+/*!
+ Construct the C++ class data structures, if they have not
+ already been constructed. Returns a reference to the map
+ of C++ service clases.
+
+ \note This is currently not used.
+ */
+NodeMap& QDocDatabase::getServiceClasses()
+{
+ if (nonCompatClasses_.isEmpty() && qmlClasses_.isEmpty())
+ processForest(&QDocDatabase::findAllClasses);
+ return serviceClasses_;
+}
+
+/*!
+ Construct the data structures for QML basic types, if they
+ have not already been constructed. Returns a reference to
+ the map of QML basic types.
+ */
+NodeMap& QDocDatabase::getQmlBasicTypes()
+{
+ if (nonCompatClasses_.isEmpty() && qmlBasicTypes_.isEmpty())
+ processForest(&QDocDatabase::findAllClasses);
+ return qmlBasicTypes_;
+}
+
+/*!
+ Construct the data structures for obsolete things, if they
+ have not already been constructed. Returns a reference to
+ the map of obsolete QML types.
+ */
+NodeMap& QDocDatabase::getQmlTypes()
+{
+ if (nonCompatClasses_.isEmpty() && qmlClasses_.isEmpty())
+ processForest(&QDocDatabase::findAllClasses);
+ return qmlClasses_;
+}
+
+/*!
+ Construct the data structures for obsolete things, if they
+ have not already been constructed. Returns a reference to
+ the map of obsolete C++ clases.
+ */
+NodeMap& QDocDatabase::getObsoleteClasses()
+{
+ if (obsoleteClasses_.isEmpty() && obsoleteQmlTypes_.isEmpty())
+ processForest(&QDocDatabase::findAllObsoleteThings);
+ return obsoleteClasses_;
+}
+
+/*!
+ Construct the C++ class data structures, if they have not
+ already been constructed. Returns a reference to the map
+ of compatibility C++ clases.
+ */
+NodeMap& QDocDatabase::getCompatibilityClasses()
+{
+ if (nonCompatClasses_.isEmpty() && qmlClasses_.isEmpty())
+ processForest(&QDocDatabase::findAllClasses);
+ return compatClasses_;
+}
+
+/*!
+ Construct the C++ class data structures, if they have not
+ already been constructed. Returns a reference to the map
+ of main C++ clases.
+
+ \note The main C++ classes data structure is currently not
+ used.
+ */
+NodeMap& QDocDatabase::getMainClasses()
+{
+ if (nonCompatClasses_.isEmpty() && qmlClasses_.isEmpty())
+ processForest(&QDocDatabase::findAllClasses);
+ return mainClasses_;
+}
+
+/*!
+ Construct the C++ class data structures, if they have not
+ already been constructed. Returns a reference to the map
+ of all C++ classes.
+ */
+NodeMap& QDocDatabase::getCppClasses()
+{
+ if (nonCompatClasses_.isEmpty() && qmlClasses_.isEmpty())
+ processForest(&QDocDatabase::findAllClasses);
+ return nonCompatClasses_;
}
/*!
Finds all the C++ class nodes and QML type nodes and
sorts them into maps.
*/
-void QDocDatabase::findAllClasses(const InnerNode* node)
+void QDocDatabase::findAllClasses(InnerNode* node)
{
NodeList::const_iterator c = node->childNodes().constBegin();
while (c != node->childNodes().constEnd()) {
@@ -445,14 +1012,16 @@ void QDocDatabase::findAllClasses(const InnerNode* node)
serviceClasses_.insert(serviceName, *c);
}
}
- else if ((*c)->type() == Node::Document &&
- (*c)->subType() == Node::QmlClass &&
- !(*c)->doc().isEmpty()) {
+ else if (((*c)->isQmlType() || (*c)->isQmlBasicType())&& !(*c)->doc().isEmpty()) {
QString qmlTypeName = (*c)->name();
if (qmlTypeName.startsWith(QLatin1String("QML:")))
qmlClasses_.insert(qmlTypeName.mid(4),*c);
else
qmlClasses_.insert(qmlTypeName,*c);
+
+ //also add to the QML basic type map
+ if ((*c)->isQmlBasicType())
+ qmlBasicTypes_.insert(qmlTypeName,*c);
}
else if ((*c)->isInnerNode()) {
findAllClasses(static_cast<InnerNode*>(*c));
@@ -463,15 +1032,26 @@ void QDocDatabase::findAllClasses(const InnerNode* node)
}
/*!
+ Construct the function index data structure and return it.
+ This data structure is used to output the function index page.
+ */
+NodeMapMap& QDocDatabase::getFunctionIndex()
+{
+ funcIndex_.clear();
+ processForest(&QDocDatabase::findAllFunctions);
+ return funcIndex_;
+}
+
+/*!
Finds all the function nodes
*/
-void QDocDatabase::findAllFunctions(const InnerNode* node)
+void QDocDatabase::findAllFunctions(InnerNode* node)
{
NodeList::ConstIterator c = node->childNodes().constBegin();
while (c != node->childNodes().constEnd()) {
if ((*c)->access() != Node::Private) {
if ((*c)->isInnerNode()) {
- findAllFunctions(static_cast<const InnerNode*>(*c));
+ findAllFunctions(static_cast<InnerNode*>(*c));
}
else if ((*c)->type() == Node::Function) {
const FunctionNode* func = static_cast<const FunctionNode*>(*c);
@@ -491,7 +1071,7 @@ void QDocDatabase::findAllFunctions(const InnerNode* node)
Finds all the nodes containing legalese text and puts them
in a map.
*/
-void QDocDatabase::findAllLegaleseTexts(const InnerNode* node)
+void QDocDatabase::findAllLegaleseTexts(InnerNode* node)
{
NodeList::ConstIterator c = node->childNodes().constBegin();
while (c != node->childNodes().constEnd()) {
@@ -499,7 +1079,7 @@ void QDocDatabase::findAllLegaleseTexts(const InnerNode* node)
if (!(*c)->doc().legaleseText().isEmpty())
legaleseTexts_.insertMulti((*c)->doc().legaleseText(), *c);
if ((*c)->isInnerNode())
- findAllLegaleseTexts(static_cast<const InnerNode *>(*c));
+ findAllLegaleseTexts(static_cast<InnerNode *>(*c));
}
++c;
}
@@ -508,13 +1088,13 @@ void QDocDatabase::findAllLegaleseTexts(const InnerNode* node)
/*!
Finds all the namespace nodes and puts them in an index.
*/
-void QDocDatabase::findAllNamespaces(const InnerNode* node)
+void QDocDatabase::findAllNamespaces(InnerNode* node)
{
NodeList::ConstIterator c = node->childNodes().constBegin();
while (c != node->childNodes().constEnd()) {
if ((*c)->access() != Node::Private) {
if ((*c)->isInnerNode()) {
- findAllNamespaces(static_cast<const InnerNode *>(*c));
+ findAllNamespaces(static_cast<InnerNode *>(*c));
if ((*c)->type() == Node::Namespace) {
// Ensure that the namespace's name is not empty (the root
// namespace has no name).
@@ -532,7 +1112,7 @@ void QDocDatabase::findAllNamespaces(const InnerNode* node)
maps. They can be C++ classes, QML types, or they can be
functions, enum types, typedefs, methods, etc.
*/
-void QDocDatabase::findAllObsoleteThings(const InnerNode* node)
+void QDocDatabase::findAllObsoleteThings(InnerNode* node)
{
NodeList::const_iterator c = node->childNodes().constBegin();
while (c != node->childNodes().constEnd()) {
@@ -545,7 +1125,7 @@ void QDocDatabase::findAllObsoleteThings(const InnerNode* node)
name = (*c)->parent()->name() + "::" + name;
obsoleteClasses_.insert(name, *c);
}
- else if ((*c)->type() == Node::Document && (*c)->subType() == Node::QmlClass) {
+ else if ((*c)->isQmlType()) {
if (name.startsWith(QLatin1String("QML:")))
name = name.mid(4);
name = (*c)->qmlModuleName() + "::" + name;
@@ -581,7 +1161,7 @@ void QDocDatabase::findAllObsoleteThings(const InnerNode* node)
++p;
}
}
- else if ((*c)->type() == Node::Document && (*c)->subType() == Node::QmlClass) {
+ else if ((*c)->isQmlType()) {
InnerNode* n = static_cast<InnerNode*>(*c);
bool inserted = false;
NodeList::const_iterator p = n->childNodes().constBegin();
@@ -596,7 +1176,7 @@ void QDocDatabase::findAllObsoleteThings(const InnerNode* node)
Node* parent = (*c)->parent();
if (parent->type() == Node::QmlPropertyGroup && parent->parent())
parent = parent->parent();
- if (parent && parent->subType() == Node::QmlClass && !parent->name().isEmpty())
+ if (parent && parent->isQmlType() && !parent->name().isEmpty())
name = parent->name() + "::" + name;
}
qmlTypesWithObsoleteMembers_.insert(name,*c);
@@ -627,7 +1207,7 @@ void QDocDatabase::findAllObsoleteThings(const InnerNode* node)
This function is used for generating the "New Classes... in x.y"
section on the \e{What's New in Qt x.y} page.
*/
-void QDocDatabase::findAllSince(const InnerNode* node)
+void QDocDatabase::findAllSince(InnerNode* node)
{
NodeList::const_iterator child = node->childNodes().constBegin();
while (child != node->childNodes().constEnd()) {
@@ -665,7 +1245,7 @@ void QDocDatabase::findAllSince(const InnerNode* node)
nsmap.value().insert(className,(*child));
ncmap.value().insert(className,(*child));
}
- else if ((*child)->subType() == Node::QmlClass) {
+ else if ((*child)->isQmlType()) {
// Insert QML elements into the since and element maps.
QString className = (*child)->name();
if ((*child)->parent() && !(*child)->parent()->name().isEmpty()) {
@@ -702,8 +1282,10 @@ void QDocDatabase::findAllSince(const InnerNode* node)
reference to the value, which is a NodeMap. If \a key is not
found, return a reference to an empty NodeMap.
*/
-const NodeMap& QDocDatabase::getClassMap(const QString& key) const
+const NodeMap& QDocDatabase::getClassMap(const QString& key)
{
+ if (newSinceMaps_.isEmpty() && newClassMaps_.isEmpty() && newQmlTypeMaps_.isEmpty())
+ processForest(&QDocDatabase::findAllSince);
NodeMapMap::const_iterator i = newClassMaps_.constFind(key);
if (i != newClassMaps_.constEnd())
return i.value();
@@ -715,8 +1297,10 @@ const NodeMap& QDocDatabase::getClassMap(const QString& key) const
reference to the value, which is a NodeMap. If the \a key is not
found, return a reference to an empty NodeMap.
*/
-const NodeMap& QDocDatabase::getQmlTypeMap(const QString& key) const
+const NodeMap& QDocDatabase::getQmlTypeMap(const QString& key)
{
+ if (newSinceMaps_.isEmpty() && newClassMaps_.isEmpty() && newQmlTypeMaps_.isEmpty())
+ processForest(&QDocDatabase::findAllSince);
NodeMapMap::const_iterator i = newQmlTypeMaps_.constFind(key);
if (i != newQmlTypeMaps_.constEnd())
return i.value();
@@ -728,8 +1312,10 @@ const NodeMap& QDocDatabase::getQmlTypeMap(const QString& key) const
a reference to the value, which is a NodeMultiMap. If \a key
is not found, return a reference to an empty NodeMultiMap.
*/
-const NodeMultiMap& QDocDatabase::getSinceMap(const QString& key) const
+const NodeMultiMap& QDocDatabase::getSinceMap(const QString& key)
{
+ if (newSinceMaps_.isEmpty() && newClassMaps_.isEmpty() && newQmlTypeMaps_.isEmpty())
+ processForest(&QDocDatabase::findAllSince);
NodeMultiMapMap::const_iterator i = newSinceMaps_.constFind(key);
if (i != newSinceMaps_.constEnd())
return i.value();
@@ -742,209 +1328,55 @@ const NodeMultiMap& QDocDatabase::getSinceMap(const QString& key) const
to generating documentation.
*/
void QDocDatabase::resolveIssues() {
- resolveQmlInheritance(treeRoot());
- resolveTargets(treeRoot());
- tree_->resolveCppToQmlLinks();
+ resolveQmlInheritance(primaryTreeRoot());
+ resolveTargets();
+ primaryTree()->resolveCppToQmlLinks();
}
/*!
- Searches the \a database for a node named \a target and returns
- a pointer to it if found.
+ This function is called for autolinking to a \a type,
+ which could be a function return type or a parameter
+ type. The tree node that represents the \a type is
+ returned. All the trees are searched until a match is
+ found. When searching the primary tree, the search
+ begins at \a relative and proceeds up the parent chain.
+ When searching the index trees, the search begins at the
+ root.
*/
-const Node* QDocDatabase::resolveTarget(const QString& target,
- const Node* relative,
- const Node* self)
+const Node* QDocDatabase::resolveType(const QString& type, const Node* relative)
{
- const Node* node = 0;
- if (target.endsWith("()")) {
- QString funcName = target;
- funcName.chop(2);
- QStringList path = funcName.split("::");
- const FunctionNode* fn = tree_->findFunctionNode(path, relative, SearchBaseClasses);
- if (fn) {
- /*
- Why is this case not accepted?
- */
- if (fn->metaness() != FunctionNode::MacroWithoutParams)
- node = fn;
- }
- }
- else if (target.contains(QLatin1Char('#'))) {
- // This error message is never printed; I think we can remove the case.
- qDebug() << "qdoc: target case not handled:" << target;
- }
- else {
- QStringList path = target.split("::");
- int flags = SearchBaseClasses | SearchEnumValues | NonFunction;
- node = tree_->findNode(path, relative, flags, self);
+ QStringList path = type.split("::");
+ if ((path.size() == 1) && (path.at(0)[0].isLower() || path.at(0) == QString("T"))) {
+ NodeMap::iterator i = typeNodeMap_.find(path.at(0));
+ if (i != typeNodeMap_.end())
+ return i.value();
}
- return node;
+ return forest_.resolveType(path, relative);
}
/*!
Finds the node that will generate the documentation that
contains the \a target and returns a pointer to it.
+
+ Can this be improved by using the target map in Tree?
*/
const Node* QDocDatabase::findNodeForTarget(const QString& target, const Node* relative)
{
const Node* node = 0;
if (target.isEmpty())
node = relative;
- else if (target.endsWith(".html"))
- node = tree_->root()->findChildNodeByNameAndType(target, Node::Document);
+ else if (target.endsWith(".html")) {
+ node = findNodeByNameAndType(QStringList(target), Node::Document);
+ }
else {
node = resolveTarget(target, relative);
if (!node)
- node = findDocNodeByTitle(target, relative);
+ node = findDocNodeByTitle(target);
}
return node;
}
/*!
- Inserts a new target into the target table with the specified
- \a name, \a node, and \a priority.
- */
-void QDocDatabase::insertTarget(const QString& name, TargetRec::Type type, Node* node, int priority)
-{
- TargetRec target;
- target.type_ = type;
- target.node_ = node;
- target.priority_ = priority;
- Atom a = Atom(Atom::Target, name);
- target.ref_ = refForAtom(&a);
- targetRecMultiMap_.insert(name, target);
-}
-
-/*!
- This function searches for a \a target anchor node. If it
- finds one, it sets \a ref and returns the found node.
- */
-const Node*
-QDocDatabase::findUnambiguousTarget(const QString& target, QString& ref, const Node* relative)
-{
- TargetRec bestTarget;
- int numBestTargets = 0;
- QList<TargetRec> bestTargetList;
-
- QString key = Doc::canonicalTitle(target);
- TargetRecMultiMap::iterator i = targetRecMultiMap_.find(key);
- while (i != targetRecMultiMap_.end()) {
- if (i.key() != key)
- break;
- const TargetRec& candidate = i.value();
- if (candidate.priority_ < bestTarget.priority_) {
- bestTarget = candidate;
- bestTargetList.clear();
- bestTargetList.append(candidate);
- numBestTargets = 1;
- } else if (candidate.priority_ == bestTarget.priority_) {
- bestTargetList.append(candidate);
- ++numBestTargets;
- }
- ++i;
- }
- if (numBestTargets > 0) {
- if (numBestTargets == 1) {
- ref = bestTarget.ref_;
- return bestTarget.node_;
- }
- else if (bestTargetList.size() > 1) {
- if (relative && !relative->qmlModuleName().isEmpty()) {
- for (int i=0; i<bestTargetList.size(); ++i) {
- const Node* n = bestTargetList.at(i).node_;
- if (n && relative->qmlModuleName() == n->qmlModuleName()) {
- ref = bestTargetList.at(i).ref_;
- return n;
- }
- }
- }
- }
- }
- ref.clear();
- return 0;
-}
-
-/*!
- This function searches for a node with the specified \a title.
- If \a relative node is provided, it is used to disambiguate if
- it has a QML module identifier.
- */
-const DocNode* QDocDatabase::findDocNodeByTitle(const QString& title, const Node* relative) const
-{
- QString key = Doc::canonicalTitle(title);
- DocNodeMultiMap::const_iterator i = docNodesByTitle_.constFind(key);
- if (i != docNodesByTitle_.constEnd()) {
- if (relative && !relative->qmlModuleName().isEmpty()) {
- const DocNode* dn = i.value();
- InnerNode* parent = dn->parent();
- if (parent && parent->type() == Node::Document && parent->subType() == Node::Collision) {
- const NodeList& nl = parent->childNodes();
- NodeList::ConstIterator it = nl.constBegin();
- while (it != nl.constEnd()) {
- if ((*it)->qmlModuleName() == relative->qmlModuleName()) {
- /*
- By returning here, we avoid printing
- all the duplicate header warnings,
- which are not really duplicates now,
- because of the QML module name being
- used as a namespace qualifier.
- */
- dn = static_cast<const DocNode*>(*it);
- return dn;
- }
- ++it;
- }
- }
- }
- /*
- Reporting all these duplicate section titles is probably
- overkill. We should report the duplicate file and let
- that suffice.
- */
- DocNodeMultiMap::const_iterator j = i;
- ++j;
- if (j != docNodesByTitle_.constEnd() && j.key() == i.key()) {
- QList<Location> internalLocations;
- while (j != docNodesByTitle_.constEnd()) {
- if (j.key() == i.key() && j.value()->url().isEmpty()) {
- internalLocations.append(j.value()->location());
- break; // Just report one duplicate for now.
- }
- ++j;
- }
- if (internalLocations.size() > 0) {
- i.value()->location().warning(tr("This page title exists in more than one file: \"%1\"").arg(title));
- foreach (const Location &location, internalLocations)
- location.warning(tr("[It also exists here]"));
- }
- }
- return i.value();
- }
- return 0;
-}
-
-/*!
- This function searches for a node with a canonical title
- constructed from \a target. If the node it finds is \a node,
- it returns the ref from that node. Otherwise it returns an
- empty string.
- */
-QString QDocDatabase::findTarget(const QString& target, const Node* node) const
-{
- QString key = Doc::canonicalTitle(target);
- TargetRecMultiMap::const_iterator i = targetRecMultiMap_.constFind(key);
-
- if (i != targetRecMultiMap_.constEnd()) {
- do {
- if (i.value().node_ == node)
- return i.value().ref_;
- ++i;
- } while (i != targetRecMultiMap_.constEnd() && i.key() == key);
- }
- return QString();
-}
-
-/*!
For each QML Type node in the tree beginning at \a root,
if it has a QML base type name but its QML base type node
pointer is 0, use the QML base type name to look up the
@@ -953,111 +1385,40 @@ QString QDocDatabase::findTarget(const QString& target, const Node* node) const
*/
void QDocDatabase::resolveQmlInheritance(InnerNode* root)
{
- // Dop we need recursion?
+ NodeMap previousSearches;
+ // Do we need recursion?
foreach (Node* child, root->childNodes()) {
- if (child->type() == Node::Document && child->subType() == Node::QmlClass) {
+ if (child->isQmlType()) {
QmlClassNode* qcn = static_cast<QmlClassNode*>(child);
- if ((qcn->qmlBaseNode() == 0) && !qcn->qmlBaseName().isEmpty()) {
- QmlClassNode* bqcn = 0;
- if (qcn->qmlBaseName().contains("::")) {
- bqcn = qmlTypeMap_.value(qcn->qmlBaseName());
- }
- else {
- const ImportList& imports = qcn->importList();
- for (int i=0; i<imports.size(); ++i) {
- bqcn = findQmlType(imports[i], qcn->qmlBaseName());
- if (bqcn)
- break;
- }
- }
- if (bqcn == 0) {
- bqcn = findQmlType(QString(), qcn->qmlBaseName());
- }
- if (bqcn) {
+ if (qcn->qmlBaseNodeNotSet() && !qcn->qmlBaseName().isEmpty()) {
+ QmlClassNode* bqcn = static_cast<QmlClassNode*>(previousSearches.value(qcn->qmlBaseName()));
+ if (bqcn)
qcn->setQmlBaseNode(bqcn);
- }
-#if 0
else {
- qDebug() << "Temporary error message (ignore): UNABLE to resolve QML base type:"
- << qcn->qmlBaseName() << "for QML type:" << qcn->name();
- }
-#endif
- }
- }
- }
-}
-
-/*!
- */
-void QDocDatabase::resolveTargets(InnerNode* root)
-{
- // need recursion
-
- foreach (Node* child, root->childNodes()) {
- if (child->type() == Node::Document) {
- DocNode* node = static_cast<DocNode*>(child);
- if (!node->title().isEmpty()) {
- QString key = Doc::canonicalTitle(node->title());
- QList<DocNode*> nodes = docNodesByTitle_.values(key);
- bool alreadyThere = false;
- if (!nodes.empty()) {
- for (int i=0; i< nodes.size(); ++i) {
- if (nodes[i]->subType() == Node::ExternalPage) {
- if (node->name() == nodes[i]->name()) {
- alreadyThere = true;
+ if (!qcn->importList().isEmpty()) {
+ const ImportList& imports = qcn->importList();
+ for (int i=0; i<imports.size(); ++i) {
+ bqcn = findQmlType(imports[i], qcn->qmlBaseName());
+ if (bqcn)
break;
- }
}
}
- }
- if (!alreadyThere) {
- docNodesByTitle_.insert(key, node);
- }
- }
- if (node->subType() == Node::Collision) {
- resolveTargets(node);
- }
- }
-
- if (child->doc().hasTableOfContents()) {
- const QList<Atom*>& toc = child->doc().tableOfContents();
- TargetRec target;
- target.node_ = child;
- target.priority_ = 3;
-
- for (int i = 0; i < toc.size(); ++i) {
- target.ref_ = refForAtom(toc.at(i));
- QString title = Text::sectionHeading(toc.at(i)).toString();
- if (!title.isEmpty()) {
- QString key = Doc::canonicalTitle(title);
- targetRecMultiMap_.insert(key, target);
+ if (bqcn == 0) {
+ bqcn = findQmlType(QString(), qcn->qmlBaseName());
+ }
+ if (bqcn) {
+ qcn->setQmlBaseNode(bqcn);
+ previousSearches.insert(qcn->qmlBaseName(), bqcn);
+ }
+#if 0
+ else {
+ qDebug() << "Temporary error message (ignore): UNABLE to resolve QML base type:"
+ << qcn->qmlBaseName() << "for QML type:" << qcn->name();
+ }
+#endif
}
}
}
- if (child->doc().hasKeywords()) {
- const QList<Atom*>& keywords = child->doc().keywords();
- TargetRec target;
- target.node_ = child;
- target.priority_ = 1;
-
- for (int i = 0; i < keywords.size(); ++i) {
- target.ref_ = refForAtom(keywords.at(i));
- QString key = Doc::canonicalTitle(keywords.at(i)->string());
- targetRecMultiMap_.insert(key, target);
- }
- }
- if (child->doc().hasTargets()) {
- const QList<Atom*>& toc = child->doc().targets();
- TargetRec target;
- target.node_ = child;
- target.priority_ = 2;
-
- for (int i = 0; i < toc.size(); ++i) {
- target.ref_ = refForAtom(toc.at(i));
- QString key = Doc::canonicalTitle(toc.at(i)->string());
- targetRecMultiMap_.insert(key, target);
- }
- }
}
}
@@ -1096,17 +1457,6 @@ void QDocDatabase::generateIndex(const QString& fileName,
QDocIndexFiles::destroyQDocIndexFiles();
}
-QString QDocDatabase::refForAtom(const Atom* atom)
-{
- if (atom) {
- if (atom->type() == Atom::SectionLeft)
- return Doc::canonicalTitle(Text::sectionHeading(atom).toString());
- if (atom->type() == Atom::Target)
- return Doc::canonicalTitle(atom->string());
- }
- return QString();
-}
-
/*!
If there are open namespaces, search for the function node
having the same function name as the \a clone node in each
@@ -1135,21 +1485,28 @@ FunctionNode* QDocDatabase::findNodeInOpenNamespace(const QStringList& parentPat
}
/*!
- Find a node of the specified \a type and \a subtype that is
- reached with the specified \a path. If such a node is found
- in an open namespace, prefix \a path with the name of the
- open namespace and "::" and return a pointer to the node.
- Othewrwise return 0.
- */
-Node* QDocDatabase::findNodeInOpenNamespace(QStringList& path,
- Node::Type type,
- Node::SubType subtype)
+ Find a node of the specified \a type that is reached with
+ the specified \a path qualified with the name of one of the
+ open namespaces (might not be any open ones). If the node
+ is found in an open namespace, prefix \a path with the name
+ of the open namespace and "::" and return a pointer to the
+ node. Othewrwise return 0.
+
+ This function only searches in the current primary tree.
+ */
+Node* QDocDatabase::findNodeInOpenNamespace(QStringList& path, Node::Type type)
{
+ if (path.isEmpty())
+ return 0;
Node* n = 0;
if (!openNamespaces_.isEmpty()) {
foreach (const QString& t, openNamespaces_) {
- QStringList p = t.split("::") + path;
- n = findNodeByNameAndType(p, type, subtype);
+ QStringList p;
+ if (t != path[0])
+ p = t.split("::") + path;
+ else
+ p = path;
+ n = primaryTree()->findNodeByNameAndType(p, type);
if (n) {
path = p;
break;
@@ -1159,4 +1516,148 @@ Node* QDocDatabase::findNodeInOpenNamespace(QStringList& path,
return n;
}
+/*!
+ Finds all the collection nodes of type \a nt into the
+ collection node map \a cnn. Nodes that match \a relative
+ are not included.
+ */
+void QDocDatabase::mergeCollections(Node::Type nt, CNMap& cnm, const Node* relative)
+{
+ QRegExp singleDigit("\\b([0-9])\\b");
+ CNMultiMap cnmm;
+ forest_.mergeCollectionMaps(nt, cnmm);
+ cnm.clear();
+ if (cnmm.isEmpty())
+ return;
+ QStringList keys = cnmm.uniqueKeys();
+ foreach (QString key, keys) {
+ QList<CollectionNode*> values = cnmm.values(key);
+ CollectionNode* n = 0;
+ foreach (CollectionNode* v, values) {
+ if (v && v->wasSeen() && (v != relative)) {
+ n = v;
+ break;
+ }
+ }
+ if (n) {
+ if (values.size() > 1) {
+ foreach (CollectionNode* v, values) {
+ if (v != n) {
+ foreach (Node* t, v->members())
+ n->addMember(t);
+ }
+ }
+ }
+ if (!n->members().isEmpty()) {
+ QString sortKey = n->fullTitle().toLower();
+ if (sortKey.startsWith("the "))
+ sortKey.remove(0, 4);
+ sortKey.replace(singleDigit, "0\\1");
+ cnm.insert(sortKey, n);
+ }
+ }
+ }
+}
+
+/*!
+ Finds all the collection nodes with the same name
+ and type as \a cn and merges their members into the
+ members list of \a cn.
+ */
+void QDocDatabase::mergeCollections(CollectionNode* cn)
+{
+ CollectionList cl;
+ forest_.getCorrespondingCollections(cn, cl);
+ if (!cl.empty()) {
+ foreach (CollectionNode* v, cl) {
+ if (v != cn) {
+ foreach (Node* t, v->members())
+ cn->addMember(t);
+ }
+ }
+ }
+}
+
+
+/*!
+ This function is called when the \a{atom} might be a link
+ atom. It handles the optional, square bracket parameters
+ for the link command.
+ */
+Node* QDocDatabase::findNode(const Atom* atom)
+{
+ QStringList path(atom->string());
+ if (atom->specifiesDomain()) {
+ return atom->domain()->findNodeByNameAndType(path, atom->goal());
+ }
+ qDebug() << "FINDNODE:" << path << atom->goal();
+ return forest_.findNodeByNameAndType(path, atom->goal());
+}
+
+const DocNode* QDocDatabase::findDocNodeByTitle(const Atom* atom)
+{
+ return forest_.findDocNodeByTitle(atom->string());
+}
+
+/*!
+ Searches for the node that matches the path in \a atom. The
+ \a relative node is used if the first leg of the path is
+ empty, i.e. if the path begins with a hashtag. The function
+ also sets \a ref if there remains an unused leg in the path
+ after the node is found. The node is returned as well as the
+ \a ref. If the returned node pointer is null, \a ref is not
+ valid.
+ */
+const Node* QDocDatabase::findNode(const Atom* atom, const Node* relative, QString& ref)
+{
+ const Node* node = 0;
+ QStringList path = atom->string().split("#");
+ QString first = path.first().trimmed();
+ path.removeFirst();
+
+ if (first.isEmpty())
+ node = relative; // search for a target on the current page.
+ else if (atom->specifiesDomain()) {
+ qDebug() << "Processing LinkAtom";
+ if (first.endsWith(".html")) { // The target is an html file.
+ node = atom->domain()->findNodeByNameAndType(QStringList(first), Node::Document);
+ }
+ else if (first.endsWith("()")) { // The target is a C++ function or QML method.
+ node = atom->domain()->resolveFunctionTarget(first, 0); //relative);
+ }
+ else {
+ node = atom->domain()->resolveTarget(first, 0); // relative);
+ if (!node)
+ node = atom->domain()->findUnambiguousTarget(first, ref); // ref
+ if (!node && path.isEmpty())
+ node = atom->domain()->findDocNodeByTitle(first);
+ }
+ }
+ else {
+ if (first.endsWith(".html")) { // The target is an html file.
+ node = findNodeByNameAndType(QStringList(first), Node::Document); // ref
+ }
+ else if (first.endsWith("()")) { // The target is a C++ function or QML method.
+ node = resolveFunctionTarget(first, relative);
+ }
+ else {
+ node = resolveTarget(first, relative); // ref
+ if (!node)
+ node = findUnambiguousTarget(first, ref); // ref
+ if (!node && path.isEmpty())
+ node = findDocNodeByTitle(first);
+ }
+ }
+ if (node && ref.isEmpty()) {
+ if (!node->url().isEmpty())
+ return node;
+ if (!path.isEmpty()) {
+ ref = findTarget(path.first(), node);
+ if (ref.isEmpty())
+ node = 0;
+ }
+ }
+ return node;
+}
+
QT_END_NAMESPACE
diff --git a/src/tools/qdoc/qdocdatabase.h b/src/tools/qdoc/qdocdatabase.h
index 4decba5f79..99d1c46ca2 100644
--- a/src/tools/qdoc/qdocdatabase.h
+++ b/src/tools/qdoc/qdocdatabase.h
@@ -45,19 +45,21 @@
#include <qstring.h>
#include <qmap.h>
#include "tree.h"
+#include "config.h"
+#include "text.h"
+#include <qdebug.h>
QT_BEGIN_NAMESPACE
-typedef QMap<QString, DocNode*> DocNodeMap;
-typedef QMap<QString, QmlClassNode*> QmlTypeMap;
typedef QMap<QString, NodeMap> NodeMapMap;
typedef QMap<QString, NodeMultiMap> NodeMultiMapMap;
typedef QMultiMap<QString, Node*> QDocMultiMap;
typedef QMap<Text, const Node*> TextToNodeMap;
-typedef QMultiMap<QString, DocNode*> DocNodeMultiMap;
+typedef QList<CollectionNode*> CollectionList;
class Atom;
class Generator;
+class QDocDatabase;
enum FindFlag {
SearchBaseClasses = 0x1,
@@ -65,20 +67,139 @@ enum FindFlag {
NonFunction = 0x4
};
-struct TargetRec
+class QDocForest
{
public:
- enum Type { Unknown, Target, Keyword, Contents, Class, Function, Page, Subtitle };
- TargetRec() : node_(0), priority_(INT_MAX), type_(Unknown) { }
- bool isEmpty() const { return ref_.isEmpty(); }
- //void debug(int idx, const QString& key);
- Node* node_;
- QString ref_;
- int priority_;
- Type type_;
-};
-typedef QMultiMap<QString, TargetRec> TargetRecMultiMap;
+ friend class QDocDatabase;
+ QDocForest(QDocDatabase* qdb)
+ : qdb_(qdb), primaryTree_(0), currentIndex_(0) { }
+ ~QDocForest();
+
+ NamespaceNode* firstRoot();
+ NamespaceNode* nextRoot();
+ Tree* firstTree();
+ Tree* nextTree();
+ Tree* primaryTree() { return primaryTree_; }
+ Tree* findTree(const QString& t) { return forest_.value(t); }
+ NamespaceNode* primaryTreeRoot() { return (primaryTree_ ? primaryTree_->root() : 0); }
+ bool isEmpty() { return searchOrder().isEmpty(); }
+ bool done() { return (currentIndex_ >= searchOrder().size()); }
+ const QVector<Tree*>& searchOrder();
+ const QVector<Tree*>& indexSearchOrder();
+ void setSearchOrder();
+
+ const Node* findNode(const QStringList& path, const Node* relative, int findFlags) {
+ foreach (Tree* t, searchOrder()) {
+ const Node* n = t->findNode(path, relative, findFlags);
+ if (n)
+ return n;
+ relative = 0;
+ }
+ return 0;
+ }
+
+ Node* findNodeByNameAndType(const QStringList& path, Node::Type type) {
+ foreach (Tree* t, searchOrder()) {
+ Node* n = t->findNodeByNameAndType(path, type);
+ if (n)
+ return n;
+ }
+ return 0;
+ }
+
+ ClassNode* findClassNode(const QStringList& path) {
+ foreach (Tree* t, searchOrder()) {
+ ClassNode* n = t->findClassNode(path);
+ if (n)
+ return n;
+ }
+ return 0;
+ }
+
+ InnerNode* findRelatesNode(const QStringList& path) {
+ foreach (Tree* t, searchOrder()) {
+ InnerNode* n = t->findRelatesNode(path);
+ if (n)
+ return n;
+ }
+ return 0;
+ }
+
+ const Node* resolveFunctionTarget(const QString& target, const Node* relative) {
+ foreach (Tree* t, searchOrder()) {
+ const Node* n = t->resolveFunctionTarget(target, relative);
+ if (n)
+ return n;
+ relative = 0;
+ }
+ return 0;
+ }
+ const Node* resolveTarget(const QString& target, const Node* relative);
+
+ const Node* resolveType(const QStringList& path, const Node* relative)
+ {
+ foreach (Tree* t, searchOrder()) {
+ const Node* n = resolveTypeHelper(path, relative, t);
+ if (n)
+ return n;
+ relative = 0;
+ }
+ return 0;
+ }
+
+ const Node* findUnambiguousTarget(const QString& target, QString& ref)
+ {
+ foreach (Tree* t, searchOrder()) {
+ const Node* n = t->findUnambiguousTarget(target, ref);
+ if (n)
+ return n;
+ }
+ return 0;
+ }
+ const DocNode* findDocNodeByTitle(const QString& title)
+ {
+ foreach (Tree* t, searchOrder()) {
+ const DocNode* n = t->findDocNodeByTitle(title);
+ if (n)
+ return n;
+ }
+ return 0;
+ }
+
+ QmlClassNode* lookupQmlType(const QString& name)
+ {
+ foreach (Tree* t, searchOrder()) {
+ QmlClassNode* qcn = t->lookupQmlType(name);
+ if (qcn)
+ return qcn;
+ }
+ return 0;
+ }
+ void mergeCollectionMaps(Node::Type nt, CNMultiMap& cnmm);
+ void getCorrespondingCollections(CollectionNode* cn, CollectionList& cl)
+ {
+ foreach (Tree* t, searchOrder()) {
+ CollectionNode* ccn = t->getCorrespondingCollection(cn);
+ if (ccn)
+ cl.append(ccn);
+ }
+ }
+
+ private:
+ void newPrimaryTree(const QString& module);
+ NamespaceNode* newIndexTree(const QString& module);
+ const Node* resolveTypeHelper(const QStringList& path, const Node* relative, Tree* t);
+
+ private:
+ QDocDatabase* qdb_;
+ Tree* primaryTree_;
+ int currentIndex_;
+ QMap<QString, Tree*> forest_;
+ QVector<Tree*> searchOrder_;
+ QVector<Tree*> indexSearchOrder_;
+ QVector<QString> moduleNames_;
+};
class QDocDatabase
{
@@ -89,100 +210,136 @@ class QDocDatabase
static void destroyQdocDB();
~QDocDatabase();
- const DocNodeMap& groups() const { return groups_; }
- const DocNodeMap& modules() const { return modules_; }
- const DocNodeMap& qmlModules() const { return qmlModules_; }
-
- DocNode* getGroup(const QString& name);
- DocNode* findGroup(const QString& name);
- DocNode* findModule(const QString& name);
- QmlModuleNode* findQmlModule(const QString& name);
-
- DocNode* addGroup(const QString& name);
- DocNode* addModule(const QString& name);
- QmlModuleNode* addQmlModule(const QString& name);
-
- DocNode* addToGroup(const QString& name, Node* node);
- DocNode* addToModule(const QString& name, Node* node);
- void addToQmlModule(const QString& name, Node* node);
-
- QmlClassNode* findQmlType(const QString& qmid, const QString& name) const;
- QmlClassNode* findQmlType(const ImportRec& import, const QString& name) const;
-
- void findAllClasses(const InnerNode *node);
- void findAllFunctions(const InnerNode *node);
- void findAllLegaleseTexts(const InnerNode *node);
- void findAllNamespaces(const InnerNode *node);
- void findAllObsoleteThings(const InnerNode* node);
- void findAllSince(const InnerNode *node);
- void buildCollections();
-
- // special collection access functions
- NodeMap& getCppClasses() { return nonCompatClasses_; }
- NodeMap& getMainClasses() { return mainClasses_; }
- NodeMap& getCompatibilityClasses() { return compatClasses_; }
- NodeMap& getObsoleteClasses() { return obsoleteClasses_; }
- NodeMap& getClassesWithObsoleteMembers() { return classesWithObsoleteMembers_; }
- NodeMap& getObsoleteQmlTypes() { return obsoleteQmlTypes_; }
- NodeMap& getQmlTypesWithObsoleteMembers() { return qmlTypesWithObsoleteMembers_; }
- NodeMap& getNamespaces() { return namespaceIndex_; }
- NodeMap& getServiceClasses() { return serviceClasses_; }
- NodeMap& getQmlTypes() { return qmlClasses_; }
- NodeMapMap& getFunctionIndex() { return funcIndex_; }
- TextToNodeMap& getLegaleseTexts() { return legaleseTexts_; }
- const NodeMap& getClassMap(const QString& key) const;
- const NodeMap& getQmlTypeMap(const QString& key) const;
- const NodeMultiMap& getSinceMap(const QString& key) const;
-
- const Node* resolveTarget(const QString& target, const Node* relative, const Node* self=0);
- const Node* findNodeForTarget(const QString& target, const Node* relative);
- void insertTarget(const QString& name, TargetRec::Type type, Node* node, int priority);
-
- /* convenience functions
- Many of these will be either eliminated or replaced.
- */
- QString refForAtom(const Atom* atom);
- Tree* tree() { return tree_; }
- NamespaceNode* treeRoot() { return tree_->root(); }
- void resolveInheritance() { tree_->resolveInheritance(); }
- void resolveQmlInheritance(InnerNode* root);
- void resolveIssues();
- void fixInheritance() { tree_->fixInheritance(); }
- void resolveProperties() { tree_->resolveProperties(); }
+ Tree* findTree(const QString& t) { return forest_.findTree(t); }
+ const CNMap& groups() { return primaryTree()->groups(); }
+ const CNMap& modules() { return primaryTree()->modules(); }
+ const CNMap& qmlModules() { return primaryTree()->qmlModules(); }
+
+ GroupNode* getGroup(const QString& name) { return primaryTree()->getGroup(name); }
+ GroupNode* findGroup(const QString& name) { return primaryTree()->findGroup(name); }
+ ModuleNode* findModule(const QString& name) { return primaryTree()->findModule(name); }
+ QmlModuleNode* findQmlModule(const QString& name) { return primaryTree()->findQmlModule(name); }
- const Node* findNode(const QStringList& path) { return tree_->findNode(path); }
- ClassNode* findClassNode(const QStringList& path) { return tree_->findClassNode(path); }
- NamespaceNode* findNamespaceNode(const QStringList& path) { return tree_->findNamespaceNode(path); }
+ GroupNode* addGroup(const QString& name) { return primaryTree()->addGroup(name); }
+ ModuleNode* addModule(const QString& name) { return primaryTree()->addModule(name); }
+ QmlModuleNode* addQmlModule(const QString& name) { return primaryTree()->addQmlModule(name); }
- NameCollisionNode* findCollisionNode(const QString& name) const {
- return tree_->findCollisionNode(name);
+ GroupNode* addToGroup(const QString& name, Node* node) {
+ return primaryTree()->addToGroup(name, node);
}
+ ModuleNode* addToModule(const QString& name, Node* node) {
+ return primaryTree()->addToModule(name, node);
+ }
+ QmlModuleNode* addToQmlModule(const QString& name, Node* node) {
+ return primaryTree()->addToQmlModule(name, node);
+ }
+ void addExampleNode(ExampleNode* n) { primaryTree()->addExampleNode(n); }
+ ExampleNodeMap& exampleNodeMap() { return primaryTree()->exampleNodeMap(); }
+
+ QmlClassNode* findQmlType(const QString& name);
+ QmlClassNode* findQmlType(const QString& qmid, const QString& name);
+ QmlClassNode* findQmlType(const ImportRec& import, const QString& name);
- const DocNode* findDocNodeByTitle(const QString& title, const Node* relative = 0) const;
- const Node *findUnambiguousTarget(const QString &target, QString& ref, const Node* relative);
- QString findTarget(const QString &target, const Node *node) const;
- void resolveTargets(InnerNode* root);
+ private:
+ void findAllClasses(InnerNode *node);
+ void findAllFunctions(InnerNode *node);
+ void findAllLegaleseTexts(InnerNode *node);
+ void findAllNamespaces(InnerNode *node);
+ void findAllObsoleteThings(InnerNode* node);
+ void findAllSince(InnerNode *node);
+
+ public:
+ /*******************************************************************
+ special collection access functions
+ ********************************************************************/
+ NodeMap& getCppClasses();
+ NodeMap& getMainClasses();
+ NodeMap& getCompatibilityClasses();
+ NodeMap& getObsoleteClasses();
+ NodeMap& getClassesWithObsoleteMembers();
+ NodeMap& getObsoleteQmlTypes();
+ NodeMap& getQmlTypesWithObsoleteMembers();
+ NodeMap& getNamespaces();
+ NodeMap& getServiceClasses();
+ NodeMap& getQmlBasicTypes();
+ NodeMap& getQmlTypes();
+ NodeMapMap& getFunctionIndex();
+ TextToNodeMap& getLegaleseTexts();
+ const NodeMap& getClassMap(const QString& key);
+ const NodeMap& getQmlTypeMap(const QString& key);
+ const NodeMultiMap& getSinceMap(const QString& key);
+
+ /*******************************************************************
+ Many of these will be either eliminated or replaced.
+ ********************************************************************/
+ void resolveInheritance() { primaryTree()->resolveInheritance(); }
+ void resolveQmlInheritance(InnerNode* root);
+ void resolveIssues();
+ void fixInheritance() { primaryTree()->fixInheritance(); }
+ void resolveProperties() { primaryTree()->resolveProperties(); }
+
+ void resolveTargets() {
+ primaryTree()->resolveTargets(primaryTreeRoot());
+ }
+ void insertTarget(const QString& name, TargetRec::Type type, Node* node, int priority) {
+ primaryTree()->insertTarget(name, type, node, priority);
+ }
+ /*******************************************************************
+ The functions declared below are called for the current tree only.
+ ********************************************************************/
FunctionNode* findFunctionNode(const QStringList& parentPath, const FunctionNode* clone) {
- return tree_->findFunctionNode(parentPath, clone);
+ return primaryTree()->findFunctionNode(parentPath, clone);
+ }
+ FunctionNode* findNodeInOpenNamespace(const QStringList& parentPath, const FunctionNode* clone);
+ Node* findNodeInOpenNamespace(QStringList& path, Node::Type type);
+ NameCollisionNode* findCollisionNode(const QString& name) {
+ return primaryTree()->findCollisionNode(name);
}
- Node* findNodeByNameAndType(const QStringList& path, Node::Type type, Node::SubType subtype){
- return tree_->findNodeByNameAndType(path, type, subtype, 0);
+ NameCollisionNode* checkForCollision(const QString& name) {
+ return primaryTree()->checkForCollision(name);
}
- NameCollisionNode* checkForCollision(const QString& name) const {
- return tree_->checkForCollision(name);
+ /*******************************************************************/
+
+ /*******************************************************************
+ The functions declared below handle the parameters in '[' ']'.
+ ********************************************************************/
+ Node* findNode(const Atom* atom);
+ const Node* findNode(const Atom* atom, const Node* relative, QString& ref);
+ const DocNode* findDocNodeByTitle(const Atom* atom);
+ /*******************************************************************/
+
+ /*******************************************************************
+ The functions declared below are called for all trees.
+ ********************************************************************/
+ ClassNode* findClassNode(const QStringList& path) { return forest_.findClassNode(path); }
+ InnerNode* findRelatesNode(const QStringList& path) { return forest_.findRelatesNode(path); }
+ const Node* resolveTarget(const QString& target, const Node* relative) {
+ return forest_.resolveTarget(target, relative);
+ }
+ const Node* resolveFunctionTarget(const QString& target, const Node* relative) {
+ return forest_.resolveFunctionTarget(target, relative);
+ }
+ const Node* resolveType(const QString& type, const Node* relative);
+ const Node* findNodeForTarget(const QString& target, const Node* relative);
+ const DocNode* findDocNodeByTitle(const QString& title) {
+ return forest_.findDocNodeByTitle(title);
}
- void addBaseClass(ClassNode* subclass,
- Node::Access access,
- const QStringList& basePath,
- const QString& dataTypeWithTemplateArgs,
- InnerNode* parent) {
- tree_->addBaseClass(subclass, access, basePath, dataTypeWithTemplateArgs, parent);
+ const Node* findUnambiguousTarget(const QString& target, QString& ref) {
+ return forest_.findUnambiguousTarget(target, ref);
+ }
+ Node* findNodeByNameAndType(const QStringList& path, Node::Type type) {
+ return forest_.findNodeByNameAndType(path, type);
+ }
+ /*******************************************************************/
+
+ QString findTarget(const QString& target, const Node* node) {
+ return node->root()->tree()->findTarget(target, node);
}
void addPropertyFunction(PropertyNode* property,
const QString& funcName,
PropertyNode::FunctionRole funcRole) {
- tree_->addPropertyFunction(property, funcName, funcRole);
+ primaryTree()->addPropertyFunction(property, funcName, funcRole);
}
void setVersion(const QString& v) { version_ = v; }
@@ -198,37 +355,43 @@ class QDocDatabase
void clearOpenNamespaces() { openNamespaces_.clear(); }
void insertOpenNamespace(const QString& path) { openNamespaces_.insert(path); }
- FunctionNode* findNodeInOpenNamespace(const QStringList& parentPath, const FunctionNode* clone);
- Node* findNodeInOpenNamespace(QStringList& path, Node::Type type, Node::SubType subtype);
void setShowInternal(bool value) { showInternal_ = value; }
- /* debugging functions */
- void printModules() const;
- void printQmlModules() const;
+ // Try to make this function private.
+ QDocForest& forest() { return forest_; }
+ NamespaceNode* primaryTreeRoot() { return forest_.primaryTreeRoot(); }
+ void newPrimaryTree(const QString& module) { forest_.newPrimaryTree(module); }
+ NamespaceNode* newIndexTree(const QString& module) { return forest_.newIndexTree(module); }
+ const QVector<Tree*>& searchOrder() { return forest_.searchOrder(); }
+ void setSearchOrder() { forest_.setSearchOrder(); }
+ void mergeCollections(Node::Type nt, CNMap& cnm, const Node* relative);
+ void mergeCollections(CollectionNode* cn);
private:
friend class QDocIndexFiles;
friend class QDocTagFiles;
const Node* findNode(const QStringList& path, const Node* relative, int findFlags) {
- return tree_->findNode(path, relative, findFlags);
+ return forest_.findNode(path, relative, findFlags);
}
+ void processForest(void (QDocDatabase::*) (InnerNode*));
+ static void initializeDB();
private:
QDocDatabase();
- QDocDatabase(QDocDatabase const& ) { }; // copy constructor is private
- QDocDatabase& operator=(QDocDatabase const& ); // assignment operator is private
+ QDocDatabase(QDocDatabase const& ) : showInternal_(false), forest_(this) { }
+ QDocDatabase& operator=(QDocDatabase const& );
+ Tree* primaryTree() { return forest_.primaryTree(); }
+
+ public:
+ static bool debug;
private:
static QDocDatabase* qdocDB_;
+ static NodeMap typeNodeMap_;
bool showInternal_;
QString version_;
- QDocMultiMap masterMap_;
- Tree* tree_;
- DocNodeMap groups_;
- DocNodeMap modules_;
- DocNodeMap qmlModules_;
- QmlTypeMap qmlTypeMap_;
+ QDocForest forest_;
NodeMap nonCompatClasses_;
NodeMap mainClasses_;
@@ -239,14 +402,13 @@ class QDocDatabase
NodeMap qmlTypesWithObsoleteMembers_;
NodeMap namespaceIndex_;
NodeMap serviceClasses_;
+ NodeMap qmlBasicTypes_;
NodeMap qmlClasses_;
NodeMapMap newClassMaps_;
NodeMapMap newQmlTypeMaps_;
NodeMultiMapMap newSinceMaps_;
NodeMapMap funcIndex_;
TextToNodeMap legaleseTexts_;
- DocNodeMultiMap docNodesByTitle_;
- TargetRecMultiMap targetRecMultiMap_;
QSet<QString> openNamespaces_;
};
diff --git a/src/tools/qdoc/qdocindexfiles.cpp b/src/tools/qdoc/qdocindexfiles.cpp
index 00c9c55020..4531ce8eea 100644
--- a/src/tools/qdoc/qdocindexfiles.cpp
+++ b/src/tools/qdoc/qdocindexfiles.cpp
@@ -54,6 +54,8 @@
QT_BEGIN_NAMESPACE
+static Node* top = 0;
+
/*!
\class QDocIndexFiles
@@ -77,6 +79,7 @@ QDocIndexFiles::QDocIndexFiles()
QDocIndexFiles::~QDocIndexFiles()
{
qdb_ = 0;
+ gen_ = 0;
}
/*!
@@ -109,10 +112,13 @@ void QDocIndexFiles::readIndexes(const QStringList& indexFiles)
foreach (const QString& indexFile, indexFiles) {
QString msg = "Loading index file: " + indexFile;
Location::logToStdErr(msg);
+ //qDebug() << msg;
readIndexFile(indexFile);
}
}
+static bool readingRoot = true;
+
/*!
Reads and parses the index file at \a path.
*/
@@ -144,13 +150,16 @@ void QDocIndexFiles::readIndexFile(const QString& path)
basesList_.clear();
relatedList_.clear();
+ readingRoot = true;
+ NamespaceNode* root = qdb_->newIndexTree(project_);
+
// Scan all elements in the XML file, constructing a map that contains
// base classes for each class found.
-
QDomElement child = indexElement.firstChildElement();
while (!child.isNull()) {
- readIndexSection(child, qdb_->treeRoot(), indexUrl);
+ readIndexSection(child, root, indexUrl);
child = child.nextSiblingElement();
+ readingRoot = true;
}
// Now that all the base classes have been found for this index,
@@ -164,13 +173,16 @@ void QDocIndexFiles::readIndexFile(const QString& path)
appropriate node(s).
*/
void QDocIndexFiles::readIndexSection(const QDomElement& element,
- InnerNode* parent,
+ Node* current,
const QString& indexUrl)
{
QString name = element.attribute("name");
QString href = element.attribute("href");
Node* node;
Location location;
+ InnerNode* parent = 0;
+ if (current->isInnerNode())
+ parent = static_cast<InnerNode*>(current);
QString filePath;
int lineNo = 0;
@@ -189,9 +201,11 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
}
else if (element.nodeName() == "class") {
node = new ClassNode(parent, name);
- basesList_.append(QPair<ClassNode*,QString>(static_cast<ClassNode*>(node),
- element.attribute("bases")));
-
+ if (element.hasAttribute("bases")) {
+ QString bases = element.attribute("bases");
+ if (!bases.isEmpty())
+ basesList_.append(QPair<ClassNode*,QString>(static_cast<ClassNode*>(node), bases));
+ }
if (!indexUrl.isEmpty())
location = Location(indexUrl + QLatin1Char('/') + name.toLower() + ".html");
else if (!indexUrl.isNull())
@@ -201,8 +215,7 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
abstract = true;
node->setAbstract(abstract);
}
- else if ((element.nodeName() == "qmlclass") ||
- ((element.nodeName() == "page") && (element.attribute("subtype") == "qmlclass"))) {
+ else if (element.nodeName() == "qmlclass") {
QmlClassNode* qcn = new QmlClassNode(parent, name);
qcn->setTitle(element.attribute("title"));
QString qmlModuleName = element.attribute("qml-module-name");
@@ -213,8 +226,9 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
abstract = true;
qcn->setAbstract(abstract);
QString qmlFullBaseName = element.attribute("qml-base-type");
- if (!qmlFullBaseName.isEmpty())
+ if (!qmlFullBaseName.isEmpty()) {
qcn->setQmlBaseName(qmlFullBaseName);
+ }
if (element.hasAttribute("location"))
name = element.attribute("location", QString());
if (!indexUrl.isEmpty())
@@ -254,11 +268,11 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
if (element.attribute("writable") == "false")
readonly = true;
QmlPropertyNode* qpn = 0;
- if (parent->type() == Node::Document) {
+ if (parent->isQmlType()) {
QmlClassNode* qcn = static_cast<QmlClassNode*>(parent);
qpn = new QmlPropertyNode(qcn, name, type, attached);
}
- else if (parent->type() == Node::QmlPropertyGroup) {
+ else if (parent->isQmlPropertyGroup()) {
QmlPropertyGroupNode* qpgn = static_cast<QmlPropertyGroupNode*>(parent);
qpn = new QmlPropertyNode(qpgn, name, type, attached);
}
@@ -277,6 +291,31 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
FunctionNode* fn = new FunctionNode(t, parent, name, attached);
node = fn;
}
+ else if (element.nodeName() == "group") {
+ GroupNode* gn = qdb_->addGroup(name);
+ gn->setTitle(element.attribute("title"));
+ gn->setSubTitle(element.attribute("subtitle"));
+ if (element.attribute("seen") == "true")
+ gn->markSeen();
+ node = gn;
+ }
+ else if (element.nodeName() == "module") {
+ ModuleNode* mn = qdb_->addModule(name);
+ mn->setTitle(element.attribute("title"));
+ mn->setSubTitle(element.attribute("subtitle"));
+ if (element.attribute("seen") == "true")
+ mn->markSeen();
+ node = mn;
+ }
+ else if (element.nodeName() == "qmlmodule") {
+ QString t = element.attribute("qml-module-name") + " " + element.attribute("qml-module-version");
+ QmlModuleNode* qmn = qdb_->addQmlModule(t);
+ qmn->setTitle(element.attribute("title"));
+ qmn->setSubTitle(element.attribute("subtitle"));
+ if (element.attribute("seen") == "true")
+ qmn->markSeen();
+ node = qmn;
+ }
else if (element.nodeName() == "page") {
Node::SubType subtype;
Node::PageType ptype = Node::NoPageType;
@@ -293,18 +332,6 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
subtype = Node::File;
ptype = Node::NoPageType;
}
- else if (attr == "group") {
- subtype = Node::Group;
- ptype = Node::OverviewPage;
- }
- else if (attr == "module") {
- subtype = Node::Module;
- ptype = Node::OverviewPage;
- }
- else if (attr == "qmlmodule") {
- subtype = Node::QmlModule;
- ptype = Node::OverviewPage;
- }
else if (attr == "page") {
subtype = Node::Page;
ptype = Node::ArticlePage;
@@ -313,25 +340,10 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
subtype = Node::ExternalPage;
ptype = Node::ArticlePage;
}
- else if (attr == "qmlclass") {
- subtype = Node::QmlClass;
- ptype = Node::ApiPage;
- }
- else if (attr == "qmlbasictype") {
- subtype = Node::QmlBasicType;
- ptype = Node::ApiPage;
- }
else
return;
- DocNode* docNode = 0;
- if (subtype == Node::QmlModule) {
- QString t = element.attribute("qml-module-name") + " " +
- element.attribute("qml-module-version");
- docNode = qdb_->addQmlModule(t);
- }
- else
- docNode = new DocNode(parent, name, subtype, ptype);
+ DocNode* docNode = new DocNode(parent, name, subtype, ptype);
docNode->setTitle(element.attribute("title"));
if (element.hasAttribute("location"))
@@ -383,31 +395,33 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
}
else if (element.nodeName() == "function") {
FunctionNode::Virtualness virt;
- if (element.attribute("virtual") == "non")
+ QString t = element.attribute("virtual");
+ if (t == "non")
virt = FunctionNode::NonVirtual;
- else if (element.attribute("virtual") == "impure")
+ else if (t == "impure")
virt = FunctionNode::ImpureVirtual;
- else if (element.attribute("virtual") == "pure")
+ else if (t == "pure")
virt = FunctionNode::PureVirtual;
else
return;
+ t = element.attribute("meta");
FunctionNode::Metaness meta;
- if (element.attribute("meta") == "plain")
+ if (t == "plain")
meta = FunctionNode::Plain;
- else if (element.attribute("meta") == "signal")
+ else if (t == "signal")
meta = FunctionNode::Signal;
- else if (element.attribute("meta") == "slot")
+ else if (t == "slot")
meta = FunctionNode::Slot;
- else if (element.attribute("meta") == "constructor")
+ else if (t == "constructor")
meta = FunctionNode::Ctor;
- else if (element.attribute("meta") == "destructor")
+ else if (t == "destructor")
meta = FunctionNode::Dtor;
- else if (element.attribute("meta") == "macro")
+ else if (t == "macro")
meta = FunctionNode::MacroWithParams;
- else if (element.attribute("meta") == "macrowithparams")
+ else if (t == "macrowithparams")
meta = FunctionNode::MacroWithParams;
- else if (element.attribute("meta") == "macrowithoutparams")
+ else if (t == "macrowithoutparams")
meta = FunctionNode::MacroWithoutParams;
else
return;
@@ -426,6 +440,10 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
QPair<FunctionNode*,QString>(functionNode,
element.attribute("relates")));
}
+ /*
+ Note: The "signature" attribute was written to the
+ index file, but it is not read back in. Is that ok?
+ */
QDomElement child = element.firstChildElement("parameter");
while (!child.isNull()) {
@@ -453,15 +471,15 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
location = Location(parent->name().toLower() + ".html");
}
else if (element.nodeName() == "keyword") {
- qdb_->insertTarget(name, TargetRec::Keyword, parent, 1);
+ qdb_->insertTarget(name, TargetRec::Keyword, current, 1);
return;
}
else if (element.nodeName() == "target") {
- qdb_->insertTarget(name, TargetRec::Target, parent, 2);
+ qdb_->insertTarget(name, TargetRec::Target, current, 2);
return;
}
else if (element.nodeName() == "contents") {
- qdb_->insertTarget(name, TargetRec::Contents, parent, 3);
+ qdb_->insertTarget(name, TargetRec::Contents, current, 3);
return;
}
else
@@ -513,7 +531,7 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
QString moduleName = element.attribute("module");
if (!moduleName.isEmpty())
- node->setModuleName(moduleName);
+ qdb_->addToModule(moduleName, node);
if (!href.isEmpty()) {
if (node->isExternalPage())
node->setUrl(href);
@@ -529,15 +547,8 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
QString groupsAttr = element.attribute("groups");
if (!groupsAttr.isEmpty()) {
QStringList groupNames = groupsAttr.split(",");
- for (int i=0; i<groupNames.size(); ++i) {
- DocNode* dn = qdb_->findGroup(groupNames[i]);
- if (dn) {
- dn->addMember(node);
- }
- else {
- qDebug() << "NODE:" << node->name() << "GROUPS:" << groupNames;
- qDebug() << "DID NOT FIND GROUP for:" << node->name();
- }
+ foreach (QString name, groupNames) {
+ qdb_->addToGroup(name, node);
}
}
@@ -558,83 +569,59 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
node->setReconstitutedBrief(briefAttr);
}
- if (node->isInnerNode()) {
- InnerNode* inner = static_cast<InnerNode*>(node);
+ // zzz
+ bool useParent = (element.nodeName() == "namespace" && name.isEmpty());
+ if (element.hasChildNodes()) {
QDomElement child = element.firstChildElement();
while (!child.isNull()) {
- if (element.nodeName() == "class") {
- readIndexSection(child, inner, indexUrl);
- }
- else if (element.nodeName() == "qmlclass") {
- readIndexSection(child, inner, indexUrl);
- }
- else if (element.nodeName() == "page") {
- readIndexSection(child, inner, indexUrl);
- }
- else if (element.nodeName() == "namespace" && !name.isEmpty()) {
- // The root node in the index is a namespace with an empty name.
- readIndexSection(child, inner, indexUrl);
- }
- else {
+ if (useParent)
readIndexSection(child, parent, indexUrl);
- }
+ else
+ readIndexSection(child, node, indexUrl);
child = child.nextSiblingElement();
}
}
}
/*!
+ This function tries to resolve class inheritance immediately
+ after the index file is read. It is not always possible to
+ resolve a class inheritance at this point, because the base
+ class might be in an index file that hasn't been read yet, or
+ it might be in one of the header files that will be read for
+ the current module. These cases will be resolved after all
+ the index files and header and source files have been read,
+ just prior to beginning the generate phase for the current
+ module.
+
+ I don't think this is completely correct because it always
+ sets the access to public.
*/
void QDocIndexFiles::resolveIndex()
{
QPair<ClassNode*,QString> pair;
foreach (pair, basesList_) {
foreach (const QString& base, pair.second.split(QLatin1Char(','))) {
- Node* n = qdb_->treeRoot()->findChildNodeByNameAndType(base, Node::Class);
- if (n) {
- pair.first->addBaseClass(Node::Public, static_cast<ClassNode*>(n));
- }
+ QStringList basePath = base.split(QString("::"));
+ Node* n = qdb_->findClassNode(basePath);
+ if (n)
+ pair.first->addResolvedBaseClass(Node::Public, static_cast<ClassNode*>(n));
+ else
+ pair.first->addUnresolvedBaseClass(Node::Public, basePath, QString());
}
}
QPair<FunctionNode*,QString> relatedPair;
foreach (relatedPair, relatedList_) {
- Node* n = qdb_->treeRoot()->findChildNodeByNameAndType(relatedPair.second, Node::Class);
+ QStringList path = relatedPair.second.split("::");
+ Node* n = qdb_->findRelatesNode(path);
if (n)
relatedPair.first->setRelates(static_cast<ClassNode*>(n));
}
-}
-
-/*!
- Normally this is used for writing the \e groups attribute,
- but it can be used for writing any attribute with a list
- value that comes from some subset of the members of \a n.
- \note The members of \a n are \e not the children of \a n.
-
- The names we want to include are the names of the members
- of \a n that have node type \a t and node subtype \a st.
- The attribute name is \a attr. The names are joined with
- the space character and written with \a writer.
- */
-void QDocIndexFiles::writeMembersAttribute(QXmlStreamWriter& writer,
- const InnerNode* n,
- Node::Type t,
- Node::SubType st,
- const QString& attr)
-{
- const NodeList& members = n->members();
- if (!members.isEmpty()) {
- QStringList names;
- NodeList::ConstIterator i = members.constBegin();
- while (i != members.constEnd()) {
- if ((*i)->type() == t && (*i)->subType() == st)
- names.append((*i)->name());
- ++i;
- }
- if (!names.isEmpty())
- writer.writeAttribute(attr, names.join(","));
- }
+ // No longer needed.
+ basesList_.clear();
+ relatedList_.clear();
}
/*!
@@ -663,17 +650,29 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
case Node::Class:
nodeName = "class";
break;
- case Node::Document:
- nodeName = "page";
- if (node->subType() == Node::QmlClass) {
+ case Node::QmlType:
+ {
nodeName = "qmlclass";
QmlModuleNode* qmn = node->qmlModule();
if (qmn)
qmlModuleName = qmn->qmlModuleName();
qmlFullBaseName = node->qmlFullBaseName();
}
- else if (node->subType() == Node::QmlBasicType)
- nodeName = "qmlbasictype";
+ break;
+ case Node::QmlBasicType:
+ nodeName = "qmlbasictype";
+ break;
+ case Node::Document:
+ nodeName = "page";
+ break;
+ case Node::Group:
+ nodeName = "group";
+ break;
+ case Node::Module:
+ nodeName = "module";
+ break;
+ case Node::QmlModule:
+ nodeName = "qmlmodule";
break;
case Node::Enum:
nodeName = "enum";
@@ -741,14 +740,14 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
QString objName = node->name();
// Special case: only the root node should have an empty name.
- if (objName.isEmpty() && node != qdb_->treeRoot())
+ if (objName.isEmpty() && node != qdb_->primaryTreeRoot())
return false;
writer.writeStartElement(nodeName);
QXmlStreamAttributes attributes;
- if (node->type() != Node::Document) {
+ if (!node->isDocNode() && !node->isGroup() && !node->isModule() && !node->isQmlModule()) {
QString threadSafety;
switch (node->threadSafeness()) {
case Node::NonReentrant:
@@ -832,10 +831,12 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
if (!href.isEmpty())
writer.writeAttribute("href", href);
- writer.writeAttribute("access", access);
writer.writeAttribute("status", status);
- if (node->isAbstract())
- writer.writeAttribute("abstract", "true");
+ if (!node->isDocNode() && !node->isGroup() && !node->isModule() && !node->isQmlModule()) {
+ writer.writeAttribute("access", access);
+ if (node->isAbstract())
+ writer.writeAttribute("abstract", "true");
+ }
if (!node->location().fileName().isEmpty())
writer.writeAttribute("location", node->location().fileName());
if (!node->location().filePath().isEmpty()) {
@@ -847,7 +848,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
writer.writeAttribute("since", node->since());
}
- QString brief = node->doc().briefText().toString();
+ QString brief = node->doc().trimmedBriefText(node->name()).toString();
switch (node->type()) {
case Node::Class:
{
@@ -856,13 +857,16 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
QList<RelatedClass> bases = classNode->baseClasses();
QSet<QString> baseStrings;
foreach (const RelatedClass& related, bases) {
- ClassNode* baseClassNode = related.node;
- baseStrings.insert(baseClassNode->name());
+ ClassNode* n = related.node_;
+ if (n)
+ baseStrings.insert(n->fullName());
}
- writer.writeAttribute("bases", QStringList(baseStrings.toList()).join(","));
+ if (!baseStrings.isEmpty())
+ writer.writeAttribute("bases", QStringList(baseStrings.toList()).join(","));
if (!node->moduleName().isEmpty())
writer.writeAttribute("module", node->moduleName());
- writeMembersAttribute(writer, classNode, Node::Document, Node::Group, "groups");
+ if (!classNode->groupNames().isEmpty())
+ writer.writeAttribute("groups", classNode->groupNames().join(","));
if (!brief.isEmpty())
writer.writeAttribute("brief", brief);
}
@@ -872,7 +876,20 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
const NamespaceNode* namespaceNode = static_cast<const NamespaceNode*>(node);
if (!namespaceNode->moduleName().isEmpty())
writer.writeAttribute("module", namespaceNode->moduleName());
- writeMembersAttribute(writer, namespaceNode, Node::Document, Node::Group, "groups");
+ if (!namespaceNode->groupNames().isEmpty())
+ writer.writeAttribute("groups", namespaceNode->groupNames().join(","));
+ if (!brief.isEmpty())
+ writer.writeAttribute("brief", brief);
+ }
+ break;
+ case Node::QmlType:
+ {
+ const QmlClassNode* qcn = static_cast<const QmlClassNode*>(node);
+ writer.writeAttribute("title", qcn->title());
+ writer.writeAttribute("fulltitle", qcn->fullTitle());
+ writer.writeAttribute("subtitle", qcn->subTitle());
+ if (!qcn->groupNames().isEmpty())
+ writer.writeAttribute("groups", qcn->groupNames().join(","));
if (!brief.isEmpty())
writer.writeAttribute("brief", brief);
}
@@ -880,8 +897,8 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
case Node::Document:
{
/*
- Document nodes (such as manual pages) contain subtypes,
- titles and other attributes.
+ Document nodes (such as manual pages) have a subtype,
+ a title, and other attributes.
*/
bool writeModuleName = false;
const DocNode* docNode = static_cast<const DocNode*>(node);
@@ -897,26 +914,6 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
case Node::File:
writer.writeAttribute("subtype", "file");
break;
- case Node::Group:
- {
- writer.writeAttribute("subtype", "group");
- writer.writeAttribute("seen", docNode->wasSeen() ? "true" : "false");
- // Groups contain information about their group members.
- const NodeList& members = docNode->members();
- QStringList names;
- foreach (const Node* member, members) {
- names.append(member->name());
- }
- writer.writeAttribute("members", names.join(","));
- writeModuleName = true;
- }
- break;
- case Node::Module:
- writer.writeAttribute("subtype", "module");
- break;
- case Node::QmlModule:
- writer.writeAttribute("subtype", "qmlmodule");
- break;
case Node::Page:
writer.writeAttribute("subtype", "page");
writeModuleName = true;
@@ -924,12 +921,6 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
case Node::ExternalPage:
writer.writeAttribute("subtype", "externalpage");
break;
- case Node::QmlClass:
- //writer.writeAttribute("subtype", "qmlclass");
- break;
- case Node::QmlBasicType:
- //writer.writeAttribute("subtype", "qmlbasictype");
- break;
default:
break;
}
@@ -939,7 +930,82 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
if (!node->moduleName().isEmpty() && writeModuleName) {
writer.writeAttribute("module", node->moduleName());
}
- writeMembersAttribute(writer, docNode, Node::Document, Node::Group, "groups");
+ if (!docNode->groupNames().isEmpty())
+ writer.writeAttribute("groups", docNode->groupNames().join(","));
+ if (!brief.isEmpty())
+ writer.writeAttribute("brief", brief);
+ }
+ break;
+ case Node::Group:
+ {
+ const GroupNode* gn = static_cast<const GroupNode*>(node);
+ writer.writeAttribute("seen", gn->wasSeen() ? "true" : "false");
+ writer.writeAttribute("title", gn->title());
+ if (!gn->subTitle().isEmpty())
+ writer.writeAttribute("subtitle", gn->subTitle());
+ if (!gn->moduleName().isEmpty())
+ writer.writeAttribute("module", gn->moduleName());
+ if (!gn->groupNames().isEmpty())
+ writer.writeAttribute("groups", gn->groupNames().join(","));
+ /*
+ This is not read back in, so it probably
+ shouldn't be written out in the first place.
+ */
+ if (!gn->members().isEmpty()) {
+ QStringList names;
+ foreach (const Node* member, gn->members())
+ names.append(member->name());
+ writer.writeAttribute("members", names.join(","));
+ }
+ if (!brief.isEmpty())
+ writer.writeAttribute("brief", brief);
+ }
+ break;
+ case Node::Module:
+ {
+ const ModuleNode* mn = static_cast<const ModuleNode*>(node);
+ writer.writeAttribute("seen", mn->wasSeen() ? "true" : "false");
+ writer.writeAttribute("title", mn->title());
+ if (!mn->subTitle().isEmpty())
+ writer.writeAttribute("subtitle", mn->subTitle());
+ if (!mn->moduleName().isEmpty())
+ writer.writeAttribute("module", mn->moduleName());
+ if (!mn->groupNames().isEmpty())
+ writer.writeAttribute("groups", mn->groupNames().join(","));
+ /*
+ This is not read back in, so it probably
+ shouldn't be written out in the first place.
+ */
+ if (!mn->members().isEmpty()) {
+ QStringList names;
+ foreach (const Node* member, mn->members())
+ names.append(member->name());
+ writer.writeAttribute("members", names.join(","));
+ }
+ if (!brief.isEmpty())
+ writer.writeAttribute("brief", brief);
+ }
+ case Node::QmlModule:
+ {
+ const QmlModuleNode* qmn = static_cast<const QmlModuleNode*>(node);
+ writer.writeAttribute("seen", qmn->wasSeen() ? "true" : "false");
+ writer.writeAttribute("title", qmn->title());
+ if (!qmn->subTitle().isEmpty())
+ writer.writeAttribute("subtitle", qmn->subTitle());
+ if (!qmn->moduleName().isEmpty())
+ writer.writeAttribute("module", qmn->moduleName());
+ if (!qmn->groupNames().isEmpty())
+ writer.writeAttribute("groups", qmn->groupNames().join(","));
+ /*
+ This is not read back in, so it probably
+ shouldn't be written out in the first place.
+ */
+ if (!qmn->members().isEmpty()) {
+ QStringList names;
+ foreach (const Node* member, qmn->members())
+ names.append(member->name());
+ writer.writeAttribute("members", names.join(","));
+ }
if (!brief.isEmpty())
writer.writeAttribute("brief", brief);
}
@@ -995,14 +1061,34 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
writer.writeAttribute("overload", functionNode->isOverload()?"true":"false");
if (functionNode->isOverload())
writer.writeAttribute("overload-number", QString::number(functionNode->overloadNumber()));
- if (functionNode->relates())
+ if (functionNode->relates()) {
writer.writeAttribute("relates", functionNode->relates()->name());
+ }
const PropertyNode* propertyNode = functionNode->associatedProperty();
if (propertyNode)
writer.writeAttribute("associated-property", propertyNode->name());
writer.writeAttribute("type", functionNode->returnType());
if (!brief.isEmpty())
writer.writeAttribute("brief", brief);
+
+ /*
+ Note: The "signature" attribute is written to the
+ index file, but it is not read back in. Is that ok?
+ */
+ QString signature = functionNode->signature();
+ if (functionNode->isConst())
+ signature += " const";
+ writer.writeAttribute("signature", signature);
+
+ for (int i = 0; i < functionNode->parameters().size(); ++i) {
+ Parameter parameter = functionNode->parameters()[i];
+ writer.writeStartElement("parameter");
+ writer.writeAttribute("left", parameter.leftType());
+ writer.writeAttribute("right", parameter.rightType());
+ writer.writeAttribute("name", parameter.name());
+ writer.writeAttribute("default", parameter.defaultValue());
+ writer.writeEndElement(); // parameter
+ }
}
break;
case Node::QmlProperty:
@@ -1010,7 +1096,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
QmlPropertyNode* qpn = static_cast<QmlPropertyNode*>(node);
writer.writeAttribute("type", qpn->dataType());
writer.writeAttribute("attached", qpn->isAttached() ? "true" : "false");
- writer.writeAttribute("writable", qpn->isWritable(qdb_) ? "true" : "false");
+ writer.writeAttribute("writable", qpn->isWritable() ? "true" : "false");
if (!brief.isEmpty())
writer.writeAttribute("brief", brief);
}
@@ -1070,10 +1156,68 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
writer.writeAttribute("brief", brief);
}
break;
+ case Node::Enum:
+ {
+ const EnumNode* enumNode = static_cast<const EnumNode*>(node);
+ if (enumNode->flagsType()) {
+ writer.writeAttribute("typedef",enumNode->flagsType()->fullDocumentName());
+ }
+ foreach (const EnumItem& item, enumNode->items()) {
+ writer.writeStartElement("value");
+ writer.writeAttribute("name", item.name());
+ writer.writeAttribute("value", item.value());
+ writer.writeEndElement(); // value
+ }
+ }
+ break;
+ case Node::Typedef:
+ {
+ const TypedefNode* typedefNode = static_cast<const TypedefNode*>(node);
+ if (typedefNode->associatedEnum()) {
+ writer.writeAttribute("enum",typedefNode->associatedEnum()->fullDocumentName());
+ }
+ }
+ break;
default:
break;
}
+ /*
+ For our pages, we canonicalize the target, keyword and content
+ item names so that they can be used by qdoc for other sets of
+ documentation.
+
+ The reason we do this here is that we don't want to ruin
+ externally composed indexes, containing non-qdoc-style target names
+ when reading in indexes.
+
+ targets and keywords are now allowed in any node, not just inner nodes.
+ */
+
+ if (node->doc().hasTargets()) {
+ bool external = false;
+ if (node->type() == Node::Document) {
+ const DocNode* docNode = static_cast<const DocNode*>(node);
+ if (docNode->subType() == Node::ExternalPage)
+ external = true;
+ }
+ foreach (const Atom* target, node->doc().targets()) {
+ QString targetName = target->string();
+ if (!external)
+ targetName = Doc::canonicalTitle(targetName);
+ writer.writeStartElement("target");
+ writer.writeAttribute("name", targetName);
+ writer.writeEndElement(); // target
+ }
+ }
+ if (node->doc().hasKeywords()) {
+ foreach (const Atom* keyword, node->doc().keywords()) {
+ writer.writeStartElement("keyword");
+ writer.writeAttribute("name", Doc::canonicalTitle(keyword->string()));
+ writer.writeEndElement(); // keyword
+ }
+ }
+
// Inner nodes and function nodes contain child nodes of some sort, either
// actual child nodes or function parameters. For these, we close the
// opening tag, create child elements, then add a closing tag for the
@@ -1082,36 +1226,6 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
if (node->isInnerNode()) {
const InnerNode* inner = static_cast<const InnerNode*>(node);
- // For internal pages, we canonicalize the target, keyword and content
- // item names so that they can be used by qdoc for other sets of
- // documentation.
- // The reason we do this here is that we don't want to ruin
- // externally composed indexes, containing non-qdoc-style target names
- // when reading in indexes.
-
- if (inner->doc().hasTargets()) {
- bool external = false;
- if (inner->type() == Node::Document) {
- const DocNode* docNode = static_cast<const DocNode*>(inner);
- if (docNode->subType() == Node::ExternalPage)
- external = true;
- }
- foreach (const Atom* target, inner->doc().targets()) {
- QString targetName = target->string();
- if (!external)
- targetName = Doc::canonicalTitle(targetName);
- writer.writeStartElement("target");
- writer.writeAttribute("name", targetName);
- writer.writeEndElement(); // target
- }
- }
- if (inner->doc().hasKeywords()) {
- foreach (const Atom* keyword, inner->doc().keywords()) {
- writer.writeStartElement("keyword");
- writer.writeAttribute("name", Doc::canonicalTitle(keyword->string()));
- writer.writeEndElement(); // keyword
- }
- }
if (inner->doc().hasTableOfContents()) {
for (int i = 0; i < inner->doc().tableOfContents().size(); ++i) {
Atom* item = inner->doc().tableOfContents()[i];
@@ -1125,70 +1239,6 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
}
}
}
- else if (node->type() == Node::Function) {
- const FunctionNode* functionNode = static_cast<const FunctionNode*>(node);
- // Write a signature attribute for convenience.
- QStringList signatureList;
- QStringList resolvedParameters;
- foreach (const Parameter& parameter, functionNode->parameters()) {
- QString leftType = parameter.leftType();
- const Node* leftNode = qdb_->findNode(parameter.leftType().split("::"),
- 0,
- SearchBaseClasses|NonFunction);
- if (!leftNode || leftNode->type() != Node::Typedef) {
- leftNode = qdb_->findNode(parameter.leftType().split("::"),
- node->parent(),
- SearchBaseClasses|NonFunction);
- }
- if (leftNode && leftNode->type() == Node::Typedef) {
- if (leftNode->type() == Node::Typedef) {
- const TypedefNode* typedefNode = static_cast<const TypedefNode*>(leftNode);
- if (typedefNode->associatedEnum()) {
- leftType = "QFlags<" + typedefNode->associatedEnum()->fullDocumentName() +
- QLatin1Char('>');
- }
- }
- else
- leftType = leftNode->fullDocumentName();
- }
- resolvedParameters.append(leftType);
- signatureList.append(leftType + QLatin1Char(' ') + parameter.name());
- }
-
- QString signature = functionNode->name() + QLatin1Char('(') + signatureList.join(", ") +
- QLatin1Char(')');
- if (functionNode->isConst())
- signature += " const";
- writer.writeAttribute("signature", signature);
-
- for (int i = 0; i < functionNode->parameters().size(); ++i) {
- Parameter parameter = functionNode->parameters()[i];
- writer.writeStartElement("parameter");
- writer.writeAttribute("left", resolvedParameters[i]);
- writer.writeAttribute("right", parameter.rightType());
- writer.writeAttribute("name", parameter.name());
- writer.writeAttribute("default", parameter.defaultValue());
- writer.writeEndElement(); // parameter
- }
- }
- else if (node->type() == Node::Enum) {
- const EnumNode* enumNode = static_cast<const EnumNode*>(node);
- if (enumNode->flagsType()) {
- writer.writeAttribute("typedef",enumNode->flagsType()->fullDocumentName());
- }
- foreach (const EnumItem& item, enumNode->items()) {
- writer.writeStartElement("value");
- writer.writeAttribute("name", item.name());
- writer.writeAttribute("value", item.value());
- writer.writeEndElement(); // value
- }
- }
- else if (node->type() == Node::Typedef) {
- const TypedefNode* typedefNode = static_cast<const TypedefNode*>(node);
- if (typedefNode->associatedEnum()) {
- writer.writeAttribute("enum",typedefNode->associatedEnum()->fullDocumentName());
- }
- }
return true;
}
@@ -1239,7 +1289,7 @@ bool compareNodes(const Node* n1, const Node* n2)
return false;
}
- if (n1->type() == Node::Document && n2->type() == Node::Document) {
+ if (n1->isDocNode() && n2->isDocNode()) {
const DocNode* f1 = static_cast<const DocNode*>(n1);
const DocNode* f2 = static_cast<const DocNode*>(n2);
if (f1->fullTitle() < f2->fullTitle())
@@ -1262,9 +1312,13 @@ void QDocIndexFiles::generateIndexSections(QXmlStreamWriter& writer,
bool generateInternalNodes)
{
/*
- Note that the groups are written after all the other nodes.
+ Note that groups, modules, and QML modules are written
+ after all the other nodes.
*/
- if (!node->isGroup() && generateIndexSection(writer, node, generateInternalNodes)) {
+ if (node->isGroup() || node->isModule() || node->isQmlModule())
+ return;
+
+ if (generateIndexSection(writer, node, generateInternalNodes)) {
if (node->isInnerNode()) {
const InnerNode* inner = static_cast<const InnerNode*>(node);
@@ -1288,6 +1342,47 @@ void QDocIndexFiles::generateIndexSections(QXmlStreamWriter& writer,
generateIndexSections(writer, child, generateInternalNodes);
}
}
+
+ if (node == top) {
+ /*
+ We wait until the end of the index file to output the group, module,
+ and QML module elements. By outputting them at the end, when we read
+ the index file back in, all the group, module, and QML module member
+ elements will have already been created. It is then only necessary to
+ create the group, module, or QML module element and add each member to
+ its member list.
+ */
+ const CNMap& groups = qdb_->groups();
+ if (!groups.isEmpty()) {
+ CNMap::ConstIterator g = groups.constBegin();
+ while (g != groups.constEnd()) {
+ if (generateIndexSection(writer, g.value(), generateInternalNodes))
+ writer.writeEndElement();
+ ++g;
+ }
+ }
+
+ const CNMap& modules = qdb_->modules();
+ if (!modules.isEmpty()) {
+ CNMap::ConstIterator g = modules.constBegin();
+ while (g != modules.constEnd()) {
+ if (generateIndexSection(writer, g.value(), generateInternalNodes))
+ writer.writeEndElement();
+ ++g;
+ }
+ }
+
+ const CNMap& qmlModules = qdb_->qmlModules();
+ if (!qmlModules.isEmpty()) {
+ CNMap::ConstIterator g = qmlModules.constBegin();
+ while (g != qmlModules.constEnd()) {
+ if (generateIndexSection(writer, g.value(), generateInternalNodes))
+ writer.writeEndElement();
+ ++g;
+ }
+ }
+ }
+
writer.writeEndElement();
}
}
@@ -1320,23 +1415,8 @@ void QDocIndexFiles::generateIndex(const QString& fileName,
writer.writeAttribute("version", qdb_->version());
writer.writeAttribute("project", g->config()->getString(CONFIG_PROJECT));
- generateIndexSections(writer, qdb_->treeRoot(), generateInternalNodes);
-
- /*
- We wait until the end of the index file to output the group elements.
- By waiting until the end, when we read each group element, its members
- will have already been created. It is then only necessary to create
- the group page and add each member to its member list.
- */
- const DocNodeMap& groups = qdb_->groups();
- if (!groups.isEmpty()) {
- DocNodeMap::ConstIterator g = groups.constBegin();
- while (g != groups.constEnd()) {
- if (generateIndexSection(writer, g.value(), generateInternalNodes))
- writer.writeEndElement();
- ++g;
- }
- }
+ top = qdb_->primaryTreeRoot();
+ generateIndexSections(writer, top, generateInternalNodes);
writer.writeEndElement(); // INDEX
writer.writeEndElement(); // QDOCINDEX
diff --git a/src/tools/qdoc/qdocindexfiles.h b/src/tools/qdoc/qdocindexfiles.h
index e4a83176a2..27ee96ea8d 100644
--- a/src/tools/qdoc/qdocindexfiles.h
+++ b/src/tools/qdoc/qdocindexfiles.h
@@ -72,15 +72,10 @@ class QDocIndexFiles
bool generateInternalNodes = false);
void readIndexFile(const QString& path);
- void readIndexSection(const QDomElement& element, InnerNode* parent, const QString& indexUrl);
+ void readIndexSection(const QDomElement& element, Node* current, const QString& indexUrl);
void resolveIndex();
bool generateIndexSection(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false);
void generateIndexSections(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false);
- void writeMembersAttribute(QXmlStreamWriter& writer,
- const InnerNode* n,
- Node::Type t,
- Node::SubType st,
- const QString& attr);
private:
static QDocIndexFiles* qdocIndexFiles_;
@@ -89,7 +84,6 @@ class QDocIndexFiles
QString project_;
QList<QPair<ClassNode*,QString> > basesList_;
QList<QPair<FunctionNode*,QString> > relatedList_;
-
};
QT_END_NAMESPACE
diff --git a/src/tools/qdoc/qdoctagfiles.cpp b/src/tools/qdoc/qdoctagfiles.cpp
index a0054ea229..cc2bd3f1f0 100644
--- a/src/tools/qdoc/qdoctagfiles.cpp
+++ b/src/tools/qdoc/qdoctagfiles.cpp
@@ -147,7 +147,7 @@ void QDocTagFiles::generateTagFileCompounds(QXmlStreamWriter& writer, const Inne
QString objName = node->name();
// Special case: only the root node should have an empty name.
- if (objName.isEmpty() && node != qdb_->treeRoot())
+ if (objName.isEmpty() && node != qdb_->primaryTreeRoot())
continue;
// *** Write the starting tag for the element here. ***
@@ -162,8 +162,9 @@ void QDocTagFiles::generateTagFileCompounds(QXmlStreamWriter& writer, const Inne
const ClassNode* classNode = static_cast<const ClassNode*>(node);
QList<RelatedClass> bases = classNode->baseClasses();
foreach (const RelatedClass& related, bases) {
- ClassNode* baseClassNode = related.node;
- writer.writeTextElement("base", baseClassNode->name());
+ ClassNode* n = related.node_;
+ if (n)
+ writer.writeTextElement("base", n->name());
}
// Recurse to write all members.
@@ -243,7 +244,7 @@ void QDocTagFiles::generateTagFileMembers(QXmlStreamWriter& writer, const InnerN
QString objName = node->name();
// Special case: only the root node should have an empty name.
- if (objName.isEmpty() && node != qdb_->treeRoot())
+ if (objName.isEmpty() && node != qdb_->primaryTreeRoot())
continue;
// *** Write the starting tag for the element here. ***
@@ -294,31 +295,8 @@ void QDocTagFiles::generateTagFileMembers(QXmlStreamWriter& writer, const InnerN
QStringList pieces = gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()).split(QLatin1Char('#'));
writer.writeTextElement("anchorfile", pieces[0]);
writer.writeTextElement("anchor", pieces[1]);
-
- // Write a signature attribute for convenience.
- QStringList signatureList;
-
- foreach (const Parameter& parameter, functionNode->parameters()) {
- QString leftType = parameter.leftType();
- const Node* leftNode = qdb_->findNode(parameter.leftType().split("::"),
- 0,
- SearchBaseClasses|NonFunction);
- if (!leftNode || leftNode->type() != Node::Typedef) {
- leftNode = qdb_->findNode(parameter.leftType().split("::"),
- node->parent(),
- SearchBaseClasses|NonFunction);
- }
- if (leftNode && leftNode->type() == Node::Typedef) {
- const TypedefNode* typedefNode = static_cast<const TypedefNode*>(leftNode);
- if (typedefNode->associatedEnum()) {
- leftType = "QFlags<" + typedefNode->associatedEnum()->fullDocumentName() +
- QLatin1Char('>');
- }
- }
- signatureList.append(leftType + QLatin1Char(' ') + parameter.name());
- }
-
- QString signature = QLatin1Char('(')+signatureList.join(", ")+QLatin1Char(')');
+ QString signature = functionNode->signature();
+ signature = signature.mid(signature.indexOf(QChar('('))).trimmed();
if (functionNode->isConst())
signature += " const";
if (functionNode->virtualness() == FunctionNode::PureVirtual)
@@ -395,7 +373,7 @@ void QDocTagFiles::generateTagFile(const QString& fileName, Generator* g)
writer.setAutoFormatting(true);
writer.writeStartDocument();
writer.writeStartElement("tagfile");
- generateTagFileCompounds(writer, qdb_->treeRoot());
+ generateTagFileCompounds(writer, qdb_->primaryTreeRoot());
writer.writeEndElement(); // tagfile
writer.writeEndDocument();
file.close();
diff --git a/src/tools/qdoc/qmlcodeparser.h b/src/tools/qdoc/qmlcodeparser.h
index 71b4660fe7..7f6f8d1a81 100644
--- a/src/tools/qdoc/qmlcodeparser.h
+++ b/src/tools/qdoc/qmlcodeparser.h
@@ -58,7 +58,6 @@ QT_BEGIN_NAMESPACE
class Config;
class Node;
class QString;
-class Tree;
class QmlCodeParser : public CodeParser
{
diff --git a/src/tools/qdoc/qmlvisitor.cpp b/src/tools/qdoc/qmlvisitor.cpp
index ec1ef41256..2ef751e9bc 100644
--- a/src/tools/qdoc/qmlvisitor.cpp
+++ b/src/tools/qdoc/qmlvisitor.cpp
@@ -97,7 +97,7 @@ QmlDocVisitor::QmlDocVisitor(const QString &filePath,
this->engine = engine;
this->commands_ = commands;
this->topics_ = topics;
- current = QDocDatabase::qdocDB()->treeRoot();
+ current = QDocDatabase::qdocDB()->primaryTreeRoot();
}
/*!
@@ -365,7 +365,7 @@ void QmlDocVisitor::applyMetacommands(QQmlJS::AST::SourceLocation,
QString command = *i;
ArgList args = doc.metaCommandArgs(command);
if (command == COMMAND_QMLABSTRACT) {
- if ((node->type() == Node::Document) && (node->subType() == Node::QmlClass)) {
+ if (node->isQmlType()) {
node->setAbstract(true);
}
}
@@ -378,7 +378,7 @@ void QmlDocVisitor::applyMetacommands(QQmlJS::AST::SourceLocation,
else if (command == COMMAND_QMLINHERITS) {
if (node->name() == args[0].first)
doc.location().warning(tr("%1 tries to inherit itself").arg(args[0].first));
- else if (node->subType() == Node::QmlClass) {
+ else if (node->isQmlType()) {
QmlClassNode *qmlClass = static_cast<QmlClassNode*>(node);
qmlClass->setQmlBaseName(args[0].first);
QmlClassNode::addInheritedBy(args[0].first,node);
@@ -541,7 +541,7 @@ bool QmlDocVisitor::visit(QQmlJS::AST::UiPublicMember *member)
switch (member->type) {
case QQmlJS::AST::UiPublicMember::Signal:
{
- if (current->type() == Node::Document) {
+ if (current->isQmlType()) {
QmlClassNode *qmlClass = static_cast<QmlClassNode *>(current);
if (qmlClass) {
@@ -564,7 +564,7 @@ bool QmlDocVisitor::visit(QQmlJS::AST::UiPublicMember *member)
{
QString type = member->memberType.toString();
QString name = member->name.toString();
- if (current->type() == Node::Document) {
+ if (current->isQmlType()) {
QmlClassNode *qmlClass = static_cast<QmlClassNode *>(current);
if (qmlClass) {
QString name = member->name.toString();
@@ -608,7 +608,7 @@ bool QmlDocVisitor::visit(QQmlJS::AST::FunctionDeclaration* fd)
if (nestingLevel > 1) {
return true;
}
- if (current->type() == Node::Document) {
+ if (current->isQmlType()) {
QmlClassNode* qmlClass = static_cast<QmlClassNode*>(current);
if (qmlClass) {
QString name = fd->name.toString();
@@ -661,7 +661,7 @@ bool QmlDocVisitor::visit(QQmlJS::AST::UiScriptBinding* )
if (nestingLevel > 1) {
return true;
}
- if (current->type() == Node::Document) {
+ if (current->isQmlType()) {
QString handler = sb->qualifiedId->name.toString();
if (handler.length() > 2 && handler.startsWith("on") && handler.at(2).isUpper()) {
QmlClassNode* qmlClass = static_cast<QmlClassNode*>(current);
diff --git a/src/tools/qdoc/text.cpp b/src/tools/qdoc/text.cpp
index e2f682726d..ae716a0e50 100644
--- a/src/tools/qdoc/text.cpp
+++ b/src/tools/qdoc/text.cpp
@@ -111,6 +111,22 @@ Text& Text::operator<<(const Atom& atom)
return *this;
}
+/*!
+ Special output operator for LinkAtom. It makes a copy of
+ the LinkAtom \a atom and connects the cop;y to the list
+ in this Text.
+ */
+Text& Text::operator<<(const LinkAtom& atom)
+{
+ if (first == 0) {
+ first = new LinkAtom(atom);
+ last = first;
+ }
+ else
+ last = new LinkAtom(last, atom);
+ return *this;
+}
+
Text& Text::operator<<(const Text& text)
{
const Atom* atom = text.firstAtom();
diff --git a/src/tools/qdoc/text.h b/src/tools/qdoc/text.h
index 9274140caa..ca079e3b35 100644
--- a/src/tools/qdoc/text.h
+++ b/src/tools/qdoc/text.h
@@ -65,6 +65,7 @@ public:
Text& operator<<(Atom::Type atomType);
Text& operator<<(const QString& string);
Text& operator<<(const Atom& atom);
+ Text& operator<<(const LinkAtom& atom);
Text& operator<<(const Text& text);
void stripFirstAtom();
void stripLastAtom();
diff --git a/src/tools/qdoc/tree.cpp b/src/tools/qdoc/tree.cpp
index 113220059c..e689227bf1 100644
--- a/src/tools/qdoc/tree.cpp
+++ b/src/tools/qdoc/tree.cpp
@@ -60,132 +60,91 @@ QT_BEGIN_NAMESPACE
This class is now private. Only class QDocDatabase has access.
Please don't change this. If you must access class Tree, do it
though the pointer to the singleton QDocDatabase.
+
+ Tree is being converted to a forest. A static member provides a
+ map of Tree* values with the module names as the keys. There is
+ one Tree in the map for each index file read, and there is one
+ tree that is not in the map for the module whose documentation
+ is being generated.
*/
/*!
- Constructs the singleton tree. \a qdb is the pointer to the
+ Constructs a Tree. \a qdb is the pointer to the singleton
qdoc database that is constructing the tree. This might not
be necessary, and it might be removed later.
*/
-Tree::Tree(QDocDatabase* qdb)
- : qdb_(qdb), root_(0, QString())
+Tree::Tree(const QString& module, QDocDatabase* qdb)
+ : module_(module), qdb_(qdb), root_(0, QString())
{
+ root_.setModuleName(module_);
+ root_.setTree(this);
}
/*!
- Destroys the singleton Tree.
+ Destroys the Tree. The root node is a data member
+ of this object, so its destructor is called. The
+ destructor of each child node is called, and these
+ destructors are recursive. Thus the entire tree is
+ destroyed.
*/
Tree::~Tree()
{
+ // nothing
}
-// 1 calls 2
+/* API members */
+
/*!
- Searches the tree for a node that matches the \a path. The
- search begins at \a start but can move up the parent chain
- recursively if no match is found.
+ Find the C++ class node named \a path. Begin the search at the
+ \a start node. If the \a start node is 0, begin the search
+ at the root of the tree. Only a C++ class node named \a path is
+ acceptible. If one is not found, 0 is returned.
*/
-const Node* Tree::findNode(const QStringList& path,
- const Node* start,
- int findFlags,
- const Node* self) const
+ClassNode* Tree::findClassNode(const QStringList& path, Node* start) const
{
- const Node* current = start;
- if (!current)
- current = root();
-
- /*
- First, search for a node assuming we don't want a QML node.
- If that search fails, search again assuming we do want a
- QML node.
- */
- const Node* n = findNode(path,current,findFlags,self,false);
- if (!n) {
- n = findNode(path,current,findFlags,self,true);
- }
- return n;
+ if (!start)
+ start = const_cast<NamespaceNode*>(root());
+ return static_cast<ClassNode*>(findNodeRecursive(path, 0, start, Node::Class));
}
-// 2 is private; it is only called by 1.
/*!
- This overload function was extracted from the one above that has the
- same signature without the last bool parameter, \a qml. This version
- is called only by that other one. It is therefore private. It can
- be called a second time by that other version, if the first call
- returns null. If \a qml is false, the search will only match a node
- that is not a QML node. If \a qml is true, the search will only
- match a node that is a QML node.
-*/
-const Node* Tree::findNode(const QStringList& path,
- const Node* start,
- int findFlags,
- const Node* self,
- bool qml) const
+ Find the Namespace node named \a path. Begin the search at
+ the root of the tree. Only a Namespace node named \a path
+ is acceptible. If one is not found, 0 is returned.
+ */
+NamespaceNode* Tree::findNamespaceNode(const QStringList& path) const
{
- const Node* current = start;
- do {
- const Node* node = current;
- int i;
- int start_idx = 0;
-
- /*
- If the path contains one or two double colons ("::"),
- check first to see if the first two path strings refer
- to a QML element. If they do, path[0] will be the QML
- module identifier, and path[1] will be the QML type.
- If the anser is yes, the reference identifies a QML
- class node.
- */
- if (qml && path.size() >= 2 && !path[0].isEmpty()) {
- QmlClassNode* qcn = qdb_->findQmlType(path[0], path[1]);
- if (qcn) {
- node = qcn;
- if (path.size() == 2)
- return node;
- start_idx = 2;
- }
- }
-
- for (i = start_idx; i < path.size(); ++i) {
- if (node == 0 || !node->isInnerNode())
- break;
-
- const Node* next = static_cast<const InnerNode*>(node)->findChildNodeByName(path.at(i), qml);
- if (!next && (findFlags & SearchEnumValues) && i == path.size()-1)
- next = static_cast<const InnerNode*>(node)->findEnumNodeForValue(path.at(i));
+ Node* start = const_cast<NamespaceNode*>(root());
+ return static_cast<NamespaceNode*>(findNodeRecursive(path, 0, start, Node::Namespace));
+}
- if (!next && !qml && node->type() == Node::Class && (findFlags & SearchBaseClasses)) {
- NodeList baseClasses = allBaseClasses(static_cast<const ClassNode*>(node));
- foreach (const Node* baseClass, baseClasses) {
- next = static_cast<const InnerNode*>(baseClass)->findChildNodeByName(path.at(i));
- if (!next && (findFlags & SearchEnumValues) && i == path.size() - 1)
- next = static_cast<const InnerNode*>(baseClass)->findEnumNodeForValue(path.at(i));
- if (next)
- break;
- }
- }
- node = next;
- }
- if (node && i == path.size()
- && (!(findFlags & NonFunction) || node->type() != Node::Function
- || ((FunctionNode*)node)->metaness() == FunctionNode::MacroWithoutParams)) {
- if ((node != self) && (node->type() != Node::QmlPropertyGroup)) {
- if (node->subType() == Node::Collision) {
- node = node->applyModuleName(start);
- }
- return node;
- }
- }
- current = current->parent();
- } while (current);
+/*!
+ This function first ignores the \a clone node and searches
+ for the parent node with \a parentPath. If that search is
+ successful, it searches for a child node of the parent that
+ matches the \a clone node. If it finds a node that is just
+ like the \a clone, it returns a pointer to the found node.
- return 0;
+ There should be a way to avoid creating the clone in the
+ first place. Investigate when time allows.
+ */
+FunctionNode* Tree::findFunctionNode(const QStringList& parentPath, const FunctionNode* clone)
+{
+ const Node* parent = findNamespaceNode(parentPath);
+ if (parent == 0)
+ parent = findClassNode(parentPath, 0);
+ if (parent == 0)
+ parent = findNode(parentPath);
+ if (parent == 0 || !parent->isInnerNode())
+ return 0;
+ return ((InnerNode*)parent)->findFunctionNode(clone);
}
+
/*!
Find the Qml type node named \a path. Begin the search at the
\a start node. If the \a start node is 0, begin the search
- at the root of the tree. Only a Qml type node named \a path is
+ at the root of the tree. Only a Qml type node named <\a path is
acceptible. If one is not found, 0 is returned.
*/
QmlClassNode* Tree::findQmlTypeNode(const QStringList& path)
@@ -203,7 +162,7 @@ QmlClassNode* Tree::findQmlTypeNode(const QStringList& path)
if (qcn)
return qcn;
}
- return static_cast<QmlClassNode*>(findNodeRecursive(path, 0, root(), Node::Document, Node::QmlClass));
+ return static_cast<QmlClassNode*>(findNodeRecursive(path, 0, root(), Node::QmlType));
}
/*!
@@ -215,7 +174,7 @@ QmlClassNode* Tree::findQmlTypeNode(const QStringList& path)
node as its first child, and return a pointer to the new
NameCollisionNode. Otherwise return 0.
*/
-NameCollisionNode* Tree::checkForCollision(const QString& name) const
+NameCollisionNode* Tree::checkForCollision(const QString& name)
{
Node* n = const_cast<Node*>(findNode(QStringList(name)));
if (n) {
@@ -248,18 +207,6 @@ NameCollisionNode* Tree::findCollisionNode(const QString& name) const
}
/*!
- This function just calls the const version of the same function
- and returns the function node.
- */
-FunctionNode* Tree::findFunctionNode(const QStringList& path,
- Node* relative,
- int findFlags)
-{
- return const_cast<FunctionNode*>
- (const_cast<const Tree*>(this)->findFunctionNode(path,relative,findFlags));
-}
-
-/*!
This function begins searching the tree at \a relative for
the \l {FunctionNode} {function node} identified by \a path.
The \a findFlags are used to restrict the search. If a node
@@ -274,17 +221,23 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path,
if (!relative)
relative = root();
- /*
- If the path contains two double colons ("::"), check
- first to see if it is a reference to a QML method. If
- it is a reference to a QML method, first look up the
- QML class node in the QML module map.
- */
if (path.size() == 3 && !path[0].isEmpty()) {
- QmlClassNode* qcn = qdb_->findQmlType(path[0], path[1]);
- if (qcn) {
- return static_cast<const FunctionNode*>(qcn->findFunctionNode(path[2]));
+ QmlClassNode* qcn = lookupQmlType(QString(path[0] + "::" + path[1]));
+ if (!qcn) {
+ QStringList p(path[1]);
+ Node* n = findNodeByNameAndType(p, Node::QmlType);
+ if (n) {
+ if (n->isQmlType())
+ qcn = static_cast<QmlClassNode*>(n);
+ else if (n->subType() == Node::Collision) {
+ NameCollisionNode* ncn;
+ ncn = static_cast<NameCollisionNode*>(n);
+ qcn = static_cast<QmlClassNode*>(ncn->findAny(Node::QmlType, Node::NoSubType));
+ }
+ }
}
+ if (qcn)
+ return static_cast<const FunctionNode*>(qcn->findFunctionNode(path[2]));
}
do {
@@ -299,7 +252,7 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path,
if (i == path.size() - 1)
next = ((InnerNode*) node)->findFunctionNode(path.at(i));
else
- next = ((InnerNode*) node)->findChildNodeByName(path.at(i));
+ next = ((InnerNode*) node)->findChildNode(path.at(i));
if (!next && node->type() == Node::Class && (findFlags & SearchBaseClasses)) {
NodeList baseClasses = allBaseClasses(static_cast<const ClassNode*>(node));
@@ -307,7 +260,7 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path,
if (i == path.size() - 1)
next = static_cast<const InnerNode*>(baseClass)->findFunctionNode(path.at(i));
else
- next = static_cast<const InnerNode*>(baseClass)->findChildNodeByName(path.at(i));
+ next = static_cast<const InnerNode*>(baseClass)->findChildNode(path.at(i));
if (next)
break;
@@ -339,57 +292,34 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path,
return 0;
}
-/*!
- This function just calls the const version of itself and
- returns the result.
- */
-FunctionNode* Tree::findFunctionNode(const QStringList& parentPath,
- const FunctionNode* clone,
- Node* relative,
- int findFlags)
+static NodeTypeList t;
+static const NodeTypeList& relatesTypes()
{
- return const_cast<FunctionNode*>(
- const_cast<const Tree*>(this)->findFunctionNode(parentPath,
- clone,
- relative,
- findFlags));
+ if (t.isEmpty()) {
+ t.reserve(3);
+ t.append(NodeTypePair(Node::Class, Node::NoSubType));
+ t.append(NodeTypePair(Node::Namespace, Node::NoSubType));
+ t.append(NodeTypePair(Node::Document, Node::HeaderFile));
+ }
+ return t;
}
/*!
- This function first ignores the \a clone node and searches
- for the node having the \a parentPath by calling the main
- findFunction(\a {parentPath}, \a {relative}, \a {findFlags}).
- If that search is successful, then it searches for the \a clone
- in the found parent node.
- */
-const FunctionNode* Tree::findFunctionNode(const QStringList& parentPath,
- const FunctionNode* clone,
- const Node* relative,
- int findFlags) const
-{
- const Node* parent = findNamespaceNode(parentPath);
- if (parent == 0)
- parent = findClassNode(parentPath, 0);
- if (parent == 0)
- parent = findNode(parentPath, relative, findFlags);
- if (parent == 0 || !parent->isInnerNode())
- return 0;
- return ((InnerNode*)parent)->findFunctionNode(clone);
-}
+ This function searches for the node specified by \a path.
+ The matching node can be one of several different types
+ including a C++ class, a C++ namespace, or a C++ header
+ file.
-/*!
+ I'm not sure if it can be a QML type, but if that is a
+ possibility, the code can easily accommodate it.
+
+ If a matching node is found, a pointer to it is returned.
+ Otherwise 0 is returned.
*/
-void Tree::addBaseClass(ClassNode* subclass, Node::Access access,
- const QStringList& basePath,
- const QString& dataTypeWithTemplateArgs,
- InnerNode* parent)
+InnerNode* Tree::findRelatesNode(const QStringList& path)
{
- unresolvedInheritanceMap[subclass].append(
- InheritanceBound(access,
- basePath,
- dataTypeWithTemplateArgs,
- parent)
- );
+ Node* n = findNodeRecursive(path, 0, root(), relatesTypes());
+ return ((n && n->isInnerNode()) ? static_cast<InnerNode*>(n) : 0);
}
/*!
@@ -402,24 +332,25 @@ void Tree::addPropertyFunction(PropertyNode* property,
}
/*!
- This function resolves inheritance and reimplementation settings
- for each C++ class node found in the namspace beginning at \a rootNode.
- If it finds another namespace node in the child list of \a rootNode,
- it calls itself recursively. For each child of \a rootNode that is a
- class node, it calls the other resolveInheritance() function.
+ This function resolves C++ inheritance and reimplementation
+ settings for each C++ class node found in the tree beginning
+ at \a n. It also calls itself recursively for each C++ class
+ node or namespace node it encounters. For each child of \a n
+ that is a class node, it calls resolveInheritanceHelper().
This function does not resolve QML inheritance.
*/
-void Tree::resolveInheritance(NamespaceNode* rootNode)
+void Tree::resolveInheritance(InnerNode* n)
{
- if (!rootNode)
- rootNode = root();
+ if (!n)
+ n = root();
for (int pass = 0; pass < 2; pass++) {
- NodeList::ConstIterator c = rootNode->childNodes().constBegin();
- while (c != rootNode->childNodes().constEnd()) {
+ NodeList::ConstIterator c = n->childNodes().constBegin();
+ while (c != n->childNodes().constEnd()) {
if ((*c)->type() == Node::Class) {
- resolveInheritance(pass, (ClassNode*)* c);
+ resolveInheritanceHelper(pass, (ClassNode*)*c);
+ resolveInheritance((ClassNode*)*c);
}
else if ((*c)->type() == Node::Namespace) {
NamespaceNode* ns = static_cast<NamespaceNode*>(*c);
@@ -427,8 +358,73 @@ void Tree::resolveInheritance(NamespaceNode* rootNode)
}
++c;
}
- if (rootNode == root())
- unresolvedInheritanceMap.clear();
+ }
+}
+
+/*!
+ This function is run twice for eachclass node \a cn in the
+ tree. First it is run with \a pass set to 0 for each
+ class node \a cn. Then it is run with \a pass set to 1 for
+ eachclass node \a cn.
+
+ In \a pass 0, all the base classes ofclass node \a cn are
+ found and added to the base class list forclass node \a cn.
+
+ In \a pass 1, each child ofclass node \a cn that is a function
+ that is reimplemented from one of the base classes is marked
+ as being reimplemented from that class.
+
+ Some property node fixing up is also done in \a pass 1.
+ */
+void Tree::resolveInheritanceHelper(int pass, ClassNode* cn)
+{
+ if (pass == 0) {
+ QList<RelatedClass>& bases = cn->baseClasses();
+ QList<RelatedClass>::iterator b = bases.begin();
+ while (b != bases.end()) {
+ if (!(*b).node_) {
+ Node* n = qdb_->findClassNode((*b).path_);
+#if 0
+ /*
+ If the node for the base class was not found,
+ the reason might be that the subclass is in a
+ namespace and the base class is in the same
+ namespace, but the base class name was not
+ qualified with the namespace name. That is the
+ case most of the time. Then restart the search
+ at the parent of the subclass node (the namespace
+ node) using the unqualified base class name.
+ */
+ if (!n) {
+ InnerNode* parent = cn->parent();
+ n = findClassNode((*b).path_, parent);
+ }
+#endif
+ if (n) {
+ ClassNode* bcn = static_cast<ClassNode*>(n);
+ (*b).node_ = bcn;
+ bcn->addDerivedClass((*b).access_, cn);
+ }
+ }
+ ++b;
+ }
+ }
+ else {
+ NodeList::ConstIterator c = cn->childNodes().constBegin();
+ while (c != cn->childNodes().constEnd()) {
+ if ((*c)->type() == Node::Function) {
+ FunctionNode* func = (FunctionNode*)* c;
+ FunctionNode* from = findVirtualFunctionInBaseClasses(cn, func);
+ if (from != 0) {
+ if (func->virtualness() == FunctionNode::NonVirtual)
+ func->setVirtualness(FunctionNode::ImpureVirtual);
+ func->setReimplementedFrom(from);
+ }
+ }
+ else if ((*c)->type() == Node::Property)
+ cn->fixPropertyUsingBaseClasses(static_cast<PropertyNode*>(*c));
+ ++c;
+ }
}
}
@@ -486,57 +482,6 @@ void Tree::resolveProperties()
}
/*!
- This function is run twice for each \a classNode in the
- tree. First it is run with \a pass set to 0 for each
- \a classNode. Then it is run with \a pass set to 1 for
- each \a classNode.
-
- In \a pass 0, all the base classes of \a classNode are
- found and added to the base class list for \a classNode.
-
- In \a pass 1, each child of \a classNode that is a function
- that is reimplemented from one of the base classes is marked
- as being reimplemented from that class.
-
- Some property node fixing up is also done in \a pass 1.
- */
-void Tree::resolveInheritance(int pass, ClassNode* classNode)
-{
- if (pass == 0) {
- QList<InheritanceBound> bounds = unresolvedInheritanceMap[classNode];
- QList<InheritanceBound>::ConstIterator b = bounds.constBegin();
- while (b != bounds.constEnd()) {
- Node* n = findClassNode((*b).basePath);
- if (!n && (*b).parent) {
- n = findClassNode((*b).basePath, (*b).parent);
- }
- if (n) {
- classNode->addBaseClass((*b).access, static_cast<ClassNode*>(n), (*b).dataTypeWithTemplateArgs);
- }
- ++b;
- }
- }
- else {
- NodeList::ConstIterator c = classNode->childNodes().constBegin();
- while (c != classNode->childNodes().constEnd()) {
- if ((*c)->type() == Node::Function) {
- FunctionNode* func = (FunctionNode*)* c;
- FunctionNode* from = findVirtualFunctionInBaseClasses(classNode, func);
- if (from != 0) {
- if (func->virtualness() == FunctionNode::NonVirtual)
- func->setVirtualness(FunctionNode::ImpureVirtual);
- func->setReimplementedFrom(from);
- }
- }
- else if ((*c)->type() == Node::Property) {
- fixPropertyUsingBaseClasses(classNode, static_cast<PropertyNode*>(*c));
- }
- ++c;
- }
- }
-}
-
-/*!
For each QML class node that points to a C++ class node,
follow its C++ class node pointer and set the C++ class
node's QML class node pointer back to the QML class node.
@@ -545,7 +490,7 @@ void Tree::resolveCppToQmlLinks()
{
foreach (Node* child, root_.childNodes()) {
- if (child->type() == Node::Document && child->subType() == Node::QmlClass) {
+ if (child->isQmlType()) {
QmlClassNode* qcn = static_cast<QmlClassNode*>(child);
ClassNode* cn = const_cast<ClassNode*>(qcn->classNode());
if (cn)
@@ -575,16 +520,18 @@ void Tree::fixInheritance(NamespaceNode* rootNode)
/*!
*/
-FunctionNode* Tree::findVirtualFunctionInBaseClasses(ClassNode* classNode,
- FunctionNode* clone)
+FunctionNode* Tree::findVirtualFunctionInBaseClasses(ClassNode* cn, FunctionNode* clone)
{
- QList<RelatedClass>::ConstIterator r = classNode->baseClasses().constBegin();
- while (r != classNode->baseClasses().constEnd()) {
+ const QList<RelatedClass>& rc = cn->baseClasses();
+ QList<RelatedClass>::ConstIterator r = rc.constBegin();
+ while (r != rc.constEnd()) {
FunctionNode* func;
- if (((func = findVirtualFunctionInBaseClasses((*r).node, clone)) != 0 ||
- (func = (*r).node->findFunctionNode(clone)) != 0)) {
- if (func->virtualness() != FunctionNode::NonVirtual)
- return func;
+ if ((*r).node_) {
+ if (((func = findVirtualFunctionInBaseClasses((*r).node_, clone)) != 0 ||
+ (func = (*r).node_->findFunctionNode(clone)) != 0)) {
+ if (func->virtualness() != FunctionNode::NonVirtual)
+ return func;
+ }
}
++r;
}
@@ -593,31 +540,14 @@ FunctionNode* Tree::findVirtualFunctionInBaseClasses(ClassNode* classNode,
/*!
*/
-void Tree::fixPropertyUsingBaseClasses(ClassNode* classNode, PropertyNode* property)
-{
- QList<RelatedClass>::const_iterator r = classNode->baseClasses().constBegin();
- while (r != classNode->baseClasses().constEnd()) {
- Node* n = r->node->findChildNodeByNameAndType(property->name(), Node::Property);
- if (n) {
- PropertyNode* baseProperty = static_cast<PropertyNode*>(n);
- fixPropertyUsingBaseClasses(r->node, baseProperty);
- property->setOverriddenFrom(baseProperty);
- }
- else {
- fixPropertyUsingBaseClasses(r->node, property);
- }
- ++r;
- }
-}
-
-/*!
- */
NodeList Tree::allBaseClasses(const ClassNode* classNode) const
{
NodeList result;
foreach (const RelatedClass& r, classNode->baseClasses()) {
- result += r.node;
- result += allBaseClasses(r.node);
+ if (r.node_) {
+ result += r.node_;
+ result += allBaseClasses(r.node_);
+ }
}
return result;
}
@@ -629,16 +559,9 @@ NodeList Tree::allBaseClasses(const ClassNode* classNode) const
search at the tree root. \a subtype is not used unless
\a type is \c{Document}.
*/
-Node* Tree::findNodeByNameAndType(const QStringList& path,
- Node::Type type,
- Node::SubType subtype,
- Node* start,
- bool acceptCollision)
+Node* Tree::findNodeByNameAndType(const QStringList& path, Node::Type type) const
{
- if (!start)
- start = const_cast<NamespaceNode*>(root());
- Node* result = findNodeRecursive(path, 0, start, type, subtype, acceptCollision);
- return result;
+ return findNodeRecursive(path, 0, root(), type);
}
/*!
@@ -659,22 +582,19 @@ Node* Tree::findNodeByNameAndType(const QStringList& path,
*/
Node* Tree::findNodeRecursive(const QStringList& path,
int pathIndex,
- Node* start,
- Node::Type type,
- Node::SubType subtype,
- bool acceptCollision) const
+ const Node* start,
+ Node::Type type) const
{
if (!start || path.isEmpty())
return 0; // no place to start, or nothing to search for.
+ Node* node = const_cast<Node*>(start);
if (start->isLeaf()) {
if (pathIndex >= path.size())
- return start; // found a match.
+ return node; // found a match.
return 0; // premature leaf
}
- if (pathIndex >= path.size())
- return 0; // end of search path.
- InnerNode* current = static_cast<InnerNode*>(start);
+ InnerNode* current = static_cast<InnerNode*>(node);
const NodeList& children = current->childNodes();
const QString& name = path.at(pathIndex);
for (int i=0; i<children.size(); ++i) {
@@ -683,79 +603,654 @@ Node* Tree::findNodeRecursive(const QStringList& path,
continue;
if (n->isQmlPropertyGroup()) {
if (type == Node::QmlProperty) {
- n = findNodeRecursive(path, pathIndex, n, type, subtype);
+ n = findNodeRecursive(path, pathIndex, n, type);
if (n)
return n;
}
}
else if (n->name() == name) {
if (pathIndex+1 >= path.size()) {
- if (n->type() == type) {
- if (type == Node::Document) {
- if (n->subType() == subtype)
- return n;
- else if (n->subType() == Node::Collision && acceptCollision)
- return n;
- else if (subtype == Node::NoSubType)
- return n; // don't care what subtype is.
- return 0;
+ if ((n->type() == type) || (type == Node::NoType))
+ return n;
+ continue;
+ }
+ else { // Search the children of n for the next name in the path.
+ n = findNodeRecursive(path, pathIndex+1, n, type);
+ if (n)
+ return n;
+ }
+ }
+ }
+ return 0;
+}
+
+/*!
+ Recursive search for a node identified by \a path. Each
+ path element is a name. \a pathIndex specifies the index
+ of the name in \a path to try to match. \a start is the
+ node whose children shoulod be searched for one that has
+ that name. Each time a name match is found, increment the
+ \a pathIndex and call this function recursively.
+
+ If the end of the path is reached (i.e. if a matching
+ node is found for each name in the \a path), test the
+ matching node's type and subtype values against the ones
+ listed in \a types. If a match is found there, return the
+ pointer to the final node. Otherwise return 0.
+ */
+Node* Tree::findNodeRecursive(const QStringList& path,
+ int pathIndex,
+ Node* start,
+ const NodeTypeList& types) const
+{
+ if (!start || path.isEmpty())
+ return 0;
+ if (start->isLeaf())
+ return ((pathIndex >= path.size()) ? start : 0);
+ if (pathIndex >= path.size())
+ return 0;
+
+ InnerNode* current = static_cast<InnerNode*>(start);
+ const NodeList& children = current->childNodes();
+ for (int i=0; i<children.size(); ++i) {
+ Node* n = children.at(i);
+ if (n && n->name() == path.at(pathIndex)) {
+ if (pathIndex+1 >= path.size()) {
+ if (n->match(types))
+ return n;
+ }
+ else if (!n->isLeaf()) {
+ n = findNodeRecursive(path, pathIndex+1, n, types);
+ if (n)
+ return n;
+ }
+ }
+ }
+ return 0;
+}
+
+/*!
+ Searches the tree for a node that matches the \a path. The
+ search begins at \a start but can move up the parent chain
+ recursively if no match is found.
+
+ This findNode() callse the other findNode(), which is not
+ called anywhere else.
+ */
+const Node* Tree::findNode(const QStringList& path, const Node* start, int findFlags) const
+{
+ const Node* current = start;
+ if (!current)
+ current = root();
+
+ /*
+ First, search for a node assuming we don't want a QML node.
+ If that search fails, search again assuming we do want a
+ QML node.
+ */
+ const Node* n = findNode(path, current, findFlags, false);
+ if (n)
+ return n;
+ return findNode(path, current, findFlags, true);
+}
+
+/*!
+ This overload function was extracted from the one above that has the
+ same signature without the last bool parameter, \a qml. This version
+ is called only by that other one. It is therefore private. It can
+ be called a second time by that other version, if the first call
+ returns null. If \a qml is false, the search will only match a node
+ that is not a QML node. If \a qml is true, the search will only
+ match a node that is a QML node.
+
+ This findNode() is only called by the other findNode().
+*/
+const Node* Tree::findNode(const QStringList& path, const Node* start, int findFlags, bool qml) const
+{
+ const Node* current = start;
+ do {
+ const Node* node = current;
+ int i;
+ int start_idx = 0;
+
+ /*
+ If the path contains one or two double colons ("::"),
+ check first to see if the first two path strings refer
+ to a QML element. If they do, path[0] will be the QML
+ module identifier, and path[1] will be the QML type.
+ If the anser is yes, the reference identifies a QML
+ class node.
+ */
+ if (qml && path.size() >= 2 && !path[0].isEmpty()) {
+ QmlClassNode* qcn = lookupQmlType(QString(path[0] + "::" + path[1]));
+ if (qcn) {
+ node = qcn;
+ if (path.size() == 2)
+ return node;
+ start_idx = 2;
+ }
+ }
+
+ for (i = start_idx; i < path.size(); ++i) {
+ if (node == 0 || !node->isInnerNode())
+ break;
+
+ const Node* next = static_cast<const InnerNode*>(node)->findChildNode(path.at(i), qml);
+ if (!next && (findFlags & SearchEnumValues) && i == path.size()-1) {
+ next = static_cast<const InnerNode*>(node)->findEnumNodeForValue(path.at(i));
+ }
+ if (!next && !qml && node->type() == Node::Class && (findFlags & SearchBaseClasses)) {
+ NodeList baseClasses = allBaseClasses(static_cast<const ClassNode*>(node));
+ foreach (const Node* baseClass, baseClasses) {
+ next = static_cast<const InnerNode*>(baseClass)->findChildNode(path.at(i));
+ if (!next && (findFlags & SearchEnumValues) && i == path.size() - 1)
+ next = static_cast<const InnerNode*>(baseClass)->findEnumNodeForValue(path.at(i));
+ if (next) {
+ break;
+ }
+ }
+ }
+ node = next;
+ }
+ if (node && i == path.size()
+ && (!(findFlags & NonFunction) || node->type() != Node::Function
+ || ((FunctionNode*)node)->metaness() == FunctionNode::MacroWithoutParams)) {
+ if (node->isCollisionNode())
+ node = node->applyModuleName(start);
+ return node;
+ }
+ current = current->parent();
+ } while (current);
+
+ return 0;
+}
+
+/*!
+ This function searches for a node with a canonical title
+ constructed from \a target. If the node it finds is \a node,
+ it returns the ref from that node. Otherwise it returns an
+ empty string.
+ */
+QString Tree::findTarget(const QString& target, const Node* node) const
+{
+ QString key = Doc::canonicalTitle(target);
+ TargetMap::const_iterator i = nodesByTarget_.constFind(key);
+ if (i != nodesByTarget_.constEnd()) {
+ do {
+ if (i.value().node_ == node)
+ return i.value().ref_;
+ ++i;
+ } while (i != nodesByTarget_.constEnd() && i.key() == key);
+ }
+ return QString();
+}
+
+/*!
+ Inserts a new target into the target table. \a name is the
+ key. The target record contains the \a type, a pointer to
+ the \a node, the \a priority. and a canonicalized form of
+ the \a name, which is later used.
+ */
+void Tree::insertTarget(const QString& name, TargetRec::Type type, Node* node, int priority)
+{
+ TargetRec target;
+ target.type_ = type;
+ target.node_ = node;
+ target.priority_ = priority;
+ target.ref_ = Doc::canonicalTitle(name);
+ nodesByTarget_.insert(name, target);
+}
+
+/*!
+ Searches this tree for a node named \a target and returns
+ a pointer to it if found. The \a start node is the starting
+ point, but it only makes sense if \a start is in this tree.
+ If \a start is not in this tree, \a start is set to 0 before
+ beginning the search to ensure that the search starts at the
+ root.
+ */
+const Node* Tree::resolveTarget(const QString& target, const Node* start)
+{
+ QStringList path = target.split("::");
+ int flags = SearchBaseClasses | SearchEnumValues | NonFunction;
+ if (start && start->tree() != this)
+ start = 0;
+ return findNode(path, start, flags);
+}
+
+/*!
+ */
+void Tree::resolveTargets(InnerNode* root)
+{
+ // need recursion
+ foreach (Node* child, root->childNodes()) {
+ if (child->type() == Node::Document) {
+ DocNode* node = static_cast<DocNode*>(child);
+ if (!node->title().isEmpty()) {
+ QString key = Doc::canonicalTitle(node->title());
+ QList<DocNode*> nodes = docNodesByTitle_.values(key);
+ bool alreadyThere = false;
+ if (!nodes.empty()) {
+ for (int i=0; i< nodes.size(); ++i) {
+ if (nodes[i]->subType() == Node::ExternalPage) {
+ if (node->name() == nodes[i]->name()) {
+ alreadyThere = true;
+ break;
+ }
+ }
}
- else
- return n;
}
- else if (n->isCollisionNode()) {
- if (acceptCollision)
- return n;
- return findNodeRecursive(path, pathIndex, n, type, subtype);
+ if (!alreadyThere) {
+ docNodesByTitle_.insert(key, node);
}
- else
- return 0;
}
- else { // Not at the end of the path.
- n = findNodeRecursive(path, pathIndex+1, n, type, subtype);
- if (n)
- return n;
+ if (node->subType() == Node::Collision) {
+ resolveTargets(node);
+ }
+ }
+
+ if (child->doc().hasTableOfContents()) {
+ const QList<Atom*>& toc = child->doc().tableOfContents();
+ TargetRec target;
+ target.node_ = child;
+ target.priority_ = 3;
+
+ for (int i = 0; i < toc.size(); ++i) {
+ target.ref_ = refForAtom(toc.at(i));
+ QString title = Text::sectionHeading(toc.at(i)).toString();
+ if (!title.isEmpty()) {
+ QString key = Doc::canonicalTitle(title);
+ nodesByTarget_.insert(key, target);
+ }
+ }
+ }
+ if (child->doc().hasKeywords()) {
+ const QList<Atom*>& keywords = child->doc().keywords();
+ TargetRec target;
+ target.node_ = child;
+ target.priority_ = 1;
+
+ for (int i = 0; i < keywords.size(); ++i) {
+ target.ref_ = refForAtom(keywords.at(i));
+ QString key = Doc::canonicalTitle(keywords.at(i)->string());
+ nodesByTarget_.insert(key, target);
+ }
+ }
+ if (child->doc().hasTargets()) {
+ const QList<Atom*>& toc = child->doc().targets();
+ TargetRec target;
+ target.node_ = child;
+ target.priority_ = 2;
+
+ for (int i = 0; i < toc.size(); ++i) {
+ target.ref_ = refForAtom(toc.at(i));
+ QString key = Doc::canonicalTitle(toc.at(i)->string());
+ nodesByTarget_.insert(key, target);
+ }
+ }
+ }
+}
+
+/*!
+ This function searches for a \a target anchor node. If it
+ finds one, it sets \a ref and returns the found node.
+ */
+const Node*
+Tree::findUnambiguousTarget(const QString& target, QString& ref)
+{
+ TargetRec bestTarget;
+ int numBestTargets = 0;
+ QList<TargetRec> bestTargetList;
+
+ QString key = Doc::canonicalTitle(target);
+ TargetMap::iterator i = nodesByTarget_.find(key);
+ while (i != nodesByTarget_.end()) {
+ if (i.key() != key)
+ break;
+ const TargetRec& candidate = i.value();
+ if (candidate.priority_ < bestTarget.priority_) {
+ bestTarget = candidate;
+ bestTargetList.clear();
+ bestTargetList.append(candidate);
+ numBestTargets = 1;
+ } else if (candidate.priority_ == bestTarget.priority_) {
+ bestTargetList.append(candidate);
+ ++numBestTargets;
+ }
+ ++i;
+ }
+ if (numBestTargets > 0) {
+ if (numBestTargets == 1) {
+ ref = bestTarget.ref_;
+ return bestTarget.node_;
+ }
+ else if (bestTargetList.size() > 1) {
+#if 0
+ qDebug() << "TARGET:" << target << numBestTargets;
+ for (int i=0; i<bestTargetList.size(); ++i) {
+ const Node* n = bestTargetList.at(i).node_;
+ qDebug() << " " << n->name() << n->title();
}
+#endif
+ ref = bestTargetList.at(0).ref_;
+ return bestTargetList.at(0).node_;
}
}
+ ref.clear();
return 0;
}
/*!
- Find the Enum type node named \a path. Begin the search at the
- \a start node. If the \a start node is 0, begin the search
- at the root of the tree. Only an Enum type node named \a path is
- acceptible. If one is not found, 0 is returned.
+ This function searches for a node with the specified \a title.
*/
-EnumNode* Tree::findEnumNode(const QStringList& path, Node* start)
+const DocNode* Tree::findDocNodeByTitle(const QString& title) const
{
- if (!start)
- start = const_cast<NamespaceNode*>(root());
- return static_cast<EnumNode*>(findNodeRecursive(path, 0, start, Node::Enum, Node::NoSubType));
+ QString key = Doc::canonicalTitle(title);
+ DocNodeMultiMap::const_iterator i = docNodesByTitle_.constFind(key);
+ if (i != docNodesByTitle_.constEnd()) {
+ /*
+ Reporting all these duplicate section titles is probably
+ overkill. We should report the duplicate file and let
+ that suffice.
+ */
+ DocNodeMultiMap::const_iterator j = i;
+ ++j;
+ if (j != docNodesByTitle_.constEnd() && j.key() == i.key()) {
+ QList<Location> internalLocations;
+ while (j != docNodesByTitle_.constEnd()) {
+ if (j.key() == i.key() && j.value()->url().isEmpty()) {
+ internalLocations.append(j.value()->location());
+ break; // Just report one duplicate for now.
+ }
+ ++j;
+ }
+ if (internalLocations.size() > 0) {
+ i.value()->location().warning("This page title exists in more than one file: " + title);
+ foreach (const Location &location, internalLocations)
+ location.warning("[It also exists here]");
+ }
+ }
+ return i.value();
+ }
+ return 0;
}
/*!
- Find the C++ class node named \a path. Begin the search at the
- \a start node. If the \a start node is 0, begin the search
- at the root of the tree. Only a C++ class node named \a path is
- acceptible. If one is not found, 0 is returned.
+ Returns a canonical title for the \a atom, if the \a atom
+ is a SectionLeft or a Target.
*/
-ClassNode* Tree::findClassNode(const QStringList& path, Node* start) const
+QString Tree::refForAtom(const Atom* atom)
{
- if (!start)
- start = const_cast<NamespaceNode*>(root());
- return static_cast<ClassNode*>(findNodeRecursive(path, 0, start, Node::Class, Node::NoSubType));
+ if (atom) {
+ if (atom->type() == Atom::SectionLeft)
+ return Doc::canonicalTitle(Text::sectionHeading(atom).toString());
+ if (atom->type() == Atom::Target)
+ return Doc::canonicalTitle(atom->string());
+ }
+ return QString();
}
/*!
- Find the Namespace node named \a path. Begin the search at
- the root of the tree. Only a Namespace node named \a path
- is acceptible. If one is not found, 0 is returned.
+ \fn const CNMap& Tree::groups() const
+ Returns a const reference to the collection of all
+ group nodes.
+*/
+
+/*!
+ \fn const ModuleMap& Tree::modules() const
+ Returns a const reference to the collection of all
+ module nodes.
+*/
+
+/*!
+ \fn const QmlModuleMap& Tree::qmlModules() const
+ Returns a const reference to the collection of all
+ QML module nodes.
+*/
+
+/*!
+ Returns the collection node in this tree that has the same
+ name and type as \a cn. Returns 0 if no match is found.
+
+ If the matching node is \a cn, return 0.
*/
-NamespaceNode* Tree::findNamespaceNode(const QStringList& path) const
+CollectionNode* Tree::getCorrespondingCollection(CollectionNode* cn)
{
- Node* start = const_cast<NamespaceNode*>(root());
- return static_cast<NamespaceNode*>(findNodeRecursive(path, 0, start, Node::Namespace, Node::NoSubType));
+ CollectionNode* ccn = 0;
+ if (cn->isGroup())
+ ccn = getGroup(cn->name());
+ else if (cn->isModule())
+ ccn = getModule(cn->name());
+ else if (cn->isQmlModule())
+ ccn = getQmlModule(cn->name());
+ if (ccn == cn)
+ ccn = 0;
+ return ccn;
+}
+
+/*!
+ Find the group node named \a name and return a pointer
+ to it. If a matching node is not found, return 0.
+ */
+GroupNode* Tree::getGroup(const QString& name)
+{
+ CNMap::const_iterator i = groups_.find(name);
+ if (i != groups_.end())
+ return static_cast<GroupNode*>(i.value());
+ return 0;
+}
+
+/*!
+ Find the module node named \a name and return a pointer
+ to it. If a matching node is not found, return 0.
+ */
+ModuleNode* Tree::getModule(const QString& name)
+{
+ CNMap::const_iterator i = modules_.find(name);
+ if (i != modules_.end())
+ return static_cast<ModuleNode*>(i.value());
+ return 0;
+}
+
+/*!
+ Find the QML module node named \a name and return a pointer
+ to it. If a matching node is not found, return 0.
+ */
+QmlModuleNode* Tree::getQmlModule(const QString& name)
+{
+ CNMap::const_iterator i = qmlModules_.find(name);
+ if (i != qmlModules_.end())
+ return static_cast<QmlModuleNode*>(i.value());
+ return 0;
+}
+
+/*!
+ Find the group node named \a name and return a pointer
+ to it. If the group node is not found, add a new group
+ node named \a name and return a pointer to the new one.
+
+ If a new group node is added, its parent is the tree root,
+ and the new group node is marked \e{not seen}.
+ */
+GroupNode* Tree::findGroup(const QString& name)
+{
+ CNMap::const_iterator i = groups_.find(name);
+ if (i != groups_.end())
+ return static_cast<GroupNode*>(i.value());;
+ GroupNode* gn = new GroupNode(root(), name);
+ gn->markNotSeen();
+ groups_.insert(name, gn);
+ return gn;
+}
+
+/*!
+ Find the module node named \a name and return a pointer
+ to it. If a matching node is not found, add a new module
+ node named \a name and return a pointer to that one.
+
+ If a new module node is added, its parent is the tree root,
+ and the new module node is marked \e{not seen}.
+ */
+ModuleNode* Tree::findModule(const QString& name)
+{
+ CNMap::const_iterator i = modules_.find(name);
+ if (i != modules_.end())
+ return static_cast<ModuleNode*>(i.value());
+ ModuleNode* mn = new ModuleNode(root(), name);
+ mn->markNotSeen();
+ modules_.insert(name, mn);
+ return mn;
+}
+
+/*!
+ Find the QML module node named \a name and return a pointer
+ to it. If a matching node is not found, add a new QML module
+ node named \a name and return a pointer to that one.
+
+ If a new QML module node is added, its parent is the tree root,
+ and the new QML module node is marked \e{not seen}.
+ */
+QmlModuleNode* Tree::findQmlModule(const QString& name)
+{
+ CNMap::const_iterator i = qmlModules_.find(name);
+ if (i != qmlModules_.end())
+ return static_cast<QmlModuleNode*>(i.value());
+ QmlModuleNode* qmn = new QmlModuleNode(root(), name);
+ qmn->markNotSeen();
+ qmn->setQmlModuleInfo(name);
+ qmlModules_.insert(name, qmn);
+ return qmn;
+}
+
+/*!
+ Looks up the group node named \a name in the collection
+ of all group nodes. If a match is found, a pointer to the
+ node is returned. Otherwise, a new group node named \a name
+ is created and inserted into the collection, and the pointer
+ to that node is returned.
+ */
+GroupNode* Tree::addGroup(const QString& name)
+{
+ GroupNode* group = findGroup(name);
+ return group;
+}
+
+/*!
+ Looks up the module node named \a name in the collection
+ of all module nodes. If a match is found, a pointer to the
+ node is returned. Otherwise, a new module node named \a name
+ is created and inserted into the collection, and the pointer
+ to that node is returned.
+ */
+ModuleNode* Tree::addModule(const QString& name)
+{
+ ModuleNode* module = findModule(name);
+ return module;
+}
+
+/*!
+ Looks up the QML module node named \a name in the collection
+ of all QML module nodes. If a match is found, a pointer to the
+ node is returned. Otherwise, a new QML module node named \a name
+ is created and inserted into the collection, and the pointer
+ to that node is returned.
+ */
+QmlModuleNode* Tree::addQmlModule(const QString& name)
+{
+ QStringList blankSplit = name.split(QLatin1Char(' '));
+ QmlModuleNode* qmn = findQmlModule(blankSplit[0]);
+ qmn->setQmlModuleInfo(name);
+ return qmn;
+}
+
+/*!
+ Looks up the group node named \a name in the collection
+ of all group nodes. If a match is not found, a new group
+ node named \a name is created and inserted into the collection.
+ Then append \a node to the group's members list, and append the
+ group name to the list of group names in \a node. The parent of
+ \a node is not changed by this function. Returns a pointer to
+ the group node.
+ */
+GroupNode* Tree::addToGroup(const QString& name, Node* node)
+{
+ GroupNode* gn = findGroup(name);
+ if (!node->isInternal()) {
+ gn->addMember(node);
+ node->appendGroupName(name);
+ }
+ return gn;
+}
+
+/*!
+ Looks up the module node named \a name in the collection
+ of all module nodes. If a match is not found, a new module
+ node named \a name is created and inserted into the collection.
+ Then append \a node to the module's members list. The parent of
+ \a node is not changed by this function. Returns the module node.
+ */
+ModuleNode* Tree::addToModule(const QString& name, Node* node)
+{
+ ModuleNode* mn = findModule(name);
+ mn->addMember(node);
+ node->setModuleName(name);
+ return mn;
+}
+
+/*!
+ Looks up the QML module named \a name. If it isn't there,
+ create it. Then append \a node to the QML module's member
+ list. The parent of \a node is not changed by this function.
+ Returns the pointer to the QML module node.
+ */
+QmlModuleNode* Tree::addToQmlModule(const QString& name, Node* node)
+{
+ QStringList qmid;
+ QStringList dotSplit;
+ QStringList blankSplit = name.split(QLatin1Char(' '));
+ qmid.append(blankSplit[0]);
+ if (blankSplit.size() > 1) {
+ qmid.append(blankSplit[0] + blankSplit[1]);
+ dotSplit = blankSplit[1].split(QLatin1Char('.'));
+ qmid.append(blankSplit[0] + dotSplit[0]);
+ }
+
+ QmlModuleNode* qmn = findQmlModule(blankSplit[0]);
+ qmn->addMember(node);
+ node->setQmlModule(qmn);
+ if (node->isQmlType()) {
+ QmlClassNode* n = static_cast<QmlClassNode*>(node);
+ for (int i=0; i<qmid.size(); ++i) {
+ QString key = qmid[i] + "::" + node->name();
+ insertQmlType(key, n);
+ }
+ }
+ return qmn;
+}
+
+/*!
+ If the QML type map does not contain \a key, insert node
+ \a n with the specified \a key.
+ */
+void Tree::insertQmlType(const QString& key, QmlClassNode* n)
+{
+ if (!qmlTypeMap_.contains(key))
+ qmlTypeMap_.insert(key,n);
+}
+
+/*!
+ Split \a target on "::" and find the function node with that
+ path.
+ */
+const Node* Tree::resolveFunctionTarget(const QString& target, const Node* relative)
+{
+ QString t = target;
+ t.chop(2);
+ QStringList path = t.split("::");
+ const FunctionNode* fn = findFunctionNode(path, relative, SearchBaseClasses);
+ if (fn && fn->metaness() != FunctionNode::MacroWithoutParams)
+ return fn;
+ return 0;
}
QT_END_NAMESPACE
diff --git a/src/tools/qdoc/tree.h b/src/tools/qdoc/tree.h
index 26dd982abd..a953751968 100644
--- a/src/tools/qdoc/tree.h
+++ b/src/tools/qdoc/tree.h
@@ -46,6 +46,7 @@
#ifndef TREE_H
#define TREE_H
+#include <QtCore/qstack.h>
#include "node.h"
QT_BEGIN_NAMESPACE
@@ -53,81 +54,76 @@ QT_BEGIN_NAMESPACE
class QStringList;
class QDocDatabase;
+struct TargetRec
+{
+ public:
+ enum Type { Unknown, Target, Keyword, Contents, Class, Function, Page, Subtitle };
+ TargetRec() : node_(0), priority_(INT_MAX), type_(Unknown) { }
+ bool isEmpty() const { return ref_.isEmpty(); }
+ Node* node_;
+ QString ref_;
+ int priority_;
+ Type type_;
+};
+
+typedef QMultiMap<QString, TargetRec> TargetMap;
+typedef QMultiMap<QString, DocNode*> DocNodeMultiMap;
+typedef QMap<QString, QmlClassNode*> QmlTypeMap;
+typedef QMultiMap<QString, const ExampleNode*> ExampleNodeMap;
+
class Tree
{
private:
+ friend class QDocForest;
friend class QDocDatabase;
typedef QMap<PropertyNode::FunctionRole, QString> RoleMap;
typedef QMap<PropertyNode*, RoleMap> PropertyMap;
- struct InheritanceBound
- {
- Node::Access access;
- QStringList basePath;
- QString dataTypeWithTemplateArgs;
- InnerNode* parent;
-
- InheritanceBound() : access(Node::Public) { }
- InheritanceBound(Node::Access access0,
- const QStringList& basePath0,
- const QString& dataTypeWithTemplateArgs0,
- InnerNode* parent)
- : access(access0), basePath(basePath0),
- dataTypeWithTemplateArgs(dataTypeWithTemplateArgs0),
- parent(parent) { }
- };
-
- Tree(QDocDatabase* qdb);
+ Tree(const QString& module, QDocDatabase* qdb);
~Tree();
- EnumNode* findEnumNode(const QStringList& path, Node* start = 0);
ClassNode* findClassNode(const QStringList& path, Node* start = 0) const;
- QmlClassNode* findQmlTypeNode(const QStringList& path);
NamespaceNode* findNamespaceNode(const QStringList& path) const;
-
- Node* findNodeByNameAndType(const QStringList& path,
- Node::Type type,
- Node::SubType subtype,
- Node* start,
- bool acceptCollision = false);
+ FunctionNode* findFunctionNode(const QStringList& parentPath, const FunctionNode* clone);
+ const Node* resolveFunctionTarget(const QString& target, const Node* relative);
Node* findNodeRecursive(const QStringList& path,
int pathIndex,
+ const Node* start,
+ Node::Type type) const;
+ Node* findNodeRecursive(const QStringList& path,
+ int pathIndex,
Node* start,
- Node::Type type,
- Node::SubType subtype,
- bool acceptCollision = false) const;
+ const NodeTypeList& types) const;
const Node* findNode(const QStringList &path,
const Node* relative = 0,
- int findFlags = 0,
- const Node* self=0) const;
+ int findFlags = 0) const;
const Node* findNode(const QStringList& path,
const Node* start,
int findFlags,
- const Node* self,
bool qml) const;
- NameCollisionNode* checkForCollision(const QString& name) const;
+ QmlClassNode* findQmlTypeNode(const QStringList& path);
+
+ Node* findNodeByNameAndType(const QStringList& path, Node::Type type) const;
+ InnerNode* findRelatesNode(const QStringList& path);
+ NameCollisionNode* checkForCollision(const QString& name);
NameCollisionNode* findCollisionNode(const QString& name) const;
- FunctionNode *findFunctionNode(const QStringList &path,
- Node *relative = 0,
- int findFlags = 0);
- FunctionNode *findFunctionNode(const QStringList &parentPath,
- const FunctionNode *clone,
- Node *relative = 0,
- int findFlags = 0);
- void addBaseClass(ClassNode *subclass,
- Node::Access access,
- const QStringList &basePath,
- const QString &dataTypeWithTemplateArgs,
- InnerNode *parent);
+ QString findTarget(const QString& target, const Node* node) const;
+ void insertTarget(const QString& name, TargetRec::Type type, Node* node, int priority);
+ const Node* resolveTarget(const QString& target, const Node* start);
+ void resolveTargets(InnerNode* root);
+ const Node* findUnambiguousTarget(const QString& target, QString& ref);
+ const DocNode* findDocNodeByTitle(const QString& title) const;
+
void addPropertyFunction(PropertyNode *property,
const QString &funcName,
PropertyNode::FunctionRole funcRole);
- void resolveInheritance(NamespaceNode *rootNode = 0);
+ void resolveInheritance(InnerNode* n = 0);
+ void resolveInheritanceHelper(int pass, ClassNode* cn);
void resolveProperties();
void resolveCppToQmlLinks();
void fixInheritance(NamespaceNode *rootNode = 0);
@@ -136,23 +132,62 @@ class Tree
const FunctionNode *findFunctionNode(const QStringList &path,
const Node *relative = 0,
int findFlags = 0) const;
- const FunctionNode *findFunctionNode(const QStringList &parentPath,
- const FunctionNode *clone,
- const Node *relative = 0,
- int findFlags = 0) const;
const NamespaceNode *root() const { return &root_; }
- void resolveInheritance(int pass, ClassNode *classe);
FunctionNode *findVirtualFunctionInBaseClasses(ClassNode *classe,
FunctionNode *clone);
- void fixPropertyUsingBaseClasses(ClassNode *classe, PropertyNode *property);
NodeList allBaseClasses(const ClassNode *classe) const;
+ QString refForAtom(const Atom* atom);
+
+ const CNMap& groups() const { return groups_; }
+ const CNMap& modules() const { return modules_; }
+ const CNMap& qmlModules() const { return qmlModules_; }
+ const CNMap& getCollections(Node::Type t) const {
+ if (t == Node::Group)
+ return groups_;
+ if (t == Node::Module)
+ return modules_;
+ return qmlModules_;
+ }
+
+ CollectionNode* getCorrespondingCollection(CollectionNode* cn);
+
+ GroupNode* getGroup(const QString& name);
+ ModuleNode* getModule(const QString& name);
+ QmlModuleNode* getQmlModule(const QString& name);
+
+ GroupNode* findGroup(const QString& name);
+ ModuleNode* findModule(const QString& name);
+ QmlModuleNode* findQmlModule(const QString& name);
+
+ GroupNode* addGroup(const QString& name);
+ ModuleNode* addModule(const QString& name);
+ QmlModuleNode* addQmlModule(const QString& name);
+
+ GroupNode* addToGroup(const QString& name, Node* node);
+ ModuleNode* addToModule(const QString& name, Node* node);
+ QmlModuleNode* addToQmlModule(const QString& name, Node* node);
+
+ QmlClassNode* lookupQmlType(const QString& name) const { return qmlTypeMap_.value(name); }
+ void insertQmlType(const QString& key, QmlClassNode* n);
+ void addExampleNode(ExampleNode* n) { exampleNodeMap_.insert(n->title(), n); }
+ ExampleNodeMap& exampleNodeMap() { return exampleNodeMap_; }
+
+ public:
+ const QString& moduleName() const { return module_; }
private:
+ QString module_;
QDocDatabase* qdb_;
NamespaceNode root_;
- QMap<ClassNode* , QList<InheritanceBound> > unresolvedInheritanceMap;
PropertyMap unresolvedPropertyMap;
+ DocNodeMultiMap docNodesByTitle_;
+ TargetMap nodesByTarget_;
+ CNMap groups_;
+ CNMap modules_;
+ CNMap qmlModules_;
+ QmlTypeMap qmlTypeMap_;
+ ExampleNodeMap exampleNodeMap_;
};
QT_END_NAMESPACE
diff --git a/src/tools/rcc/main.cpp b/src/tools/rcc/main.cpp
index 972c59ef2e..81beff8363 100644
--- a/src/tools/rcc/main.cpp
+++ b/src/tools/rcc/main.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the tools applications of the Qt Toolkit.
@@ -52,6 +52,10 @@
#include <qcommandlineoption.h>
#include <qcommandlineparser.h>
+#ifdef Q_OS_WIN
+# include <fcntl.h>
+# include <io.h>
+#endif // Q_OS_WIN
QT_BEGIN_NAMESPACE
@@ -108,13 +112,13 @@ int createProject(const QString &outFileName)
int runRcc(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
- QCoreApplication::setApplicationVersion(QString::fromLatin1(QT_VERSION_STR));
+ QCoreApplication::setApplicationVersion(QStringLiteral(QT_VERSION_STR));
// Note that rcc isn't translated.
// If you use this code as an example for a translated app, make sure to translate the strings.
QCommandLineParser parser;
parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
- parser.setApplicationDescription(QStringLiteral("Qt Resource Compiler version %1").arg(QString::fromLatin1(QT_VERSION_STR)));
+ parser.setApplicationDescription(QLatin1String("Qt Resource Compiler version " QT_VERSION_STR));
parser.addHelpOption();
parser.addVersionOption();
@@ -123,6 +127,11 @@ int runRcc(int argc, char *argv[])
outputOption.setValueName(QStringLiteral("file"));
parser.addOption(outputOption);
+ QCommandLineOption tempOption(QStringList() << QStringLiteral("t") << QStringLiteral("temp"));
+ tempOption.setDescription(QStringLiteral("Use temporary <file> for big resources."));
+ tempOption.setValueName(QStringLiteral("file"));
+ parser.addOption(tempOption);
+
QCommandLineOption nameOption(QStringLiteral("name"), QStringLiteral("Create an external initialization function with <name>."), QStringLiteral("name"));
parser.addOption(nameOption);
@@ -141,6 +150,9 @@ int runRcc(int argc, char *argv[])
QCommandLineOption binaryOption(QStringLiteral("binary"), QStringLiteral("Output a binary file for use as a dynamic resource."));
parser.addOption(binaryOption);
+ QCommandLineOption passOption(QStringLiteral("pass"), QStringLiteral("Pass number for big resources"), QStringLiteral("number"));
+ parser.addOption(passOption);
+
QCommandLineOption namespaceOption(QStringLiteral("namespace"), QStringLiteral("Turn off namespace macros."));
parser.addOption(namespaceOption);
@@ -161,7 +173,6 @@ int runRcc(int argc, char *argv[])
QString errorMsg;
RCCResourceLibrary library;
- QString outFilename = parser.value(outputOption);
if (parser.isSet(nameOption))
library.setInitName(parser.value(nameOption));
if (parser.isSet(rootOption)) {
@@ -178,6 +189,14 @@ int runRcc(int argc, char *argv[])
library.setCompressThreshold(parser.value(thresholdOption).toInt());
if (parser.isSet(binaryOption))
library.setFormat(RCCResourceLibrary::Binary);
+ if (parser.isSet(passOption)) {
+ if (parser.value(passOption) == QStringLiteral("1"))
+ library.setFormat(RCCResourceLibrary::Pass1);
+ else if (parser.value(passOption) == QStringLiteral("2"))
+ library.setFormat(RCCResourceLibrary::Pass2);
+ else
+ errorMsg = QLatin1String("Pass number must be 1 or 2");
+ }
if (parser.isSet(namespaceOption))
library.setUseNameSpace(!library.useNameSpace());
if (parser.isSet(verboseOption))
@@ -194,6 +213,9 @@ int runRcc(int argc, char *argv[])
}
}
+ QString outFilename = parser.value(outputOption);
+ QString tempFilename = parser.value(tempOption);
+
if (projectRequested) {
return createProject(outFilename);
}
@@ -217,19 +239,34 @@ int runRcc(int argc, char *argv[])
if (!library.readFiles(list, errorDevice))
return 1;
- // open output
QFile out;
- QIODevice::OpenMode mode = QIODevice::WriteOnly;
- if (library.format() == RCCResourceLibrary::C_Code)
- mode |= QIODevice::Text;
+
+ // open output
+ QIODevice::OpenMode mode = QIODevice::NotOpen;
+ switch (library.format()) {
+ case RCCResourceLibrary::C_Code:
+ case RCCResourceLibrary::Pass1:
+ mode = QIODevice::WriteOnly | QIODevice::Text;
+ break;
+ case RCCResourceLibrary::Pass2:
+ case RCCResourceLibrary::Binary:
+ mode = QIODevice::WriteOnly;
+ break;
+ }
+
if (outFilename.isEmpty() || outFilename == QLatin1String("-")) {
+#ifdef Q_OS_WIN
+ // Make sure fwrite to stdout doesn't do LF->CRLF
+ if (library.format() == RCCResourceLibrary::Binary)
+ _setmode(_fileno(stdout), _O_BINARY);
+#endif // Q_OS_WIN
// using this overload close() only flushes.
out.open(stdout, mode);
} else {
out.setFileName(outFilename);
if (!out.open(mode)) {
- const QString msg = QString::fromUtf8("Unable to open %1 for writing: %2\n").arg(outFilename).arg(out.errorString());
+ const QString msg = QString::fromLatin1("Unable to open %1 for writing: %2\n").arg(outFilename).arg(out.errorString());
errorDevice.write(msg.toUtf8());
return 1;
}
@@ -245,7 +282,23 @@ int runRcc(int argc, char *argv[])
return 0;
}
- return library.output(out, errorDevice) ? 0 : 1;
+ QFile temp;
+ if (!tempFilename.isEmpty()) {
+ temp.setFileName(tempFilename);
+ if (!temp.open(QIODevice::ReadOnly)) {
+ const QString msg = QString::fromUtf8("Unable to open temporary file %1 for reading: %2\n")
+ .arg(outFilename).arg(out.errorString());
+ errorDevice.write(msg.toUtf8());
+ return 1;
+ }
+ }
+ bool success = library.output(out, temp, errorDevice);
+ if (!success) {
+ // erase the output file if we failed
+ out.remove();
+ return 1;
+ }
+ return 0;
}
Q_CORE_EXPORT extern QBasicAtomicInt qt_qhash_seed; // from qhash.cpp
diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp
index cd9fe2ac86..813ca518b7 100644
--- a/src/tools/rcc/rcc.cpp
+++ b/src/tools/rcc/rcc.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the tools applications of the Qt Toolkit.
@@ -77,12 +77,16 @@ void RCCResourceLibrary::write(const char *str, int len)
void RCCResourceLibrary::writeByteArray(const QByteArray &other)
{
- m_out.append(other);
+ if (m_format == Pass2) {
+ m_outDevice->write(other);
+ } else {
+ m_out.append(other);
+ }
}
static inline QString msgOpenReadFailed(const QString &fname, const QString &why)
{
- return QString::fromUtf8("Unable to open %1 for reading: %2\n").arg(fname).arg(why);
+ return QString::fromLatin1("Unable to open %1 for reading: %2\n").arg(fname).arg(why);
}
@@ -164,9 +168,10 @@ QString RCCFileInfo::resourceName() const
void RCCFileInfo::writeDataInfo(RCCResourceLibrary &lib)
{
- const bool text = (lib.m_format == RCCResourceLibrary::C_Code);
+ const bool text = lib.m_format == RCCResourceLibrary::C_Code;
+ const bool pass1 = lib.m_format == RCCResourceLibrary::Pass1;
//some info
- if (text) {
+ if (text || pass1) {
if (m_language != QLocale::C) {
lib.writeString(" // ");
lib.writeByteArray(resourceName().toLocal8Bit());
@@ -209,14 +214,17 @@ void RCCFileInfo::writeDataInfo(RCCResourceLibrary &lib)
//data offset
lib.writeNumber4(m_dataOffset);
}
- if (text)
+ if (text || pass1)
lib.writeChar('\n');
}
qint64 RCCFileInfo::writeDataBlob(RCCResourceLibrary &lib, qint64 offset,
QString *errorMessage)
{
- const bool text = (lib.m_format == RCCResourceLibrary::C_Code);
+ const bool text = lib.m_format == RCCResourceLibrary::C_Code;
+ const bool pass1 = lib.m_format == RCCResourceLibrary::Pass1;
+ const bool pass2 = lib.m_format == RCCResourceLibrary::Pass2;
+ const bool binary = lib.m_format == RCCResourceLibrary::Binary;
//capture the offset
m_dataOffset = offset;
@@ -244,7 +252,7 @@ qint64 RCCFileInfo::writeDataBlob(RCCResourceLibrary &lib, qint64 offset,
#endif // QT_NO_COMPRESS
// some info
- if (text) {
+ if (text || pass1) {
lib.writeString(" // ");
lib.writeByteArray(m_fileInfo.absoluteFilePath().toLocal8Bit());
lib.writeString("\n ");
@@ -252,8 +260,9 @@ qint64 RCCFileInfo::writeDataBlob(RCCResourceLibrary &lib, qint64 offset,
// write the length
- lib.writeNumber4(data.size());
- if (text)
+ if (text || binary || pass2)
+ lib.writeNumber4(data.size());
+ if (text || pass1)
lib.writeString("\n ");
offset += 4;
@@ -267,27 +276,27 @@ qint64 RCCFileInfo::writeDataBlob(RCCResourceLibrary &lib, qint64 offset,
j = 16;
}
}
- } else {
- for (int i = data.size(); --i >= 0; )
- lib.writeChar(*p++);
+ } else if (binary || pass2) {
+ lib.writeByteArray(data);
}
offset += data.size();
// done
- if (text)
+ if (text || pass1)
lib.writeString("\n ");
return offset;
}
qint64 RCCFileInfo::writeDataName(RCCResourceLibrary &lib, qint64 offset)
{
- const bool text = (lib.m_format == RCCResourceLibrary::C_Code);
+ const bool text = lib.m_format == RCCResourceLibrary::C_Code;
+ const bool pass1 = lib.m_format == RCCResourceLibrary::Pass1;
// capture the offset
m_nameOffset = offset;
// some info
- if (text) {
+ if (text || pass1) {
lib.writeString(" // ");
lib.writeByteArray(m_name.toLocal8Bit());
lib.writeString("\n ");
@@ -295,13 +304,13 @@ qint64 RCCFileInfo::writeDataName(RCCResourceLibrary &lib, qint64 offset)
// write the length
lib.writeNumber2(m_name.length());
- if (text)
+ if (text || pass1)
lib.writeString("\n ");
offset += 2;
// write the hash
lib.writeNumber4(qt_hash(m_name));
- if (text)
+ if (text || pass1)
lib.writeString("\n ");
offset += 4;
@@ -309,13 +318,13 @@ qint64 RCCFileInfo::writeDataName(RCCResourceLibrary &lib, qint64 offset)
const QChar *unicode = m_name.unicode();
for (int i = 0; i < m_name.length(); ++i) {
lib.writeNumber2(unicode[i].unicode());
- if (text && i % 16 == 0)
+ if ((text || pass1) && i % 16 == 0)
lib.writeString("\n ");
}
offset += m_name.length()*2;
// done
- if (text)
+ if (text || pass1)
lib.writeString("\n ");
return offset;
}
@@ -349,7 +358,8 @@ RCCResourceLibrary::RCCResourceLibrary()
m_namesOffset(0),
m_dataOffset(0),
m_useNameSpace(CONSTANT_USENAMESPACE),
- m_errorDevice(0)
+ m_errorDevice(0),
+ m_outDevice(0)
{
m_out.reserve(30 * 1000 * 1000);
}
@@ -566,7 +576,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
}
if (m_root == 0) {
- const QString msg = QString::fromUtf8("RCC: Warning: No resources in '%1'.\n").arg(fname);
+ const QString msg = QString::fromLatin1("RCC: Warning: No resources in '%1'.\n").arg(fname);
m_errorDevice->write(msg.toUtf8());
if (!ignoreErrors && m_format == Binary) {
// create dummy entry, otherwise loading with QResource will crash
@@ -582,7 +592,7 @@ bool RCCResourceLibrary::addFile(const QString &alias, const RCCFileInfo &file)
{
Q_ASSERT(m_errorDevice);
if (file.m_fileInfo.size() > 0xffffffff) {
- const QString msg = QString::fromUtf8("File too big: %1\n").arg(file.m_fileInfo.absoluteFilePath());
+ const QString msg = QString::fromLatin1("File too big: %1\n").arg(file.m_fileInfo.absoluteFilePath());
m_errorDevice->write(msg.toUtf8());
return false;
}
@@ -634,7 +644,7 @@ bool RCCResourceLibrary::readFiles(bool ignoreErrors, QIODevice &errorDevice)
m_errorDevice = &errorDevice;
//read in data
if (m_verbose) {
- const QString msg = QString::fromUtf8("Processing %1 files [%2]\n")
+ const QString msg = QString::fromLatin1("Processing %1 files [%2]\n")
.arg(m_fileNames.size()).arg(static_cast<int>(ignoreErrors));
m_errorDevice->write(msg.toUtf8());
}
@@ -659,7 +669,7 @@ bool RCCResourceLibrary::readFiles(bool ignoreErrors, QIODevice &errorDevice)
}
}
if (m_verbose) {
- const QString msg = QString::fromUtf8("Interpreting %1\n").arg(fname);
+ const QString msg = QString::fromLatin1("Interpreting %1\n").arg(fname);
m_errorDevice->write(msg.toUtf8());
}
@@ -717,9 +727,39 @@ RCCResourceLibrary::ResourceDataFileMap RCCResourceLibrary::resourceDataFileMap(
return rc;
}
-bool RCCResourceLibrary::output(QIODevice &outDevice, QIODevice &errorDevice)
+bool RCCResourceLibrary::output(QIODevice &outDevice, QIODevice &tempDevice, QIODevice &errorDevice)
{
m_errorDevice = &errorDevice;
+
+ const char pattern[] = { 'Q', 'R', 'C', '_', 'D', 'A', 'T', 'A' };
+ if (m_format == Pass2) {
+ char c;
+ for (int i = 0; i < 8; ) {
+ if (!tempDevice.getChar(&c)) {
+ m_errorDevice->write("No data signature found\n");
+ return false;
+ }
+ if (c == pattern[i]) {
+ ++i;
+ } else {
+ for (int k = 0; k < i; ++k)
+ outDevice.putChar(pattern[k]);
+ outDevice.putChar(c);
+ i = 0;
+ }
+ }
+
+ m_outDevice = &outDevice;
+ quint64 start = outDevice.pos();
+ writeDataBlobs();
+ quint64 len = outDevice.pos() - start;
+
+ tempDevice.seek(tempDevice.pos() + len - 8);
+ outDevice.write(tempDevice.readAll());
+
+ return true;
+ }
+
//write out
if (m_verbose)
m_errorDevice->write("Outputting code\n");
@@ -776,7 +816,12 @@ void RCCResourceLibrary::writeNumber2(quint16 number)
void RCCResourceLibrary::writeNumber4(quint32 number)
{
- if (m_format == RCCResourceLibrary::Binary) {
+ if (m_format == RCCResourceLibrary::Pass2) {
+ m_outDevice->putChar(char(number >> 24));
+ m_outDevice->putChar(char(number >> 16));
+ m_outDevice->putChar(char(number >> 8));
+ m_outDevice->putChar(char(number));
+ } else if (m_format == RCCResourceLibrary::Binary) {
writeChar(number >> 24);
writeChar(number >> 16);
writeChar(number >> 8);
@@ -791,7 +836,7 @@ void RCCResourceLibrary::writeNumber4(quint32 number)
bool RCCResourceLibrary::writeHeader()
{
- if (m_format == C_Code) {
+ if (m_format == C_Code || m_format == Pass1) {
writeString("/****************************************************************************\n");
writeString("** Resource object code\n");
writeString("**\n");
@@ -800,7 +845,6 @@ bool RCCResourceLibrary::writeHeader()
writeString("\n**\n");
writeString("** WARNING! All changes made in this file will be lost!\n");
writeString( "*****************************************************************************/\n\n");
- writeString("#include <QtCore/qglobal.h>\n\n");
} else if (m_format == Binary) {
writeString("qres");
writeNumber4(0);
@@ -814,15 +858,16 @@ bool RCCResourceLibrary::writeHeader()
bool RCCResourceLibrary::writeDataBlobs()
{
Q_ASSERT(m_errorDevice);
- if (m_format == C_Code)
+ if (m_format == C_Code) {
writeString("static const unsigned char qt_resource_data[] = {\n");
- else if (m_format == Binary)
+ } else if (m_format == Binary) {
m_dataOffset = m_out.size();
- QStack<RCCFileInfo*> pending;
+ }
if (!m_root)
return false;
+ QStack<RCCFileInfo*> pending;
pending.push(m_root);
qint64 offset = 0;
QString errorMessage;
@@ -844,12 +889,17 @@ bool RCCResourceLibrary::writeDataBlobs()
}
if (m_format == C_Code)
writeString("\n};\n\n");
+ else if (m_format == Pass1) {
+ writeString("\nstatic const unsigned char qt_resource_data[");
+ writeByteArray(QByteArray::number(offset));
+ writeString("] = { 'Q', 'R', 'C', '_', 'D', 'A', 'T', 'A' };\n\n");
+ }
return true;
}
bool RCCResourceLibrary::writeDataNames()
{
- if (m_format == C_Code)
+ if (m_format == C_Code || m_format == Pass1)
writeString("static const unsigned char qt_resource_name[] = {\n");
else if (m_format == Binary)
m_namesOffset = m_out.size();
@@ -877,7 +927,7 @@ bool RCCResourceLibrary::writeDataNames()
}
}
}
- if (m_format == C_Code)
+ if (m_format == C_Code || m_format == Pass1)
writeString("\n};\n\n");
return true;
}
@@ -889,7 +939,7 @@ static bool qt_rcc_compare_hash(const RCCFileInfo *left, const RCCFileInfo *righ
bool RCCResourceLibrary::writeDataStructure()
{
- if (m_format == C_Code)
+ if (m_format == C_Code || m_format == Pass1)
writeString("static const unsigned char qt_resource_struct[] = {\n");
else if (m_format == Binary)
m_treeOffset = m_out.size();
@@ -936,7 +986,7 @@ bool RCCResourceLibrary::writeDataStructure()
pending.push(child);
}
}
- if (m_format == C_Code)
+ if (m_format == C_Code || m_format == Pass1)
writeString("\n};\n\n");
return true;
@@ -945,7 +995,7 @@ bool RCCResourceLibrary::writeDataStructure()
void RCCResourceLibrary::writeMangleNamespaceFunction(const QByteArray &name)
{
if (m_useNameSpace) {
- writeString("QT_MANGLE_NAMESPACE(");
+ writeString("QT_RCC_MANGLE_NAMESPACE(");
writeByteArray(name);
writeChar(')');
} else {
@@ -956,7 +1006,7 @@ void RCCResourceLibrary::writeMangleNamespaceFunction(const QByteArray &name)
void RCCResourceLibrary::writeAddNamespaceFunction(const QByteArray &name)
{
if (m_useNameSpace) {
- writeString("QT_PREPEND_NAMESPACE(");
+ writeString("QT_RCC_PREPEND_NAMESPACE(");
writeByteArray(name);
writeChar(')');
} else {
@@ -966,31 +1016,50 @@ void RCCResourceLibrary::writeAddNamespaceFunction(const QByteArray &name)
bool RCCResourceLibrary::writeInitializer()
{
- if (m_format == C_Code) {
+ if (m_format == C_Code || m_format == Pass1) {
//write("\nQT_BEGIN_NAMESPACE\n");
- QString initName = m_initName;
- if (!initName.isEmpty()) {
- initName.prepend(QLatin1Char('_'));
- initName.replace(QRegExp(QLatin1String("[^a-zA-Z0-9_]")), QLatin1String("_"));
+ QString initNameStr = m_initName;
+ if (!initNameStr.isEmpty()) {
+ initNameStr.prepend(QLatin1Char('_'));
+ initNameStr.replace(QRegExp(QLatin1String("[^a-zA-Z0-9_]")), QLatin1String("_"));
}
+ QByteArray initName = initNameStr.toLatin1();
//init
- if (m_useNameSpace)
- writeString("QT_BEGIN_NAMESPACE\n\n");
+ if (m_useNameSpace) {
+ writeString("#ifdef QT_NAMESPACE\n"
+ "# define QT_RCC_PREPEND_NAMESPACE(name) ::QT_NAMESPACE::name\n"
+ "# define QT_RCC_MANGLE_NAMESPACE0(x) x\n"
+ "# define QT_RCC_MANGLE_NAMESPACE1(a, b) a##_##b\n"
+ "# define QT_RCC_MANGLE_NAMESPACE2(a, b) QT_RCC_MANGLE_NAMESPACE1(a,b)\n"
+ "# define QT_RCC_MANGLE_NAMESPACE(name) QT_RCC_MANGLE_NAMESPACE2( \\\n"
+ " QT_RCC_MANGLE_NAMESPACE0(name), QT_RCC_MANGLE_NAMESPACE0(QT_NAMESPACE))\n"
+ "#else\n"
+ "# define QT_RCC_PREPEND_NAMESPACE(name) name\n"
+ "# define QT_RCC_MANGLE_NAMESPACE(name) name\n"
+ "#endif\n\n");
+
+ writeString("#ifdef QT_NAMESPACE\n"
+ "namespace QT_NAMESPACE {\n"
+ "#endif\n\n");
+ }
+
if (m_root) {
- writeString("extern Q_CORE_EXPORT bool qRegisterResourceData\n "
+ writeString("bool qRegisterResourceData"
"(int, const unsigned char *, "
"const unsigned char *, const unsigned char *);\n\n");
- writeString("extern Q_CORE_EXPORT bool qUnregisterResourceData\n "
+ writeString("bool qUnregisterResourceData"
"(int, const unsigned char *, "
"const unsigned char *, const unsigned char *);\n\n");
}
+
if (m_useNameSpace)
- writeString("QT_END_NAMESPACE\n\n\n");
- QString initResources = QLatin1String("qInitResources");
+ writeString("#ifdef QT_NAMESPACE\n}\n#endif\n\n");
+
+ QByteArray initResources = "qInitResources";
initResources += initName;
writeString("int ");
- writeMangleNamespaceFunction(initResources.toLatin1());
+ writeMangleNamespaceFunction(initResources);
writeString("()\n{\n");
if (m_root) {
@@ -1001,15 +1070,12 @@ bool RCCResourceLibrary::writeInitializer()
}
writeString(" return 1;\n");
writeString("}\n\n");
- writeString("Q_CONSTRUCTOR_FUNCTION(");
- writeMangleNamespaceFunction(initResources.toLatin1());
- writeString(")\n\n");
//cleanup
- QString cleanResources = QLatin1String("qCleanupResources");
+ QByteArray cleanResources = "qCleanupResources";
cleanResources += initName;
writeString("int ");
- writeMangleNamespaceFunction(cleanResources.toLatin1());
+ writeMangleNamespaceFunction(cleanResources);
writeString("()\n{\n");
if (m_root) {
writeString(" ");
@@ -1019,9 +1085,15 @@ bool RCCResourceLibrary::writeInitializer()
}
writeString(" return 1;\n");
writeString("}\n\n");
- writeString("Q_DESTRUCTOR_FUNCTION(");
- writeMangleNamespaceFunction(cleanResources.toLatin1());
- writeString(")\n\n");
+
+ writeByteArray(
+ "namespace {\n"
+ " struct initializer {\n"
+ " initializer() { QT_RCC_MANGLE_NAMESPACE(" + initResources + ")(); }\n"
+ " ~initializer() { QT_RCC_MANGLE_NAMESPACE(" + cleanResources + ")(); }\n"
+ " } dummy;\n"
+ "}\n");
+
} else if (m_format == Binary) {
int i = 4;
char *p = m_out.data();
diff --git a/src/tools/rcc/rcc.h b/src/tools/rcc/rcc.h
index 7e16fe038d..1b15c8bb87 100644
--- a/src/tools/rcc/rcc.h
+++ b/src/tools/rcc/rcc.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the tools applications of the Qt Toolkit.
@@ -64,11 +64,11 @@ public:
RCCResourceLibrary();
~RCCResourceLibrary();
- bool output(QIODevice &out, QIODevice &errorDevice);
+ bool output(QIODevice &outDevice, QIODevice &tempDevice, QIODevice &errorDevice);
bool readFiles(bool ignoreErrors, QIODevice &errorDevice);
- enum Format { Binary, C_Code };
+ enum Format { Binary, C_Code, Pass1, Pass2 };
void setFormat(Format f) { m_format = f; }
Format format() const { return m_format; }
@@ -87,6 +87,9 @@ public:
void setInitName(const QString &name) { m_initName = name; }
QString initName() const { return m_initName; }
+ void setOutputName(const QString &name) { m_outputName = name; }
+ QString outputName() const { return m_outputName; }
+
void setCompressLevel(int c) { m_compressLevel = c; }
int compressLevel() const { return m_compressLevel; }
@@ -137,6 +140,7 @@ private:
QStringList m_fileNames;
QString m_resourceRoot;
QString m_initName;
+ QString m_outputName;
Format m_format;
bool m_verbose;
int m_compressLevel;
@@ -147,6 +151,7 @@ private:
bool m_useNameSpace;
QStringList m_failedResources;
QIODevice *m_errorDevice;
+ QIODevice *m_outDevice;
QByteArray m_out;
};
diff --git a/src/widgets/accessible/accessible.pri b/src/widgets/accessible/accessible.pri
index 9fb2f18950..bcdfbd639c 100644
--- a/src/widgets/accessible/accessible.pri
+++ b/src/widgets/accessible/accessible.pri
@@ -1,6 +1,23 @@
# Qt accessibility module
contains(QT_CONFIG, accessibility) {
- HEADERS += accessible/qaccessiblewidget.h
- SOURCES += accessible/qaccessiblewidget.cpp
+ HEADERS += \
+ accessible/qaccessiblewidget.h \
+ accessible/qaccessiblewidgetfactory_p.h \
+ accessible/complexwidgets.h \
+ accessible/itemviews.h \
+ accessible/qaccessiblemenu.h \
+ accessible/qaccessiblewidgets.h \
+ accessible/rangecontrols.h \
+ accessible/simplewidgets.h
+
+ SOURCES += \
+ accessible/qaccessiblewidget.cpp \
+ accessible/qaccessiblewidgetfactory.cpp \
+ accessible/complexwidgets.cpp \
+ accessible/itemviews.cpp \
+ accessible/qaccessiblemenu.cpp \
+ accessible/qaccessiblewidgets.cpp \
+ accessible/rangecontrols.cpp \
+ accessible/simplewidgets.cpp
}
diff --git a/src/plugins/accessible/widgets/complexwidgets.cpp b/src/widgets/accessible/complexwidgets.cpp
index 5f3b6b4bd6..f7c2ac0cf1 100644
--- a/src/plugins/accessible/widgets/complexwidgets.cpp
+++ b/src/widgets/accessible/complexwidgets.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -66,7 +66,7 @@
QT_BEGIN_NAMESPACE
-QString Q_GUI_EXPORT qt_accStripAmp(const QString &text);
+QString qt_accStripAmp(const QString &text);
#ifndef QT_NO_TABBAR
/*!
@@ -114,7 +114,17 @@ public:
int childCount() const { return 0; }
int indexOfChild(const QAccessibleInterface *) const { return -1; }
- QString text(QAccessible::Text) const { return qt_accStripAmp(m_parent->tabText(m_index)); }
+ QString text(QAccessible::Text t) const
+ {
+ if (t == QAccessible::Name)
+ return qt_accStripAmp(m_parent->tabText(m_index));
+ else if (t == QAccessible::Description)
+ return m_parent->tabToolTip(m_index);
+ else if (t == QAccessible::Help)
+ return m_parent->tabWhatsThis(m_index);
+ return QString();
+ }
+
void setText(QAccessible::Text, const QString &) {}
QAccessibleInterface *parent() const {
diff --git a/src/plugins/accessible/widgets/complexwidgets.h b/src/widgets/accessible/complexwidgets.h
index 00186282f3..d3df224d95 100644
--- a/src/plugins/accessible/widgets/complexwidgets.h
+++ b/src/widgets/accessible/complexwidgets.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
diff --git a/src/plugins/accessible/widgets/itemviews.cpp b/src/widgets/accessible/itemviews.cpp
index 7d3668ee5a..723a670739 100644
--- a/src/plugins/accessible/widgets/itemviews.cpp
+++ b/src/widgets/accessible/itemviews.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -51,8 +51,6 @@
QT_BEGIN_NAMESPACE
-QString Q_GUI_EXPORT qt_accStripAmp(const QString &text);
-
#ifndef QT_NO_ITEMVIEWS
/*
Implementation of the IAccessible2 table2 interface. Much simpler than
diff --git a/src/plugins/accessible/widgets/itemviews.h b/src/widgets/accessible/itemviews.h
index 45a07c5972..2f9ca6163b 100644
--- a/src/plugins/accessible/widgets/itemviews.h
+++ b/src/widgets/accessible/itemviews.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
diff --git a/src/plugins/accessible/widgets/qaccessiblemenu.cpp b/src/widgets/accessible/qaccessiblemenu.cpp
index 39ac335131..f47980d786 100644
--- a/src/plugins/accessible/widgets/qaccessiblemenu.cpp
+++ b/src/widgets/accessible/qaccessiblemenu.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -52,8 +52,8 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_MENU
-QString Q_GUI_EXPORT qt_accStripAmp(const QString &text);
-QString Q_GUI_EXPORT qt_accHotKey(const QString &text);
+QString qt_accStripAmp(const QString &text);
+QString qt_accHotKey(const QString &text);
QAccessibleInterface *getOrCreateMenu(QWidget *menu, QAction *action)
{
diff --git a/src/plugins/accessible/widgets/qaccessiblemenu.h b/src/widgets/accessible/qaccessiblemenu.h
index e8c9f8af3a..593821e7ff 100644
--- a/src/plugins/accessible/widgets/qaccessiblemenu.h
+++ b/src/widgets/accessible/qaccessiblemenu.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
diff --git a/src/widgets/accessible/qaccessiblewidget.cpp b/src/widgets/accessible/qaccessiblewidget.cpp
index 4e5fade3f4..73425b9acd 100644
--- a/src/widgets/accessible/qaccessiblewidget.cpp
+++ b/src/widgets/accessible/qaccessiblewidget.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -134,7 +134,7 @@ static int qt_accAmpIndex(const QString &text)
#endif
}
-QString Q_WIDGETS_EXPORT qt_accStripAmp(const QString &text)
+QString qt_accStripAmp(const QString &text)
{
QString newText(text);
int ampIndex = qt_accAmpIndex(newText);
@@ -144,7 +144,7 @@ QString Q_WIDGETS_EXPORT qt_accStripAmp(const QString &text)
return newText.replace(QLatin1String("&&"), QLatin1String("&"));
}
-QString Q_WIDGETS_EXPORT qt_accHotKey(const QString &text)
+QString qt_accHotKey(const QString &text)
{
int ampIndex = qt_accAmpIndex(text);
if (ampIndex != -1)
diff --git a/src/widgets/accessible/qaccessiblewidget.h b/src/widgets/accessible/qaccessiblewidget.h
index 819bb5b8c4..079e5dbc42 100644
--- a/src/widgets/accessible/qaccessiblewidget.h
+++ b/src/widgets/accessible/qaccessiblewidget.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
diff --git a/src/plugins/accessible/widgets/main.cpp b/src/widgets/accessible/qaccessiblewidgetfactory.cpp
index 717c15edd1..3d123cc9ab 100644
--- a/src/plugins/accessible/widgets/main.cpp
+++ b/src/widgets/accessible/qaccessiblewidgetfactory.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -46,8 +46,6 @@
#include "complexwidgets.h"
#include "itemviews.h"
-#include <qaccessibleplugin.h>
-#include <qplugin.h>
#include <qpushbutton.h>
#include <qtoolbutton.h>
#include <qtreeview.h>
@@ -58,23 +56,7 @@
QT_BEGIN_NAMESPACE
-
-class AccessibleFactory : public QAccessiblePlugin
-{
- Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QAccessibleFactoryInterface" FILE "widgets.json")
-
-public:
- AccessibleFactory();
-
- QAccessibleInterface *create(const QString &classname, QObject *object);
-};
-
-AccessibleFactory::AccessibleFactory()
-{
-}
-
-QAccessibleInterface *AccessibleFactory::create(const QString &classname, QObject *object)
+QAccessibleInterface *qAccessibleFactory(const QString &classname, QObject *object)
{
QAccessibleInterface *iface = 0;
if (!object || !object->isWidgetType())
@@ -254,9 +236,6 @@ QAccessibleInterface *AccessibleFactory::create(const QString &classname, QObjec
return iface;
}
-
QT_END_NAMESPACE
-#include "main.moc"
-
#endif // QT_NO_ACCESSIBILITY
diff --git a/src/widgets/accessible/qaccessiblewidgetfactory_p.h b/src/widgets/accessible/qaccessiblewidgetfactory_p.h
new file mode 100644
index 0000000000..bf5e2da6bc
--- /dev/null
+++ b/src/widgets/accessible/qaccessiblewidgetfactory_p.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qaccessible.h>
+
+#ifndef QACCESSIBLEWIDGETFACTORY_H
+#define QACCESSIBLEWIDGETFACTORY_H
+
+QT_BEGIN_NAMESPACE
+
+QAccessibleInterface *qAccessibleFactory(const QString &classname, QObject *object);
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp b/src/widgets/accessible/qaccessiblewidgets.cpp
index b502682938..da57d4657d 100644
--- a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp
+++ b/src/widgets/accessible/qaccessiblewidgets.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -72,8 +72,7 @@
QT_BEGIN_NAMESPACE
-QString Q_GUI_EXPORT qt_accStripAmp(const QString &text);
-QString Q_GUI_EXPORT qt_accHotKey(const QString &text);
+QString qt_accStripAmp(const QString &text);
QList<QWidget*> childWidgets(const QWidget *widget, bool includeTopLevel)
{
@@ -653,6 +652,7 @@ QAccessibleTextWidget::QAccessibleTextWidget(QWidget *o, QAccessible::Role r, co
QAccessible::State QAccessibleTextWidget::state() const
{
QAccessible::State s = QAccessibleWidget::state();
+ s.selectableText = true;
s.multiLine = true;
return s;
}
@@ -706,105 +706,102 @@ QString QAccessibleTextWidget::attributes(int offset, int *startOffset, int *end
http://linuxfoundation.org/collaborate/workgroups/accessibility/iaccessible2/textattributes
*/
- if (offset >= characterCount()) {
+ // IAccessible2 defines -1 as length and -2 as cursor position
+ if (offset == -2)
+ offset = cursorPosition();
+
+ const int charCount = characterCount();
+
+ // -1 doesn't make much sense here, but it's better to return something
+ // screen readers may ask for text attributes at the cursor pos which may be equal to length
+ if (offset == -1 || offset == charCount)
+ offset = charCount - 1;
+
+ if (offset < 0 || offset > charCount) {
*startOffset = -1;
*endOffset = -1;
return QString();
}
- QMap<QString, QString> attrs;
QTextCursor cursor = textCursor();
+ cursor.setPosition(offset);
+ QTextBlock block = cursor.block();
- //cursor.charFormat returns the format of the previous character
- cursor.setPosition(offset + 1);
- QTextCharFormat charFormat = cursor.charFormat();
+ int blockStart = block.position();
+ int blockEnd = blockStart + block.length();
- cursor.setPosition(offset);
- QTextBlockFormat blockFormat = cursor.blockFormat();
+ QTextBlock::iterator iter = block.begin();
+ while (!iter.fragment().contains(offset))
+ ++iter;
- QTextCharFormat charFormatComp;
- QTextBlockFormat blockFormatComp;
-
- *startOffset = offset;
- cursor.setPosition(*startOffset);
- while (*startOffset > 0) {
- charFormatComp = cursor.charFormat();
- cursor.setPosition(*startOffset - 1);
- blockFormatComp = cursor.blockFormat();
- if ((charFormat == charFormatComp) && (blockFormat == blockFormatComp))
- (*startOffset)--;
- else
- break;
- }
+ QTextFragment fragment = iter.fragment();
+ int pos = fragment.position();
- int limit = characterCount() + 1;
- *endOffset = offset + 1;
- cursor.setPosition(*endOffset);
- while (*endOffset < limit) {
- blockFormatComp = cursor.blockFormat();
- cursor.setPosition(*endOffset + 1);
- charFormatComp = cursor.charFormat();
- if ((charFormat == charFormatComp) && (cursor.blockFormat() == blockFormatComp))
- (*endOffset)++;
- else
- break;
- }
+ // text block and fragment may overlap, use the smallest common range
+ *startOffset = qMax(pos, blockStart);
+ Q_ASSERT(*startOffset <= offset);
+ *endOffset = qMin(pos + fragment.length(), blockEnd);
+ Q_ASSERT(*endOffset >= offset);
+
+ QTextCharFormat charFormat = fragment.charFormat();
+ QTextBlockFormat blockFormat = cursor.blockFormat();
+ QMap<QByteArray, QString> attrs;
QString family = charFormat.fontFamily();
if (!family.isEmpty()) {
- family = family.replace('\\',"\\\\");
- family = family.replace(':',"\\:");
- family = family.replace(',',"\\,");
- family = family.replace('=',"\\=");
- family = family.replace(';',"\\;");
- family = family.replace('\"',"\\\"");
- attrs["font-family"] = '"'+family+'"';
+ family = family.replace('\\',QStringLiteral("\\\\"));
+ family = family.replace(':',QStringLiteral("\\:"));
+ family = family.replace(',',QStringLiteral("\\,"));
+ family = family.replace('=',QStringLiteral("\\="));
+ family = family.replace(';',QStringLiteral("\\;"));
+ family = family.replace('\"',QStringLiteral("\\\""));
+ attrs["font-family"] = QString::fromLatin1("\"%1\"").arg(family);
}
int fontSize = int(charFormat.fontPointSize());
if (fontSize)
- attrs["font-size"] = QString::number(fontSize).append("pt");
+ attrs["font-size"] = QString::fromLatin1("%1pt").arg(fontSize);
//Different weight values are not handled
- attrs["font-weight"] = (charFormat.fontWeight() > QFont::Normal) ? "bold" : "normal";
+ attrs["font-weight"] = QString::fromLatin1(charFormat.fontWeight() > QFont::Normal ? "bold" : "normal");
QFont::Style style = charFormat.font().style();
- attrs["font-style"] = (style == QFont::StyleItalic) ? "italic" : ((style == QFont::StyleOblique) ? "oblique": "normal");
+ attrs["font-style"] = QString::fromLatin1((style == QFont::StyleItalic) ? "italic" : ((style == QFont::StyleOblique) ? "oblique": "normal"));
- attrs["text-underline-style"] = charFormat.font().underline() ? "solid" : "none";
+ attrs["text-underline-style"] = QString::fromLatin1(charFormat.font().underline() ? "solid" : "none");
QTextCharFormat::VerticalAlignment alignment = charFormat.verticalAlignment();
- attrs["text-position"] = (alignment == QTextCharFormat::AlignSubScript) ? "sub" : ((alignment == QTextCharFormat::AlignSuperScript) ? "super" : "baseline" );
+ attrs["text-position"] = QString::fromLatin1((alignment == QTextCharFormat::AlignSubScript) ? "sub" : ((alignment == QTextCharFormat::AlignSuperScript) ? "super" : "baseline" ));
QBrush background = charFormat.background();
if (background.style() == Qt::SolidPattern) {
- attrs["background-color"] = QString("rgb(%1,%2,%3)").arg(background.color().red()).arg(background.color().green()).arg(background.color().blue());
+ attrs["background-color"] = QString::fromLatin1("rgb(%1,%2,%3)").arg(background.color().red()).arg(background.color().green()).arg(background.color().blue());
}
QBrush foreground = charFormat.foreground();
if (foreground.style() == Qt::SolidPattern) {
- attrs["color"] = QString("rgb(%1,%2,%3)").arg(foreground.color().red()).arg(foreground.color().green()).arg(foreground.color().blue());
+ attrs["color"] = QString::fromLatin1("rgb(%1,%2,%3)").arg(foreground.color().red()).arg(foreground.color().green()).arg(foreground.color().blue());
}
switch (blockFormat.alignment() & (Qt::AlignLeft | Qt::AlignRight | Qt::AlignHCenter | Qt::AlignJustify)) {
case Qt::AlignLeft:
- attrs["text-align"] = "left";
+ attrs["text-align"] = QStringLiteral("left");
break;
case Qt::AlignRight:
- attrs["text-align"] = "right";
+ attrs["text-align"] = QStringLiteral("right");
break;
case Qt::AlignHCenter:
- attrs["text-align"] = "center";
+ attrs["text-align"] = QStringLiteral("center");
break;
case Qt::AlignJustify:
- attrs["text-align"] = "left";
+ attrs["text-align"] = QStringLiteral("left");
break;
}
QString result;
- foreach (const QString &attributeName, attrs.keys()) {
- result.append(attributeName).append(':').append(attrs[attributeName]).append(';');
+ foreach (const QByteArray &attributeName, attrs.keys()) {
+ result.append(QString::fromLatin1(attributeName)).append(':').append(attrs[attributeName]).append(';');
}
return result;
diff --git a/src/plugins/accessible/widgets/qaccessiblewidgets.h b/src/widgets/accessible/qaccessiblewidgets.h
index 3f50010685..27764cb0ac 100644
--- a/src/plugins/accessible/widgets/qaccessiblewidgets.h
+++ b/src/widgets/accessible/qaccessiblewidgets.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
diff --git a/src/plugins/accessible/widgets/rangecontrols.cpp b/src/widgets/accessible/rangecontrols.cpp
index f2aa5522e8..d4dc74ea69 100644
--- a/src/plugins/accessible/widgets/rangecontrols.cpp
+++ b/src/widgets/accessible/rangecontrols.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -57,13 +57,6 @@
QT_BEGIN_NAMESPACE
#ifndef QT_NO_ACCESSIBILITY
-extern QString Q_GUI_EXPORT qt_accStripAmp(const QString &text);
-#ifndef QT_NO_SCROLLBAR
-extern QStyleOptionSlider Q_GUI_EXPORT qt_qscrollbarStyleOption(QScrollBar *scrollBar);
-#endif
-#ifndef QT_NO_SLIDER
-extern QStyleOptionSlider Q_GUI_EXPORT qt_qsliderStyleOption(QSlider *slider);
-#endif
#ifndef QT_NO_SPINBOX
QAccessibleAbstractSpinBox::QAccessibleAbstractSpinBox(QWidget *w)
@@ -96,15 +89,7 @@ void *QAccessibleAbstractSpinBox::interface_cast(QAccessible::InterfaceType t)
QVariant QAccessibleAbstractSpinBox::currentValue() const
{
- QVariant result = abstractSpinBox()->property("value");
- QVariant::Type type = result.type();
-
- // IA2 only allows numeric types
- if (type == QVariant::Int || type == QVariant::UInt || type == QVariant::LongLong
- || type == QVariant::ULongLong || type == QVariant::Double)
- return result;
-
- return QVariant();
+ return abstractSpinBox()->property("value");
}
void QAccessibleAbstractSpinBox::setCurrentValue(const QVariant &value)
diff --git a/src/plugins/accessible/widgets/rangecontrols.h b/src/widgets/accessible/rangecontrols.h
index dd69788bb1..98cef46c5c 100644
--- a/src/plugins/accessible/widgets/rangecontrols.h
+++ b/src/widgets/accessible/rangecontrols.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
diff --git a/src/plugins/accessible/widgets/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp
index a5365b2598..6160b37a0f 100644
--- a/src/plugins/accessible/widgets/simplewidgets.cpp
+++ b/src/widgets/accessible/simplewidgets.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -71,8 +71,8 @@ QT_BEGIN_NAMESPACE
extern QList<QWidget*> childWidgets(const QWidget *widget, bool includeTopLevel = false);
-QString Q_GUI_EXPORT qt_accStripAmp(const QString &text);
-QString Q_GUI_EXPORT qt_accHotKey(const QString &text);
+QString qt_accStripAmp(const QString &text);
+QString qt_accHotKey(const QString &text);
/*!
\class QAccessibleButton
@@ -158,6 +158,26 @@ QAccessible::State QAccessibleButton::state() const
return state;
}
+QRect QAccessibleButton::rect() const
+{
+ QAbstractButton *ab = button();
+ if (!ab->isVisible())
+ return QRect();
+
+ if (QCheckBox *cb = qobject_cast<QCheckBox *>(ab)) {
+ QPoint wpos = cb->mapToGlobal(QPoint(0, 0));
+ QStyleOptionButton opt;
+ cb->initStyleOption(&opt);
+ return cb->style()->subElementRect(QStyle::SE_CheckBoxClickRect, &opt, cb).translated(wpos);
+ } else if (QRadioButton *rb = qobject_cast<QRadioButton *>(ab)) {
+ QPoint wpos = rb->mapToGlobal(QPoint(0, 0));
+ QStyleOptionButton opt;
+ rb->initStyleOption(&opt);
+ return rb->style()->subElementRect(QStyle::SE_RadioButtonClickRect, &opt, rb).translated(wpos);
+ }
+ return QAccessibleWidget::rect();
+}
+
QStringList QAccessibleButton::actionNames() const
{
QStringList names;
@@ -606,6 +626,8 @@ QString QAccessibleLineEdit::text(QAccessible::Text t) const
case QAccessible::Value:
if (lineEdit()->echoMode() == QLineEdit::Normal)
str = lineEdit()->text();
+ else if (lineEdit()->echoMode() != QLineEdit::NoEcho)
+ str = QString(lineEdit()->text().length(), QChar::fromLatin1('*'));
break;
default:
break;
@@ -643,10 +665,8 @@ QAccessible::State QAccessibleLineEdit::state() const
if (l->echoMode() != QLineEdit::Normal)
state.passwordEdit = true;
- state.selectable = true;
- if (l->hasSelectedText())
- state.selected = true;
+ state.selectableText = true;
return state;
}
diff --git a/src/plugins/accessible/widgets/simplewidgets.h b/src/widgets/accessible/simplewidgets.h
index be19d8324f..e4ce6150e2 100644
--- a/src/plugins/accessible/widgets/simplewidgets.h
+++ b/src/widgets/accessible/simplewidgets.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -63,6 +63,7 @@ public:
QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
QAccessible::State state() const Q_DECL_OVERRIDE;
+ QRect rect() const Q_DECL_OVERRIDE;
QStringList actionNames() const Q_DECL_OVERRIDE;
void doAction(const QString &actionName) Q_DECL_OVERRIDE;
diff --git a/src/plugins/accessible/widgets/widgets.pro b/src/widgets/accessible/widgets.pro
index c6af6d3f71..c6af6d3f71 100644
--- a/src/plugins/accessible/widgets/widgets.pro
+++ b/src/widgets/accessible/widgets.pro
diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp
index 3889a589c7..14c1ce081f 100644
--- a/src/widgets/dialogs/qcolordialog.cpp
+++ b/src/widgets/dialogs/qcolordialog.cpp
@@ -1262,9 +1262,17 @@ QColorShower::QColorShower(QColorDialog *parent)
lblHtml->setBuddy(htEd);
#endif
+#if !defined(QT_NO_REGULAREXPRESSION)
QRegularExpression regExp(QStringLiteral("#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})"));
QRegularExpressionValidator *validator = new QRegularExpressionValidator(regExp, this);
htEd->setValidator(validator);
+#elif !defined(QT_NO_REGEXP)
+ QRegExp regExp(QStringLiteral("#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})"));
+ QRegExpValidator *validator = new QRegExpValidator(regExp, this);
+ htEd->setValidator(validator);
+#else
+ htEd->setReadOnly(true);
+#endif
lblHtml->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
gl->addWidget(lblHtml, 5, 1);
@@ -1460,38 +1468,46 @@ void QColorDialogPrivate::setCurrentQColor(const QColor &color)
}
}
+// size of standard and custom color selector
+enum {
+ colorColumns = 8,
+ standardColorRows = 6,
+ customColorRows = 2
+};
+
bool QColorDialogPrivate::selectColor(const QColor &col)
{
QRgb color = col.rgb();
- int i = 0, j = 0;
// Check standard colors
if (standard) {
const QRgb *standardColors = QColorDialogOptions::standardColors();
- for (i = 0; i < 6; i++) {
- for (j = 0; j < 8; j++) {
- if (color == standardColors[i + j*6]) {
- _q_newStandard(i, j);
- standard->setCurrent(i, j);
- standard->setSelected(i, j);
- standard->setFocus();
- return true;
- }
- }
+ const QRgb *standardColorsEnd = standardColors + standardColorRows * colorColumns;
+ const QRgb *match = std::find(standardColors, standardColorsEnd, color);
+ if (match != standardColorsEnd) {
+ const int index = int(match - standardColors);
+ const int row = index / standardColorRows;
+ const int column = index % standardColorRows;
+ _q_newStandard(row, column);
+ standard->setCurrent(row, column);
+ standard->setSelected(row, column);
+ standard->setFocus();
+ return true;
}
}
// Check custom colors
if (custom) {
const QRgb *customColors = QColorDialogOptions::customColors();
- for (i = 0; i < 2; i++) {
- for (j = 0; j < 8; j++) {
- if (color == customColors[i + j*2]) {
- _q_newCustom(i, j);
- custom->setCurrent(i, j);
- custom->setSelected(i, j);
- custom->setFocus();
- return true;
- }
- }
+ const QRgb *customColorsEnd = customColors + customColorRows * colorColumns;
+ const QRgb *match = std::find(customColors, customColorsEnd, color);
+ if (match != customColorsEnd) {
+ const int index = int(match - customColors);
+ const int row = index / customColorRows;
+ const int column = index % customColorRows;
+ _q_newCustom(row, column);
+ custom->setCurrent(row, column);
+ custom->setSelected(row, column);
+ custom->setFocus();
+ return true;
}
}
return false;
@@ -1519,12 +1535,12 @@ void QColorDialogPrivate::_q_newColorTypedIn(QRgb rgb)
void QColorDialogPrivate::_q_nextCustom(int r, int c)
{
- nextCust = r + 2 * c;
+ nextCust = r + customColorRows * c;
}
void QColorDialogPrivate::_q_newCustom(int r, int c)
{
- const int i = r + 2 * c;
+ const int i = r + customColorRows * c;
setCurrentRgbColor(QColorDialogOptions::customColor(i));
if (standard)
standard->setSelected(-1,-1);
@@ -1545,12 +1561,10 @@ void QColorDialogPrivate::_q_pickScreenColor()
q->installEventFilter(colorPickingEventFilter);
// If user pushes Escape, the last color before picking will be restored.
beforeScreenColorPicking = cs->currentColor();
- /*For some reason, q->grabMouse(Qt::CrossCursor) doesn't change
- * the cursor, and therefore I have to change it manually.
- */
- q->grabMouse();
#ifndef QT_NO_CURSOR
- q->setCursor(Qt::CrossCursor);
+ q->grabMouse(Qt::CrossCursor);
+#else
+ q->grabMouse();
#endif
q->grabKeyboard();
/* With setMouseTracking(true) the desired color can be more precisedly picked up,
@@ -1575,9 +1589,6 @@ void QColorDialogPrivate::releaseColorPicking()
q->removeEventFilter(colorPickingEventFilter);
q->releaseMouse();
q->releaseKeyboard();
-#ifndef QT_NO_CURSOR
- q->setCursor(Qt::ArrowCursor);
-#endif
q->setMouseTracking(false);
lblScreenColorInfo->setText(QLatin1String("\n"));
addCusBt->setDisabled(false);
@@ -1635,7 +1646,7 @@ void QColorDialogPrivate::initWidgets()
}
if (!smallDisplay) {
- standard = new QColorWell(q, 6, 8, QColorDialogOptions::standardColors());
+ standard = new QColorWell(q, standardColorRows, colorColumns, QColorDialogOptions::standardColors());
lblBasicColors = new QLabel(q);
#ifndef QT_NO_SHORTCUT
lblBasicColors->setBuddy(standard);
@@ -1657,7 +1668,7 @@ void QColorDialogPrivate::initWidgets()
leftLay->addStretch();
#endif
- custom = new QColorWell(q, 2, 8, QColorDialogOptions::customColors());
+ custom = new QColorWell(q, customColorRows, colorColumns, QColorDialogOptions::customColors());
custom->setAcceptDrops(true);
q->connect(custom, SIGNAL(selected(int,int)), SLOT(_q_newCustom(int,int)));
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
index 6349bdc301..605d430edf 100644
--- a/src/widgets/dialogs/qfiledialog.cpp
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -39,6 +39,8 @@
**
****************************************************************************/
+#define QT_NO_URL_CAST_FROM_STRING
+
#include <qvariant.h>
#include <private/qwidgetitemdata_p.h>
#include "qfiledialog.h"
@@ -579,8 +581,8 @@ QFileDialogPrivate::~QFileDialogPrivate()
void QFileDialogPrivate::initHelper(QPlatformDialogHelper *h)
{
QFileDialog *d = q_func();
- QObject::connect(h, SIGNAL(fileSelected(QUrl)), d, SLOT(_q_nativeFileSelected(QUrl)));
- QObject::connect(h, SIGNAL(filesSelected(QList<QUrl>)), d, SLOT(_q_nativeFilesSelected(QList<QUrl>)));
+ QObject::connect(h, SIGNAL(fileSelected(QUrl)), d, SLOT(_q_emitUrlSelected(QUrl)));
+ QObject::connect(h, SIGNAL(filesSelected(QList<QUrl>)), d, SLOT(_q_emitUrlsSelected(QList<QUrl>)));
QObject::connect(h, SIGNAL(currentChanged(QUrl)), d, SLOT(_q_nativeCurrentChanged(QUrl)));
QObject::connect(h, SIGNAL(directoryEntered(QUrl)), d, SLOT(_q_nativeEnterDirectory(QUrl)));
QObject::connect(h, SIGNAL(filterSelected(QString)), d, SIGNAL(filterSelected(QString)));
@@ -2028,26 +2030,6 @@ QString QFileDialog::labelText(DialogLabel label) const
return QString();
}
-/*
- For the native file dialogs
-*/
-
-#if defined(Q_WS_WIN)
-extern QString qt_win_get_open_file_name(const QFileDialogArgs &args,
- QString *initialDirectory,
- QString *selectedFilter);
-
-extern QString qt_win_get_save_file_name(const QFileDialogArgs &args,
- QString *initialDirectory,
- QString *selectedFilter);
-
-extern QStringList qt_win_get_open_file_names(const QFileDialogArgs &args,
- QString *initialDirectory,
- QString *selectedFilter);
-
-extern QString qt_win_get_existing_directory(const QFileDialogArgs &args);
-#endif
-
/*!
This is a convenience static function that returns an existing file
selected by the user. If the user presses Cancel, it returns a null string.
@@ -2110,13 +2092,7 @@ QString QFileDialog::getOpenFileName(QWidget *parent,
args.filter = filter;
args.mode = ExistingFile;
args.options = options;
-#if defined(Q_WS_WIN)
- if (QGuiApplicationPrivate::platformIntegration()->usePlatformNativeDialog() && !(args.options & DontUseNativeDialog)) {
- return qt_win_get_open_file_name(args, &(args.directory), selectedFilter);
- }
-#endif
- // create a qt dialog
QFileDialog dialog(args);
if (selectedFilter && !selectedFilter->isEmpty())
dialog.selectNameFilter(*selectedFilter);
@@ -2239,13 +2215,6 @@ QStringList QFileDialog::getOpenFileNames(QWidget *parent,
args.mode = ExistingFiles;
args.options = options;
-#if defined(Q_WS_WIN)
- if (QGuiApplicationPrivate::platformIntegration()->usePlatformNativeDialog() && !(args.options & DontUseNativeDialog)) {
- return qt_win_get_open_file_names(args, &(args.directory), selectedFilter);
- }
-#endif
-
- // create a qt dialog
QFileDialog dialog(args);
if (selectedFilter && !selectedFilter->isEmpty())
dialog.selectNameFilter(*selectedFilter);
@@ -2371,13 +2340,6 @@ QString QFileDialog::getSaveFileName(QWidget *parent,
args.mode = AnyFile;
args.options = options;
-#if defined(Q_WS_WIN)
- if (QGuiApplicationPrivate::platformIntegration()->usePlatformNativeDialog() && !(args.options & DontUseNativeDialog)) {
- return qt_win_get_save_file_name(args, &(args.directory), selectedFilter);
- }
-#endif
-
- // create a qt dialog
QFileDialog dialog(args);
dialog.setAcceptMode(AcceptSave);
if (selectedFilter && !selectedFilter->isEmpty())
@@ -2483,17 +2445,6 @@ QString QFileDialog::getExistingDirectory(QWidget *parent,
args.mode = (options & ShowDirsOnly ? DirectoryOnly : Directory);
args.options = options;
-#if defined(Q_WS_WIN)
- if (QGuiApplicationPrivate::platformIntegration()->usePlatformNativeDialog() && !(args.options & DontUseNativeDialog) && (options & ShowDirsOnly)
-#if defined(Q_OS_WINCE)
- && qt_priv_ptr_valid
-#endif
- ) {
- return qt_win_get_existing_directory(args);
- }
-#endif
-
- // create a qt dialog
QFileDialog dialog(args);
if (dialog.exec() == QDialog::Accepted) {
return dialog.selectedFiles().value(0);
@@ -2609,15 +2560,20 @@ void QFileDialog::done(int result)
void QFileDialog::accept()
{
Q_D(QFileDialog);
- QStringList files = selectedFiles();
- if (files.isEmpty())
- return;
if (!d->usingWidgets()) {
- d->emitFilesSelected(files);
+ const QList<QUrl> urls = selectedUrls();
+ if (urls.isEmpty())
+ return;
+ d->_q_emitUrlsSelected(urls);
+ if (urls.count() == 1)
+ d->_q_emitUrlSelected(urls.first());
QDialog::accept();
return;
}
+ QStringList files = selectedFiles();
+ if (files.isEmpty())
+ return;
QString lineEditText = d->lineEdit()->text();
// "hidden feature" type .. and then enter, and it will move up a dir
// special case for ".."
@@ -2780,7 +2736,7 @@ void QFileDialogPrivate::createWidgets()
qFileDialogUi->setupUi(q);
QList<QUrl> initialBookmarks;
- initialBookmarks << QUrl::fromLocalFile(QLatin1String(""))
+ initialBookmarks << QUrl(QLatin1String("file:"))
<< QUrl::fromLocalFile(QDir::homePath());
qFileDialogUi->sidebar->setModelAndUrls(model, initialBookmarks);
QFileDialog::connect(qFileDialogUi->sidebar, SIGNAL(goToUrl(QUrl)),
@@ -3648,7 +3604,7 @@ void QFileDialogPrivate::_q_fileRenamed(const QString &path, const QString oldNa
}
}
-void QFileDialogPrivate::_q_nativeFileSelected(const QUrl &file)
+void QFileDialogPrivate::_q_emitUrlSelected(const QUrl &file)
{
Q_Q(QFileDialog);
emit q->urlSelected(file);
@@ -3656,7 +3612,7 @@ void QFileDialogPrivate::_q_nativeFileSelected(const QUrl &file)
emit q->fileSelected(file.toLocalFile());
}
-void QFileDialogPrivate::_q_nativeFilesSelected(const QList<QUrl> &files)
+void QFileDialogPrivate::_q_emitUrlsSelected(const QList<QUrl> &files)
{
Q_Q(QFileDialog);
emit q->urlsSelected(files);
@@ -3757,7 +3713,7 @@ void QFileDialogComboBox::showPopup()
idx = idx.parent();
}
// add "my computer"
- list.append(QUrl::fromLocalFile(QLatin1String("")));
+ list.append(QUrl(QLatin1String("file:")));
urlModel->addUrls(list, 0);
idx = model()->index(model()->rowCount() - 1, 0);
diff --git a/src/widgets/dialogs/qfiledialog.h b/src/widgets/dialogs/qfiledialog.h
index 404e16cde1..184e07261a 100644
--- a/src/widgets/dialogs/qfiledialog.h
+++ b/src/widgets/dialogs/qfiledialog.h
@@ -287,8 +287,8 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_updateOkButton())
Q_PRIVATE_SLOT(d_func(), void _q_currentChanged(const QModelIndex &index))
Q_PRIVATE_SLOT(d_func(), void _q_enterDirectory(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_nativeFileSelected(const QUrl &))
- Q_PRIVATE_SLOT(d_func(), void _q_nativeFilesSelected(const QList<QUrl> &))
+ Q_PRIVATE_SLOT(d_func(), void _q_emitUrlSelected(const QUrl &))
+ Q_PRIVATE_SLOT(d_func(), void _q_emitUrlsSelected(const QList<QUrl> &))
Q_PRIVATE_SLOT(d_func(), void _q_nativeCurrentChanged(const QUrl &))
Q_PRIVATE_SLOT(d_func(), void _q_nativeEnterDirectory(const QUrl&))
Q_PRIVATE_SLOT(d_func(), void _q_goToDirectory(const QString &path))
diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h
index 632bbca5a4..24969b1179 100644
--- a/src/widgets/dialogs/qfiledialog_p.h
+++ b/src/widgets/dialogs/qfiledialog_p.h
@@ -210,8 +210,8 @@ public:
void _q_updateOkButton();
void _q_currentChanged(const QModelIndex &index);
void _q_enterDirectory(const QModelIndex &index);
- void _q_nativeFileSelected(const QUrl &file);
- void _q_nativeFilesSelected(const QList<QUrl> &files);
+ void _q_emitUrlSelected(const QUrl &file);
+ void _q_emitUrlsSelected(const QList<QUrl> &files);
void _q_nativeCurrentChanged(const QUrl &file);
void _q_nativeEnterDirectory(const QUrl &directory);
void _q_goToDirectory(const QString &);
@@ -369,7 +369,7 @@ inline QUrl QFileDialogPrivate::directory_sys() const
{
if (QPlatformFileDialogHelper *helper = platformFileDialogHelper())
return helper->directory();
- return QString();
+ return QUrl();
}
inline void QFileDialogPrivate::selectFile_sys(const QUrl &filename)
diff --git a/src/widgets/dialogs/qinputdialog.cpp b/src/widgets/dialogs/qinputdialog.cpp
index 10d693b4a3..99344b3dd8 100644
--- a/src/widgets/dialogs/qinputdialog.cpp
+++ b/src/widgets/dialogs/qinputdialog.cpp
@@ -60,25 +60,37 @@
QT_USE_NAMESPACE
-static const char *signalForMember(const char *member)
+enum CandidateSignal {
+ TextValueSelectedSignal,
+ IntValueSelectedSignal,
+ DoubleValueSelectedSignal,
+
+ NumCandidateSignals
+};
+
+static const char *candidateSignal(int which)
{
- static const int NumCandidates = 4;
- static const char * const candidateSignals[NumCandidates] = {
- SIGNAL(textValueSelected(QString)),
- SIGNAL(intValueSelected(int)),
- SIGNAL(doubleValueSelected(double)),
- SIGNAL(accepted())
+ switch (CandidateSignal(which)) {
+ case TextValueSelectedSignal: return SIGNAL(textValueSelected(QString));
+ case IntValueSelectedSignal: return SIGNAL(intValueSelected(int));
+ case DoubleValueSelectedSignal: return SIGNAL(doubleValueSelected(double));
+
+ case NumCandidateSignals: ; // fall through
};
+ Q_UNREACHABLE();
+ return Q_NULLPTR;
+}
+static const char *signalForMember(const char *member)
+{
QByteArray normalizedMember(QMetaObject::normalizedSignature(member));
- int i = 0;
- while (i < NumCandidates - 1) { // sic
- if (QMetaObject::checkConnectArgs(candidateSignals[i], normalizedMember))
- break;
- ++i;
- }
- return candidateSignals[i];
+ for (int i = 0; i < NumCandidateSignals; ++i)
+ if (QMetaObject::checkConnectArgs(candidateSignal(i), normalizedMember))
+ return candidateSignal(i);
+
+ // otherwise, use fit-all accepted signal:
+ return SIGNAL(accepted());
}
QT_BEGIN_NAMESPACE
diff --git a/src/widgets/dialogs/qsidebar.cpp b/src/widgets/dialogs/qsidebar.cpp
index 3d22992e3a..7b691dc609 100644
--- a/src/widgets/dialogs/qsidebar.cpp
+++ b/src/widgets/dialogs/qsidebar.cpp
@@ -249,7 +249,8 @@ void QUrlModel::addUrls(const QList<QUrl> &list, int row, bool move)
continue;
//this makes sure the url is clean
const QString cleanUrl = QDir::cleanPath(url.toLocalFile());
- url = QUrl::fromLocalFile(cleanUrl);
+ if (!cleanUrl.isEmpty())
+ url = QUrl::fromLocalFile(cleanUrl);
for (int j = 0; move && j < rowCount(); ++j) {
QString local = index(j, 0).data(UrlRole).toUrl().toLocalFile();
diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp
index b294e98c30..15f922a5b8 100644
--- a/src/widgets/dialogs/qwizard.cpp
+++ b/src/widgets/dialogs/qwizard.cpp
@@ -1475,7 +1475,7 @@ void QWizardPrivate::updateButtonTexts()
void QWizardPrivate::updateButtonLayout()
{
if (buttonsHaveCustomLayout) {
- QVarLengthArray<QWizard::WizardButton> array(buttonsCustomLayout.count());
+ QVarLengthArray<QWizard::WizardButton, QWizard::NButtons> array(buttonsCustomLayout.count());
for (int i = 0; i < buttonsCustomLayout.count(); ++i)
array[i] = buttonsCustomLayout.at(i);
setButtonLayout(array.constData(), array.count());
diff --git a/src/widgets/doc/qtwidgets.qdocconf b/src/widgets/doc/qtwidgets.qdocconf
index 508a257fa5..4b19702208 100644
--- a/src/widgets/doc/qtwidgets.qdocconf
+++ b/src/widgets/doc/qtwidgets.qdocconf
@@ -2,7 +2,6 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = QtWidgets
description = Qt Widgets Reference Documentation
-url = http://qt-project.org/doc/qt-$QT_VER
version = $QT_VERSION
examplesinstallpath = widgets
diff --git a/src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc b/src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc
index 36d3dc6af4..702c17bc26 100644
--- a/src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc
+++ b/src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc
@@ -1864,3 +1864,8 @@ QTabBar::close-button:hover {
}
//! [159]
+
+//! [160]
+* { lineedit-password-mask-delay: 1000 }
+//! [160]
+
diff --git a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
index e8c1be4c46..32fe384c75 100644
--- a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
+++ b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
@@ -862,6 +862,9 @@
\l{#lineedit-password-character-prop}{lineedit-password-character}
property.
+ The password mask delay can be changed using the
+ \l{#lineedit-password-mask-delay-prop}{lineedit-password-mask-delay}
+
See \l{Qt Style Sheets Examples#Customizing QLineEdit}{Customizing QLineEdit}
for an example.
@@ -2009,6 +2012,23 @@
\snippet code/doc_src_stylesheet.qdoc 61
\row
+ \li \b{\c lineedit-password-mask-delay*} \target lineedit-password-mask-delay-prop
+ \li \l{#Number}{Number}
+ \li The QLineEdit password mask delay in milliseconds before
+ \l{#lineedit-password-character-prop}{lineedit-password-character} is applied to visible character.
+
+ If this property is not specified, it defaults to the
+ value specified by the current style for the
+ \l{QStyle::}{SH_LineEdit_PasswordMaskDelay} style hint.
+
+ \b{This property was added in Qt 5.4.}
+
+ Example:
+
+ \snippet code/doc_src_stylesheet.qdoc 160
+
+
+ \row
\li \b{\c margin} \target margin-prop
\li \l {Box Lengths}
\li The widget's margins. Equivalent to specifying \c
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp
index e327a8737a..551f229611 100644
--- a/src/widgets/graphicsview/qgraphicsitem.cpp
+++ b/src/widgets/graphicsview/qgraphicsitem.cpp
@@ -332,6 +332,8 @@
this flag is disabled; children can draw anywhere. This behavior is
enforced by QGraphicsView::drawItems() or
QGraphicsScene::drawItems(). This flag was introduced in Qt 4.3.
+ \note This flag is similar to ItemContainsChildrenInShape but in addition
+ enforces the containment by clipping the children.
\value ItemIgnoresTransformations The item ignores inherited
transformations (i.e., its position is still anchored to its parent, but
@@ -423,6 +425,19 @@
ItemStopsClickFocusPropagation, but also suppresses focus-out. This flag
allows you to completely take over focus handling.
This flag was introduced in Qt 4.7. \endomit
+
+ \value ItemContainsChildrenInShape This flag indicates that all of the
+ item's direct or indirect children only draw within the item's shape.
+ Unlike ItemClipsChildrenToShape, this restriction is not enforced. Set
+ ItemContainsChildrenInShape when you manually assure that drawing
+ is bound to the item's shape and want to avoid the cost associated with
+ enforcing the clip. Setting this flag enables more efficient drawing and
+ collision detection. The flag is disabled by default.
+ \note If both this flag and ItemClipsChildrenToShape are set, the clip
+ will be enforced. This is equivalent to just setting
+ ItemClipsChildrenToShape.
+ .
+ This flag was introduced in Qt 5.4.
*/
/*!
@@ -836,6 +851,10 @@ void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag ch
flag = AncestorIgnoresTransformations;
enabled = flags & QGraphicsItem::ItemIgnoresTransformations;
break;
+ case QGraphicsItem::ItemContainsChildrenInShape:
+ flag = AncestorContainsChildren;
+ enabled = flags & QGraphicsItem::ItemContainsChildrenInShape;
+ break;
default:
return;
}
@@ -895,6 +914,8 @@ void QGraphicsItemPrivate::updateAncestorFlags()
flags |= AncestorClipsChildren;
if (pd->flags & QGraphicsItem::ItemIgnoresTransformations)
flags |= AncestorIgnoresTransformations;
+ if (pd->flags & QGraphicsItem::ItemContainsChildrenInShape)
+ flags |= AncestorContainsChildren;
}
if (ancestorFlags == flags)
@@ -1831,6 +1852,11 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags)
d_ptr->markParentDirty(true);
}
+ if ((flags & ItemContainsChildrenInShape) != (oldFlags & ItemContainsChildrenInShape)) {
+ // Item children containtment changes. Propagate the ancestor flag to all children.
+ d_ptr->updateAncestorFlag(ItemContainsChildrenInShape);
+ }
+
if ((flags & ItemIgnoresTransformations) != (oldFlags & ItemIgnoresTransformations)) {
// Item children clipping changes. Propagate the ancestor flag to
// all children.
@@ -2322,7 +2348,8 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly,
}
// Update children with explicitly = false.
- const bool updateChildren = update && !((flags & QGraphicsItem::ItemClipsChildrenToShape)
+ const bool updateChildren = update && !((flags & QGraphicsItem::ItemClipsChildrenToShape
+ || flags & QGraphicsItem::ItemContainsChildrenInShape)
&& !(flags & QGraphicsItem::ItemHasNoContents));
foreach (QGraphicsItem *child, children) {
if (!newVisible || !child->d_ptr->explicitlyHidden)
@@ -2835,7 +2862,9 @@ QRectF QGraphicsItemPrivate::effectiveBoundingRect(QGraphicsItem *topMostEffectI
#ifndef QT_NO_GRAPHICSEFFECT
Q_Q(const QGraphicsItem);
QRectF brect = effectiveBoundingRect(q_ptr->boundingRect());
- if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren || topMostEffectItem == q)
+ if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren
+ || topMostEffectItem == q)
return brect;
const QGraphicsItem *effectParent = parent;
@@ -2847,6 +2876,7 @@ QRectF QGraphicsItemPrivate::effectiveBoundingRect(QGraphicsItem *topMostEffectI
brect = effectParent->mapRectToItem(q, effectRectInParentSpace);
}
if (effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren
|| topMostEffectItem == effectParent) {
return brect;
}
@@ -7442,7 +7472,8 @@ QVariant QGraphicsItem::extension(const QVariant &variant) const
*/
void QGraphicsItem::addToIndex()
{
- if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
+ if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren) {
// ### add to child index only if applicable
return;
}
@@ -7459,7 +7490,8 @@ void QGraphicsItem::addToIndex()
*/
void QGraphicsItem::removeFromIndex()
{
- if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
+ if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren) {
// ### remove from child index only if applicable
return;
}
@@ -11451,6 +11483,9 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag)
case QGraphicsItem::ItemStopsFocusHandling:
str = "ItemStopsFocusHandling";
break;
+ case QGraphicsItem::ItemContainsChildrenInShape:
+ str = "ItemContainsChildrenInShape";
+ break;
}
debug << str;
return debug;
diff --git a/src/widgets/graphicsview/qgraphicsitem.h b/src/widgets/graphicsview/qgraphicsitem.h
index 4283deb5b8..dfc06fdaea 100644
--- a/src/widgets/graphicsview/qgraphicsitem.h
+++ b/src/widgets/graphicsview/qgraphicsitem.h
@@ -105,7 +105,8 @@ public:
ItemIsFocusScope = 0x8000, // internal
ItemSendsScenePositionChanges = 0x10000,
ItemStopsClickFocusPropagation = 0x20000,
- ItemStopsFocusHandling = 0x40000
+ ItemStopsFocusHandling = 0x40000,
+ ItemContainsChildrenInShape = 0x80000
// NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag.
};
Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag)
diff --git a/src/widgets/graphicsview/qgraphicsitem_p.h b/src/widgets/graphicsview/qgraphicsitem_p.h
index 3968d89a13..4d1835f178 100644
--- a/src/widgets/graphicsview/qgraphicsitem_p.h
+++ b/src/widgets/graphicsview/qgraphicsitem_p.h
@@ -172,7 +172,8 @@ public:
AncestorHandlesChildEvents = 0x1,
AncestorClipsChildren = 0x2,
AncestorIgnoresTransformations = 0x4,
- AncestorFiltersChildEvents = 0x8
+ AncestorFiltersChildEvents = 0x8,
+ AncestorContainsChildren = 0x10
};
inline QGraphicsItemPrivate()
@@ -213,7 +214,6 @@ public:
needSortChildren(0),
allChildrenDirty(0),
fullUpdatePending(0),
- dirtyChildrenBoundingRect(1),
flags(0),
paintedViewBoundingRectsNeedRepaint(0),
dirtySceneTransform(1),
@@ -239,6 +239,7 @@ public:
mayHaveChildWithGraphicsEffect(0),
isDeclarativeItem(0),
sendParentChangeNotification(0),
+ dirtyChildrenBoundingRect(1),
globalStackingOrder(-1),
q_ptr(0)
{
@@ -544,7 +545,7 @@ public:
quint32 handlesChildEvents : 1;
quint32 itemDiscovered : 1;
quint32 hasCursor : 1;
- quint32 ancestorFlags : 4;
+ quint32 ancestorFlags : 5;
quint32 cacheMode : 2;
quint32 hasBoundingRegionGranularity : 1;
quint32 isWidget : 1;
@@ -555,10 +556,9 @@ public:
quint32 needSortChildren : 1;
quint32 allChildrenDirty : 1;
quint32 fullUpdatePending : 1;
- quint32 dirtyChildrenBoundingRect : 1;
// Packed 32 bits
- quint32 flags : 19;
+ quint32 flags : 20;
quint32 paintedViewBoundingRectsNeedRepaint : 1;
quint32 dirtySceneTransform : 1;
quint32 geometryChanged : 1;
@@ -571,9 +571,9 @@ public:
quint32 filtersDescendantEvents : 1;
quint32 sceneTransformTranslateOnly : 1;
quint32 notifyBoundingRectChanged : 1;
- quint32 notifyInvalidated : 1;
// New 32 bits
+ quint32 notifyInvalidated : 1;
quint32 mouseSetsFocus : 1;
quint32 explicitActivate : 1;
quint32 wantsActive : 1;
@@ -585,7 +585,8 @@ public:
quint32 mayHaveChildWithGraphicsEffect : 1;
quint32 isDeclarativeItem : 1;
quint32 sendParentChangeNotification : 1;
- quint32 padding : 21;
+ quint32 dirtyChildrenBoundingRect : 1;
+ quint32 padding : 19;
// Optional stacking order
int globalStackingOrder;
diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp
index bccdb1fbaa..1cd162e6bb 100644
--- a/src/widgets/graphicsview/qgraphicsscene.cpp
+++ b/src/widgets/graphicsview/qgraphicsscene.cpp
@@ -299,6 +299,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate()
painterStateProtection(true),
sortCacheEnabled(false),
allItemsIgnoreTouchEvents(true),
+ minimumRenderSize(0.0),
selectionChanging(0),
rectAdjust(2),
focusItem(0),
@@ -4716,19 +4717,40 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
wasDirtyParentSceneTransform = true;
}
- const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
+ const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
+ || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape);
bool drawItem = itemHasContents && !itemIsFullyTransparent;
- if (drawItem) {
+ if (drawItem || minimumRenderSize > 0.0) {
const QRectF brect = adjustedItemEffectiveBoundingRect(item);
ENSURE_TRANSFORM_PTR
- QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toAlignedRect()
- : transformPtr->mapRect(brect).toAlignedRect();
- viewBoundingRect.adjust(-int(rectAdjust), -int(rectAdjust), rectAdjust, rectAdjust);
- if (widget)
- item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
- drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect)
- : !viewBoundingRect.normalized().isEmpty();
- if (!drawItem) {
+ QRectF preciseViewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy())
+ : transformPtr->mapRect(brect);
+
+ bool itemIsTooSmallToRender = false;
+ if (minimumRenderSize > 0.0
+ && (preciseViewBoundingRect.width() < minimumRenderSize
+ || preciseViewBoundingRect.height() < minimumRenderSize)) {
+ itemIsTooSmallToRender = true;
+ drawItem = false;
+ }
+
+ bool itemIsOutsideVisibleRect = false;
+ if (drawItem) {
+ QRect viewBoundingRect = preciseViewBoundingRect.toAlignedRect();
+ viewBoundingRect.adjust(-int(rectAdjust), -int(rectAdjust), rectAdjust, rectAdjust);
+ if (widget)
+ item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
+ drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect)
+ : !viewBoundingRect.normalized().isEmpty();
+ itemIsOutsideVisibleRect = !drawItem;
+ }
+
+ if (itemIsTooSmallToRender || itemIsOutsideVisibleRect) {
+ // We cannot simply use !drawItem here. If we did it is possible
+ // to enter the outter if statement with drawItem == false and minimumRenderSize > 0
+ // and finally end up inside this inner if, even though none of the above two
+ // conditions are met. In that case we should not return from this function
+ // but call draw() instead.
if (!itemHasChildren)
return;
if (itemClipsChildrenToShape) {
@@ -5200,7 +5222,8 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool
// Process children.
if (itemHasChildren && item->d_ptr->dirtyChildren) {
- const bool itemClipsChildrenToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape;
+ const bool itemClipsChildrenToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
+ || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape;
// Items with no content are threated as 'dummy' items which means they are never drawn and
// 'processed', so the painted view bounding rect is never up-to-date. This means that whenever
// such an item changes geometry, its children have to take care of the update regardless
@@ -5729,6 +5752,49 @@ bool QGraphicsScene::sendEvent(QGraphicsItem *item, QEvent *event)
return d->sendEvent(item, event);
}
+/*!
+ \property QGraphicsScene::minimumRenderSize
+ \since 5.4
+ \brief the minimal view-transformed size an item must have to be drawn
+
+ When the scene is rendered, any item whose width or height, transformed
+ to the target view, is smaller that minimumRenderSize(), will not be
+ rendered. If an item is not rendered and it clips its children items
+ they will also not be rendered. Set this value to speed up rendering
+ of scenes with many objects rendered on a zoomed out view.
+
+ The default value is 0. If unset, or if set to 0 or a negative value,
+ all items will always be rendered.
+
+ For example, setting this property can be especially useful if a scene
+ is rendered by multiple views, one of which serves as an overview which
+ always displays all items. In scenes with many items, such a view will
+ use a high scaling factor so that all items can be shown. Due to the
+ scaling, smaller items will only make an insignificant contribution to
+ the final rendered scene. To avoid drawing these items and reduce the
+ time necessary to render the scene, you can call setMinimumRenderSize()
+ with a non-negative value.
+
+ \note Items that are not drawn as a result of being too small, are still
+ returned by methods such as items() and itemAt(), and participate in
+ collision detection and interactions. It is recommended that you set
+ minimumRenderSize() to a value less than or equal to 1 in order to
+ avoid large unrendered items that are interactive.
+
+ \sa QStyleOptionGraphicsItem::levelOfDetailFromTransform()
+*/
+qreal QGraphicsScene::minimumRenderSize() const
+{
+ Q_D(const QGraphicsScene);
+ return d->minimumRenderSize;
+}
+void QGraphicsScene::setMinimumRenderSize(qreal minSize)
+{
+ Q_D(QGraphicsScene);
+ d->minimumRenderSize = minSize;
+ update();
+}
+
void QGraphicsScenePrivate::addView(QGraphicsView *view)
{
views << view;
diff --git a/src/widgets/graphicsview/qgraphicsscene.h b/src/widgets/graphicsview/qgraphicsscene.h
index cde0eda125..d95237baef 100644
--- a/src/widgets/graphicsview/qgraphicsscene.h
+++ b/src/widgets/graphicsview/qgraphicsscene.h
@@ -107,6 +107,7 @@ class Q_WIDGETS_EXPORT QGraphicsScene : public QObject
Q_PROPERTY(QFont font READ font WRITE setFont)
Q_PROPERTY(bool sortCacheEnabled READ isSortCacheEnabled WRITE setSortCacheEnabled)
Q_PROPERTY(bool stickyFocus READ stickyFocus WRITE setStickyFocus)
+ Q_PROPERTY(qreal minimumRenderSize READ minimumRenderSize WRITE setMinimumRenderSize)
public:
enum ItemIndexMethod {
@@ -249,6 +250,9 @@ public:
bool sendEvent(QGraphicsItem *item, QEvent *event);
+ qreal minimumRenderSize() const;
+ void setMinimumRenderSize(qreal minSize);
+
public Q_SLOTS:
void update(const QRectF &rect = QRectF());
void invalidate(const QRectF &rect = QRectF(), SceneLayers layers = AllLayers);
@@ -309,6 +313,7 @@ private:
friend class QGraphicsEffect;
friend class QGraphicsSceneIndex;
friend class QGraphicsSceneIndexPrivate;
+ friend class QGraphicsSceneLinearIndex;
friend class QGraphicsSceneBspTreeIndex;
friend class QGraphicsSceneBspTreeIndexPrivate;
friend class QGraphicsItemEffectSourcePrivate;
diff --git a/src/widgets/graphicsview/qgraphicsscene_p.h b/src/widgets/graphicsview/qgraphicsscene_p.h
index 9e5bcec488..9f50dcfea7 100644
--- a/src/widgets/graphicsview/qgraphicsscene_p.h
+++ b/src/widgets/graphicsview/qgraphicsscene_p.h
@@ -117,6 +117,8 @@ public:
quint32 allItemsIgnoreTouchEvents : 1;
quint32 padding : 15;
+ qreal minimumRenderSize;
+
QRectF growingItemsBoundingRect;
void _q_emitUpdated();
diff --git a/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp
index 7598163f2d..50f17ab73f 100644
--- a/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp
+++ b/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp
@@ -169,7 +169,8 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex()
untransformableItems << item;
continue;
}
- if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
+ if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren)
continue;
bsp.insertItem(item, item->d_ptr->sceneEffectiveBoundingRect());
@@ -351,7 +352,8 @@ void QGraphicsSceneBspTreeIndexPrivate::removeItem(QGraphicsItem *item, bool rec
// Avoid virtual function calls from the destructor.
purgePending = true;
removedItems << item;
- } else if (!(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) {
+ } else if (!(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren)) {
bsp.removeItem(item, item->d_ptr->sceneEffectiveBoundingRect());
}
} else {
@@ -510,7 +512,8 @@ void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *
return;
if (item->d_ptr->index == -1 || item->d_ptr->itemIsUntransformable()
- || (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) {
+ || (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren)) {
return; // Item is not in BSP tree; nothing to do.
}
@@ -641,8 +644,10 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics
QGraphicsItem::GraphicsItemFlags newFlags = *static_cast<const QGraphicsItem::GraphicsItemFlags *>(value);
bool ignoredTransform = item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations;
bool willIgnoreTransform = newFlags & QGraphicsItem::ItemIgnoresTransformations;
- bool clipsChildren = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape;
- bool willClipChildren = newFlags & QGraphicsItem::ItemClipsChildrenToShape;
+ bool clipsChildren = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
+ || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape;
+ bool willClipChildren = newFlags & QGraphicsItem::ItemClipsChildrenToShape
+ || newFlags & QGraphicsItem::ItemContainsChildrenInShape;
if ((ignoredTransform != willIgnoreTransform) || (clipsChildren != willClipChildren)) {
QGraphicsItem *thatItem = const_cast<QGraphicsItem *>(item);
// Remove item and its descendants from the index and append
@@ -663,10 +668,13 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics
bool ignoredTransform = item->d_ptr->itemIsUntransformable();
bool willIgnoreTransform = (item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations)
|| (newParent && newParent->d_ptr->itemIsUntransformable());
- bool ancestorClippedChildren = item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren;
+ bool ancestorClippedChildren = item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren;
bool ancestorWillClipChildren = newParent
- && ((newParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)
- || (newParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren));
+ && ((newParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
+ || newParent->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape)
+ || (newParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || newParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren));
if ((ignoredTransform != willIgnoreTransform) || (ancestorClippedChildren != ancestorWillClipChildren)) {
QGraphicsItem *thatItem = const_cast<QGraphicsItem *>(item);
// Remove item and its descendants from the index and append
diff --git a/src/widgets/graphicsview/qgraphicssceneevent.cpp b/src/widgets/graphicsview/qgraphicssceneevent.cpp
index 631aa7bf19..be91c63fad 100644
--- a/src/widgets/graphicsview/qgraphicssceneevent.cpp
+++ b/src/widgets/graphicsview/qgraphicssceneevent.cpp
@@ -348,7 +348,7 @@ class QGraphicsSceneMouseEventPrivate : public QGraphicsSceneEventPrivate
public:
inline QGraphicsSceneMouseEventPrivate()
: button(Qt::NoButton),
- buttons(0), modifiers(0)
+ buttons(0), modifiers(0), source(Qt::MouseEventNotSynthesized), flags(0)
{ }
QPointF pos;
@@ -363,6 +363,8 @@ public:
Qt::MouseButton button;
Qt::MouseButtons buttons;
Qt::KeyboardModifiers modifiers;
+ Qt::MouseEventSource source;
+ Qt::MouseEventFlags flags;
};
/*!
@@ -626,6 +628,60 @@ Qt::KeyboardModifiers QGraphicsSceneMouseEvent::modifiers() const
}
/*!
+ \since 5.4
+
+ Returns information about the mouse event source.
+
+ The mouse event source can be used to distinguish between genuine
+ and artificial mouse events. The latter are events that are
+ synthesized from touch events by the operating system or Qt itself.
+
+ \sa Qt::MouseEventSource
+ \sa QMouseEvent::source()
+ */
+Qt::MouseEventSource QGraphicsSceneMouseEvent::source() const
+{
+ Q_D(const QGraphicsSceneMouseEvent);
+ return d->source;
+}
+
+/*!
+ \since 5.4
+ \internal
+ */
+void QGraphicsSceneMouseEvent::setSource(Qt::MouseEventSource source)
+{
+ Q_D(QGraphicsSceneMouseEvent);
+ d->source = source;
+}
+
+/*!
+ \since 5.4
+
+ Returns the mouse event flags.
+
+ The mouse event flags provide additional information about a mouse event.
+
+ \sa Qt::MouseEventFlag
+ \sa QMouseEvent::flags()
+ */
+Qt::MouseEventFlags QGraphicsSceneMouseEvent::flags() const
+{
+ Q_D(const QGraphicsSceneMouseEvent);
+ return d->flags;
+}
+
+/*!
+ \since 5.4
+ \internal
+ */
+void QGraphicsSceneMouseEvent::setFlags(Qt::MouseEventFlags flags)
+{
+ Q_D(QGraphicsSceneMouseEvent);
+ d->flags = flags;
+}
+
+/*!
\internal
*/
void QGraphicsSceneMouseEvent::setModifiers(Qt::KeyboardModifiers modifiers)
diff --git a/src/widgets/graphicsview/qgraphicssceneevent.h b/src/widgets/graphicsview/qgraphicssceneevent.h
index e744d08edf..2c9c1f3f50 100644
--- a/src/widgets/graphicsview/qgraphicssceneevent.h
+++ b/src/widgets/graphicsview/qgraphicssceneevent.h
@@ -121,6 +121,12 @@ public:
Qt::KeyboardModifiers modifiers() const;
void setModifiers(Qt::KeyboardModifiers modifiers);
+ Qt::MouseEventSource source() const;
+ void setSource(Qt::MouseEventSource source);
+
+ Qt::MouseEventFlags flags() const;
+ void setFlags(Qt::MouseEventFlags);
+
private:
Q_DECLARE_PRIVATE(QGraphicsSceneMouseEvent)
Q_DISABLE_COPY(QGraphicsSceneMouseEvent)
diff --git a/src/widgets/graphicsview/qgraphicssceneindex.cpp b/src/widgets/graphicsview/qgraphicssceneindex.cpp
index 40f63937f4..d06c5523ca 100644
--- a/src/widgets/graphicsview/qgraphicssceneindex.cpp
+++ b/src/widgets/graphicsview/qgraphicssceneindex.cpp
@@ -278,7 +278,8 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe
Q_ASSERT(!item->d_ptr->dirtySceneTransform);
}
- const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
+ const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
+ || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape);
bool processItem = !itemIsFullyTransparent;
if (processItem) {
processItem = intersect(item, exposeRect, mode, viewTransform, intersectData);
diff --git a/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h b/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h
index 7debcfb501..baf3de3755 100644
--- a/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h
+++ b/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h
@@ -70,31 +70,62 @@ class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex
Q_OBJECT
public:
- QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0) : QGraphicsSceneIndex(scene)
+ QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0) : QGraphicsSceneIndex(scene), m_itemsIsValid(true)
{ }
QList<QGraphicsItem *> items(Qt::SortOrder order = Qt::DescendingOrder) const
- { Q_UNUSED(order); return m_items; }
+ {
+ Q_UNUSED(order);
+ return validList();
+ }
virtual QList<QGraphicsItem *> estimateItems(const QRectF &rect, Qt::SortOrder order) const
{
Q_UNUSED(rect);
Q_UNUSED(order);
- return m_items;
+ return validList();
}
protected :
virtual void clear()
- { m_items.clear(); }
+ {
+ m_items.clear();
+ m_itemsIsValid = true;
+ }
virtual void addItem(QGraphicsItem *item)
- { m_items << item; }
+ {
+ if (m_itemsIsValid)
+ m_items << item;
+ }
virtual void removeItem(QGraphicsItem *item)
- { m_items.removeOne(item); }
+ {
+ Q_UNUSED(item);
+ m_itemsIsValid = false;
+ }
private:
- QList<QGraphicsItem*> m_items;
+ mutable QList<QGraphicsItem*> m_items;
+ mutable bool m_itemsIsValid;
+
+ QList<QGraphicsItem*>& validList() const
+ {
+ if (!m_itemsIsValid)
+ {
+ m_items.clear();
+
+ QList<QGraphicsItem*> stack = scene()->d_func()->topLevelItems;
+ m_items << stack;
+ while (!stack.isEmpty())
+ {
+ m_items << stack.last()->childItems();
+ stack << stack.takeLast()->childItems();
+ }
+ m_itemsIsValid = true;
+ }
+ return m_items;
+ }
};
#endif // QT_NO_GRAPHICSVIEW
diff --git a/src/widgets/graphicsview/qgraphicsview.cpp b/src/widgets/graphicsview/qgraphicsview.cpp
index 5bcf52b6a3..9cd684a408 100644
--- a/src/widgets/graphicsview/qgraphicsview.cpp
+++ b/src/widgets/graphicsview/qgraphicsview.cpp
@@ -655,6 +655,8 @@ void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event)
mouseEvent.setButtons(event->buttons());
mouseEvent.setButton(event->button());
mouseEvent.setModifiers(event->modifiers());
+ mouseEvent.setSource(event->source());
+ mouseEvent.setFlags(event->flags());
lastMouseMoveScenePoint = mouseEvent.scenePos();
lastMouseMoveScreenPoint = mouseEvent.screenPos();
mouseEvent.setAccepted(false);
@@ -3217,6 +3219,8 @@ void QGraphicsView::mouseDoubleClickEvent(QMouseEvent *event)
mouseEvent.setAccepted(false);
mouseEvent.setButton(event->button());
mouseEvent.setModifiers(event->modifiers());
+ mouseEvent.setSource(event->source());
+ mouseEvent.setFlags(event->flags());
if (event->spontaneous())
qt_sendSpontaneousEvent(d->scene, &mouseEvent);
else
@@ -3265,6 +3269,8 @@ void QGraphicsView::mousePressEvent(QMouseEvent *event)
mouseEvent.setButtons(event->buttons());
mouseEvent.setButton(event->button());
mouseEvent.setModifiers(event->modifiers());
+ mouseEvent.setSource(event->source());
+ mouseEvent.setFlags(event->flags());
mouseEvent.setAccepted(false);
if (event->spontaneous())
qt_sendSpontaneousEvent(d->scene, &mouseEvent);
@@ -3392,6 +3398,8 @@ void QGraphicsView::mouseReleaseEvent(QMouseEvent *event)
mouseEvent.setButtons(event->buttons());
mouseEvent.setButton(event->button());
mouseEvent.setModifiers(event->modifiers());
+ mouseEvent.setSource(event->source());
+ mouseEvent.setFlags(event->flags());
mouseEvent.setAccepted(false);
if (event->spontaneous())
qt_sendSpontaneousEvent(d->scene, &mouseEvent);
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index b2dc614b2b..4b59e72545 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -1949,7 +1949,7 @@ void QAbstractItemView::dragMoveEvent(QDragMoveEvent *event)
case AboveItem:
if (d->isIndexDropEnabled(index.parent())) {
d->dropIndicatorRect = QRect(rect.left(), rect.top(), rect.width(), 0);
- event->accept();
+ event->acceptProposedAction();
} else {
d->dropIndicatorRect = QRect();
}
@@ -1957,7 +1957,7 @@ void QAbstractItemView::dragMoveEvent(QDragMoveEvent *event)
case BelowItem:
if (d->isIndexDropEnabled(index.parent())) {
d->dropIndicatorRect = QRect(rect.left(), rect.bottom(), rect.width(), 0);
- event->accept();
+ event->acceptProposedAction();
} else {
d->dropIndicatorRect = QRect();
}
@@ -1965,7 +1965,7 @@ void QAbstractItemView::dragMoveEvent(QDragMoveEvent *event)
case OnItem:
if (d->isIndexDropEnabled(index)) {
d->dropIndicatorRect = rect;
- event->accept();
+ event->acceptProposedAction();
} else {
d->dropIndicatorRect = QRect();
}
@@ -1973,7 +1973,7 @@ void QAbstractItemView::dragMoveEvent(QDragMoveEvent *event)
case OnViewport:
d->dropIndicatorRect = QRect();
if (d->isIndexDropEnabled(rootIndex())) {
- event->accept(); // allow dropping in empty areas
+ event->acceptProposedAction(); // allow dropping in empty areas
}
break;
}
@@ -1981,7 +1981,7 @@ void QAbstractItemView::dragMoveEvent(QDragMoveEvent *event)
d->dropIndicatorRect = QRect();
d->dropIndicatorPosition = OnViewport;
if (d->isIndexDropEnabled(rootIndex())) {
- event->accept(); // allow dropping in empty areas
+ event->acceptProposedAction(); // allow dropping in empty areas
}
}
d->viewport->update();
@@ -2050,11 +2050,14 @@ void QAbstractItemView::dropEvent(QDropEvent *event)
int col = -1;
int row = -1;
if (d->dropOn(event, &row, &col, &index)) {
- if (d->model->dropMimeData(event->mimeData(),
- dragDropMode() == InternalMove ? Qt::MoveAction : event->dropAction(), row, col, index)) {
- if (dragDropMode() == InternalMove)
- event->setDropAction(Qt::MoveAction);
+ const Qt::DropAction action = dragDropMode() == InternalMove ? Qt::MoveAction : event->dropAction();
+ if (d->model->dropMimeData(event->mimeData(), action, row, col, index)) {
+ if (action != event->dropAction()) {
+ event->setDropAction(action);
event->accept();
+ } else {
+ event->acceptProposedAction();
+ }
}
}
stopAutoScroll();
@@ -3126,6 +3129,8 @@ void QAbstractItemView::setIndexWidget(const QModelIndex &index, QWidget *widget
Q_D(QAbstractItemView);
if (!d->isIndexValid(index))
return;
+ if (indexWidget(index) == widget)
+ return;
if (QWidget *oldWidget = indexWidget(index)) {
d->persistent.remove(oldWidget);
d->removeEditor(oldWidget);
diff --git a/src/widgets/itemviews/qfileiconprovider.cpp b/src/widgets/itemviews/qfileiconprovider.cpp
index b12ab736f4..b6b5c63f84 100644
--- a/src/widgets/itemviews/qfileiconprovider.cpp
+++ b/src/widgets/itemviews/qfileiconprovider.cpp
@@ -368,8 +368,10 @@ QString QFileIconProvider::type(const QFileInfo &info) const
if (info.isRoot())
return QApplication::translate("QFileDialog", "Drive");
if (info.isFile()) {
- if (!info.suffix().isEmpty())
- return info.suffix() + QLatin1Char(' ') + QApplication::translate("QFileDialog", "File");
+ if (!info.suffix().isEmpty()) {
+ //: %1 is a file name suffix, for example txt
+ return QApplication::translate("QFileDialog", "%1 File").arg(info.suffix());
+ }
return QApplication::translate("QFileDialog", "File");
}
diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp
index a252428a81..2bf4c62593 100644
--- a/src/widgets/itemviews/qtableview.cpp
+++ b/src/widgets/itemviews/qtableview.cpp
@@ -1821,8 +1821,15 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi
return QModelIndex();
QModelIndex result = d->model->index(logicalRow, logicalColumn, d->root);
- if (!d->isRowHidden(logicalRow) && !d->isColumnHidden(logicalColumn) && d->isIndexEnabled(result))
+ if (!d->isRowHidden(logicalRow) && !d->isColumnHidden(logicalColumn) && d->isIndexEnabled(result)) {
+ if (d->hasSpans()) {
+ QSpanCollection::Span span = d->span(result.row(), result.column());
+ if (span.width() > 1 || span.height() > 1) {
+ result = d->model->sibling(span.top(), span.left(), result);
+ }
+ }
return result;
+ }
return QModelIndex();
}
diff --git a/src/widgets/kernel/kernel.pri b/src/widgets/kernel/kernel.pri
index 857fe4ac91..a9b8627beb 100644
--- a/src/widgets/kernel/kernel.pri
+++ b/src/widgets/kernel/kernel.pri
@@ -33,8 +33,8 @@ HEADERS += \
kernel/qstandardgestures_p.h \
kernel/qgesturerecognizer.h \
kernel/qgesturemanager_p.h \
- kernel/qdesktopwidget_qpa_p.h \
- kernel/qwidgetwindow_qpa_p.h \
+ kernel/qdesktopwidget_p.h \
+ kernel/qwidgetwindow_p.h \
kernel/qwindowcontainer_p.h
SOURCES += \
@@ -60,9 +60,6 @@ SOURCES += \
kernel/qgesturemanager.cpp \
kernel/qdesktopwidget.cpp \
kernel/qwidgetsvariant.cpp \
- kernel/qapplication_qpa.cpp \
- kernel/qdesktopwidget_qpa.cpp \
- kernel/qwidget_qpa.cpp \
kernel/qwidgetwindow.cpp \
kernel/qwindowcontainer.cpp
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 520fc2db67..9913b225fc 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -57,6 +57,7 @@
#include "qstyleoption.h"
#include "qstylefactory.h"
#include "qtextcodec.h"
+#include "qtooltip.h"
#include "qtranslator.h"
#include "qvariant.h"
#include "qwidget.h"
@@ -67,7 +68,7 @@
#include "private/qstylesheetstyle_p.h"
#include "private/qstyle_p.h"
#include "qmessagebox.h"
-#include "qwidgetwindow_qpa_p.h"
+#include "qwidgetwindow_p.h"
#include <QtWidgets/qgraphicsproxywidget.h>
#include <QtGui/qstylehints.h>
#include <QtGui/qinputmethod.h>
@@ -77,6 +78,7 @@
#endif
#include "private/qkeymapper_p.h"
+#include "private/qaccessiblewidgetfactory_p.h"
#include <qthread.h>
#include <private/qthread_p.h>
@@ -96,6 +98,10 @@
#include "qlibrary.h"
#endif
+#ifdef Q_OS_WIN
+#include <QtCore/qt_windows.h> // for qt_win_display_dc()
+#endif
+
#include "qdatetime.h"
#ifdef Q_OS_WINCE
@@ -187,6 +193,11 @@ QApplicationPrivate::~QApplicationPrivate()
self = 0;
}
+void QApplicationPrivate::createEventDispatcher()
+{
+ QGuiApplicationPrivate::createEventDispatcher();
+}
+
/*!
\class QApplication
\brief The QApplication class manages the GUI application's control
@@ -364,6 +375,14 @@ QApplicationPrivate::~QApplicationPrivate()
Returns the top-level widget at the given \a point; returns 0 if
there is no such widget.
*/
+QWidget *QApplication::topLevelAt(const QPoint &pos)
+{
+ if (const QWindow *window = QGuiApplication::topLevelAt(pos)) {
+ if (const QWidgetWindow *widgetWindow = qobject_cast<const QWidgetWindow *>(window))
+ return widgetWindow->widget();
+ }
+ return 0;
+}
/*!
\fn QWidget *QApplication::topLevelAt(int x, int y)
@@ -374,12 +393,6 @@ QApplicationPrivate::~QApplicationPrivate()
0 if there is no such widget.
*/
-
-/*
- The qt_init() and qt_cleanup() functions are implemented in the
- qapplication_xyz.cpp file.
-*/
-
void qt_init(QApplicationPrivate *priv, int type
);
void qt_init_tooltip_palette();
@@ -583,6 +596,11 @@ void QApplicationPrivate::construct()
qt_gui_eval_init(application_type);
#endif
+#ifndef QT_NO_ACCESSIBILITY
+ // factory for accessible interfaces for widgets shipped with Qt
+ QAccessible::installFactory(&qAccessibleFactory);
+#endif
+
#ifndef QT_NO_LIBRARY
if(load_testability) {
QLibrary testLib(QLatin1String("qttestability"));
@@ -601,6 +619,26 @@ void QApplicationPrivate::construct()
#endif
}
+void qt_init(QApplicationPrivate *priv, int type)
+{
+ Q_UNUSED(priv);
+ Q_UNUSED(type);
+
+ QColormap::initialize();
+
+ qt_init_tooltip_palette();
+
+ QApplicationPrivate::initializeWidgetFontHash();
+}
+
+void qt_init_tooltip_palette()
+{
+#ifndef QT_NO_TOOLTIP
+ if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::ToolTipPalette))
+ QToolTip::setPalette(*toolTipPalette);
+#endif
+}
+
#ifndef QT_NO_STATEMACHINE
void qRegisterGuiStateMachine();
void qUnregisterGuiStateMachine();
@@ -657,6 +695,91 @@ void QApplicationPrivate::initialize()
is_app_running = true; // no longer starting up
}
+static void setPossiblePalette(const QPalette *palette, const char *className)
+{
+ if (palette == 0)
+ return;
+ QApplicationPrivate::setPalette_helper(*palette, className, false);
+}
+
+void QApplicationPrivate::initializeWidgetPaletteHash()
+{
+ QPlatformTheme *platformTheme = QGuiApplicationPrivate::platformTheme();
+ if (!platformTheme)
+ return;
+ qt_app_palettes_hash()->clear();
+
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::ToolButtonPalette), "QToolButton");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::ButtonPalette), "QAbstractButton");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::CheckBoxPalette), "QCheckBox");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::RadioButtonPalette), "QRadioButton");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::HeaderPalette), "QHeaderView");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::ItemViewPalette), "QAbstractItemView");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::MessageBoxLabelPalette), "QMessageBoxLabel");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::TabBarPalette), "QTabBar");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::LabelPalette), "QLabel");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::GroupBoxPalette), "QGroupBox");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::MenuPalette), "QMenu");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::MenuBarPalette), "QMenuBar");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::TextEditPalette), "QTextEdit");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::TextEditPalette), "QTextControl");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::TextLineEditPalette), "QLineEdit");
+}
+
+void QApplicationPrivate::initializeWidgetFontHash()
+{
+ const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
+ if (!theme)
+ return;
+ FontHash *fontHash = qt_app_fonts_hash();
+ fontHash->clear();
+
+ if (const QFont *font = theme->font(QPlatformTheme::MenuFont))
+ fontHash->insert(QByteArrayLiteral("QMenu"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::MenuBarFont))
+ fontHash->insert(QByteArrayLiteral("QMenuBar"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::MenuItemFont))
+ fontHash->insert(QByteArrayLiteral("QMenuItem"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::MessageBoxFont))
+ fontHash->insert(QByteArrayLiteral("QMessageBox"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::LabelFont))
+ fontHash->insert(QByteArrayLiteral("QLabel"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::TipLabelFont))
+ fontHash->insert(QByteArrayLiteral("QTipLabel"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::TitleBarFont))
+ fontHash->insert(QByteArrayLiteral("QTitleBar"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::StatusBarFont))
+ fontHash->insert(QByteArrayLiteral("QStatusBar"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::MdiSubWindowTitleFont))
+ fontHash->insert(QByteArrayLiteral("QMdiSubWindowTitleBar"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::DockWidgetTitleFont))
+ fontHash->insert(QByteArrayLiteral("QDockWidgetTitle"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::PushButtonFont))
+ fontHash->insert(QByteArrayLiteral("QPushButton"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::CheckBoxFont))
+ fontHash->insert(QByteArrayLiteral("QCheckBox"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::RadioButtonFont))
+ fontHash->insert(QByteArrayLiteral("QRadioButton"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::ToolButtonFont))
+ fontHash->insert(QByteArrayLiteral("QToolButton"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::ItemViewFont))
+ fontHash->insert(QByteArrayLiteral("QAbstractItemView"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::ListViewFont))
+ fontHash->insert(QByteArrayLiteral("QListViewFont"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::HeaderViewFont))
+ fontHash->insert(QByteArrayLiteral("QHeaderViewFont"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::ListBoxFont))
+ fontHash->insert(QByteArrayLiteral("QListBox"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::ComboMenuItemFont))
+ fontHash->insert(QByteArrayLiteral("QComboMenuItemFont"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::ComboLineEditFont))
+ fontHash->insert(QByteArrayLiteral("QComboLineEditFont"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::SmallFont))
+ fontHash->insert(QByteArrayLiteral("QSmallFont"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::MiniFont))
+ fontHash->insert(QByteArrayLiteral("QMiniFont"), *font);
+}
+
/*****************************************************************************
Functions returning the active popup and modal widgets.
*****************************************************************************/
@@ -780,6 +903,32 @@ QApplication::~QApplication()
#endif
}
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+// #fixme: Remove.
+static HDC displayDC = 0; // display device context
+
+Q_WIDGETS_EXPORT HDC qt_win_display_dc() // get display DC
+{
+ Q_ASSERT(qApp && qApp->thread() == QThread::currentThread());
+ if (!displayDC)
+ displayDC = GetDC(0);
+ return displayDC;
+}
+#endif
+
+void qt_cleanup()
+{
+ QPixmapCache::clear();
+ QColormap::cleanup();
+
+ QApplicationPrivate::active_window = 0; //### this should not be necessary
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+ if (displayDC) {
+ ReleaseDC(0, displayDC);
+ displayDC = 0;
+ }
+#endif
+}
/*!
\fn QWidget *QApplication::widgetAt(const QPoint &point)
@@ -2086,6 +2235,39 @@ void QApplication::setActiveWindow(QWidget* act)
}
}
+QWidget *qt_tlw_for_window(QWindow *wnd)
+{
+ // QTBUG-32177, wnd might be a QQuickView embedded via window container.
+ while (wnd && !wnd->isTopLevel()) {
+ QWindow *parent = wnd->parent();
+ // Don't end up in windows not belonging to this application
+ if (parent && parent->type() != Qt::ForeignWindow)
+ wnd = wnd->parent();
+ else
+ break;
+ }
+ if (wnd)
+ foreach (QWidget *tlw, qApp->topLevelWidgets())
+ if (tlw->windowHandle() == wnd)
+ return tlw;
+ return 0;
+}
+
+void QApplicationPrivate::notifyActiveWindowChange(QWindow *previous)
+{
+ Q_UNUSED(previous);
+ QWindow *wnd = QGuiApplicationPrivate::focus_window;
+ if (inPopupMode()) // some delayed focus event to ignore
+ return;
+ QWidget *tlw = qt_tlw_for_window(wnd);
+ QApplication::setActiveWindow(tlw);
+ // QTBUG-37126, Active X controls may set the focus on native child widgets.
+ if (wnd && tlw && wnd != tlw->windowHandle()) {
+ if (QWidgetWindow *widgetWindow = qobject_cast<QWidgetWindow *>(wnd))
+ widgetWindow->widget()->setFocus(Qt::ActiveWindowFocusReason);
+ }
+}
+
/*!internal
* Helper function that returns the new focus widget, but does not set the focus reason.
* Returns 0 if a new focus widget could not be found.
@@ -2454,6 +2636,44 @@ bool QApplicationPrivate::tryModalHelper(QWidget *widget, QWidget **rettop)
return !isBlockedByModal(widget->window());
}
+bool qt_try_modal(QWidget *widget, QEvent::Type type)
+{
+ QWidget * top = 0;
+
+ if (QApplicationPrivate::tryModalHelper(widget, &top))
+ return true;
+
+ bool block_event = false;
+
+ switch (type) {
+#if 0
+ case QEvent::Focus:
+ if (!static_cast<QWSFocusEvent*>(event)->simpleData.get_focus)
+ break;
+ // drop through
+#endif
+ case QEvent::MouseButtonPress: // disallow mouse/key events
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseMove:
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ block_event = true;
+ break;
+ default:
+ break;
+ }
+
+ if (block_event && top && top->parentWidget() == 0)
+ top->raise();
+
+ return !block_event;
+}
+
+bool QApplicationPrivate::modalState()
+{
+ return !self->modalWindowList.isEmpty();
+}
+
/*
\internal
*/
@@ -3191,7 +3411,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
tablet->device(), tablet->pointerType(),
tablet->pressure(), tablet->xTilt(), tablet->yTilt(),
tablet->tangentialPressure(), tablet->rotation(), tablet->z(),
- tablet->modifiers(), tablet->uniqueId());
+ tablet->modifiers(), tablet->uniqueId(), tablet->button(), tablet->buttons());
te.spont = e->spontaneous();
res = d->notify_helper(w, w == receiver ? tablet : &te);
eventAccepted = ((w == receiver) ? tablet : &te)->isAccepted();
@@ -3520,7 +3740,7 @@ bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
// deliver the event
bool consumed = receiver->event(e);
- e->spont = false;
+ QCoreApplicationPrivate::setEventSpontaneous(e, false);
return consumed;
}
@@ -3529,6 +3749,123 @@ bool QApplicationPrivate::inPopupMode()
return QApplicationPrivate::popupWidgets != 0;
}
+static void ungrabKeyboardForPopup(QWidget *popup)
+{
+ if (QWidget::keyboardGrabber())
+ qt_widget_private(QWidget::keyboardGrabber())->stealKeyboardGrab(true);
+ else
+ qt_widget_private(popup)->stealKeyboardGrab(false);
+}
+
+static void ungrabMouseForPopup(QWidget *popup)
+{
+ if (QWidget::mouseGrabber())
+ qt_widget_private(QWidget::mouseGrabber())->stealMouseGrab(true);
+ else
+ qt_widget_private(popup)->stealMouseGrab(false);
+}
+
+static bool popupGrabOk;
+
+static void grabForPopup(QWidget *popup)
+{
+ Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
+ popupGrabOk = qt_widget_private(popup)->stealKeyboardGrab(true);
+ if (popupGrabOk) {
+ popupGrabOk = qt_widget_private(popup)->stealMouseGrab(true);
+ if (!popupGrabOk) {
+ // transfer grab back to the keyboard grabber if any
+ ungrabKeyboardForPopup(popup);
+ }
+ }
+}
+
+extern QWidget *qt_button_down;
+extern QWidget *qt_popup_down;
+extern bool qt_replay_popup_mouse_event;
+
+void QApplicationPrivate::closePopup(QWidget *popup)
+{
+ if (!popupWidgets)
+ return;
+ popupWidgets->removeAll(popup);
+
+ if (popup == qt_popup_down) {
+ qt_button_down = 0;
+ qt_popup_down = 0;
+ }
+
+ if (QApplicationPrivate::popupWidgets->count() == 0) { // this was the last popup
+ delete QApplicationPrivate::popupWidgets;
+ QApplicationPrivate::popupWidgets = 0;
+
+ if (popupGrabOk) {
+ popupGrabOk = false;
+
+ if (popup->geometry().contains(QPoint(QGuiApplicationPrivate::mousePressX,
+ QGuiApplicationPrivate::mousePressY))
+ || popup->testAttribute(Qt::WA_NoMouseReplay)) {
+ // mouse release event or inside
+ qt_replay_popup_mouse_event = false;
+ } else { // mouse press event
+ qt_replay_popup_mouse_event = true;
+ }
+
+ // transfer grab back to mouse grabber if any, otherwise release the grab
+ ungrabMouseForPopup(popup);
+
+ // transfer grab back to keyboard grabber if any, otherwise release the grab
+ ungrabKeyboardForPopup(popup);
+ }
+
+ if (active_window) {
+ if (QWidget *fw = active_window->focusWidget()) {
+ if (fw != QApplication::focusWidget()) {
+ fw->setFocus(Qt::PopupFocusReason);
+ } else {
+ QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
+ QCoreApplication::sendEvent(fw, &e);
+ }
+ }
+ }
+
+ } else {
+ // A popup was closed, so the previous popup gets the focus.
+ QWidget* aw = QApplicationPrivate::popupWidgets->last();
+ if (QWidget *fw = aw->focusWidget())
+ fw->setFocus(Qt::PopupFocusReason);
+
+ if (QApplicationPrivate::popupWidgets->count() == 1) // grab mouse/keyboard
+ grabForPopup(aw);
+ }
+
+}
+
+int openPopupCount = 0;
+
+void QApplicationPrivate::openPopup(QWidget *popup)
+{
+ openPopupCount++;
+ if (!popupWidgets) // create list
+ popupWidgets = new QWidgetList;
+ popupWidgets->append(popup); // add to end of list
+
+ if (QApplicationPrivate::popupWidgets->count() == 1) // grab mouse/keyboard
+ grabForPopup(popup);
+
+ // popups are not focus-handled by the window system (the first
+ // popup grabbed the keyboard), so we have to do that manually: A
+ // new popup gets the focus
+ if (popup->focusWidget()) {
+ popup->focusWidget()->setFocus(Qt::PopupFocusReason);
+ } else if (popupWidgets->count() == 1) { // this was the first popup
+ if (QWidget *fw = QApplication::focusWidget()) {
+ QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
+ QApplication::sendEvent(fw, &e);
+ }
+ }
+}
+
#ifdef QT_KEYPAD_NAVIGATION
/*!
Sets the kind of focus navigation Qt should use to \a mode.
@@ -3633,6 +3970,18 @@ bool QApplication::keypadNavigationEnabled()
window must not be hidden (i.e. not have hide() called on it, but be
visible in some sort of way) in order for this to work.
*/
+void QApplication::alert(QWidget *widget, int duration)
+{
+ if (widget) {
+ if (widget->window()->isActiveWindow() && !(widget->window()->windowState() & Qt::WindowMinimized))
+ return;
+ if (QWindow *window= QApplicationPrivate::windowForWidget(widget))
+ window->alert(duration);
+ } else {
+ foreach (QWidget *topLevel, topLevelWidgets())
+ QApplication::alert(topLevel, duration);
+ }
+}
/*!
\property QApplication::cursorFlashTime
@@ -3723,6 +4072,38 @@ int QApplication::keyboardInputInterval()
By default, this property has a value of 3.
*/
+#ifndef QT_NO_WHEELEVENT
+int QApplication::wheelScrollLines()
+{
+ return QApplicationPrivate::wheel_scroll_lines;
+}
+
+void QApplication::setWheelScrollLines(int lines)
+{
+ QApplicationPrivate::wheel_scroll_lines = lines;
+}
+#endif
+
+static inline int uiEffectToFlag(Qt::UIEffect effect)
+{
+ switch (effect) {
+ case Qt::UI_General:
+ return QPlatformTheme::GeneralUiEffect;
+ case Qt::UI_AnimateMenu:
+ return QPlatformTheme::AnimateMenuUiEffect;
+ case Qt::UI_FadeMenu:
+ return QPlatformTheme::FadeMenuUiEffect;
+ case Qt::UI_AnimateCombo:
+ return QPlatformTheme::AnimateComboUiEffect;
+ case Qt::UI_AnimateTooltip:
+ return QPlatformTheme::AnimateTooltipUiEffect;
+ case Qt::UI_FadeTooltip:
+ return QPlatformTheme::FadeTooltipUiEffect;
+ case Qt::UI_AnimateToolBox:
+ return QPlatformTheme::AnimateToolBoxUiEffect;
+ }
+ return 0;
+}
/*!
\fn void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
@@ -3735,6 +4116,19 @@ int QApplication::keyboardInputInterval()
\sa isEffectEnabled(), Qt::UIEffect, setDesktopSettingsAware()
*/
+void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
+{
+ int effectFlags = uiEffectToFlag(effect);
+ if (enable) {
+ if (effectFlags & QPlatformTheme::FadeMenuUiEffect)
+ effectFlags |= QPlatformTheme::AnimateMenuUiEffect;
+ if (effectFlags & QPlatformTheme::FadeTooltipUiEffect)
+ effectFlags |= QPlatformTheme::AnimateTooltipUiEffect;
+ QApplicationPrivate::enabledAnimations |= effectFlags;
+ } else {
+ QApplicationPrivate::enabledAnimations &= ~effectFlags;
+ }
+}
/*!
\fn bool QApplication::isEffectEnabled(Qt::UIEffect effect)
@@ -3749,6 +4143,12 @@ int QApplication::keyboardInputInterval()
\sa setEffectEnabled(), Qt::UIEffect
*/
+bool QApplication::isEffectEnabled(Qt::UIEffect effect)
+{
+ return QColormap::instance().depth() >= 16
+ && (QApplicationPrivate::enabledAnimations & QPlatformTheme::GeneralUiEffect)
+ && (QApplicationPrivate::enabledAnimations & uiEffectToFlag(effect));
+}
/*!
\fn void QApplication::beep()
@@ -3756,6 +4156,10 @@ int QApplication::keyboardInputInterval()
Sounds the bell, using the default volume and sound. The function is \e not
available in Qt for Embedded Linux.
*/
+void QApplication::beep()
+{
+ QMetaObject::invokeMethod(QGuiApplication::platformNativeInterface(), "beep");
+}
/*!
\macro qApp
@@ -3868,11 +4272,19 @@ void QApplicationPrivate::initializeMultitouch()
initializeMultitouch_sys();
}
+void QApplicationPrivate::initializeMultitouch_sys()
+{
+}
+
void QApplicationPrivate::cleanupMultitouch()
{
cleanupMultitouch_sys();
}
+void QApplicationPrivate::cleanupMultitouch_sys()
+{
+}
+
QWidget *QApplicationPrivate::findClosestTouchPointTarget(QTouchDevice *device, const QPointF &screenPos)
{
int closestTouchPointId = -1;
diff --git a/src/widgets/kernel/qapplication.h b/src/widgets/kernel/qapplication.h
index e72fe29bdb..08a450ab32 100644
--- a/src/widgets/kernel/qapplication.h
+++ b/src/widgets/kernel/qapplication.h
@@ -228,7 +228,6 @@ private:
friend class QWidget;
friend class QWidgetPrivate;
friend class QWidgetWindow;
- friend class QETWidget;
friend class QTranslator;
friend class QWidgetAnimator;
#ifndef QT_NO_SHORTCUT
diff --git a/src/widgets/kernel/qapplication_qpa.cpp b/src/widgets/kernel/qapplication_qpa.cpp
deleted file mode 100644
index 5893c52e1b..0000000000
--- a/src/widgets/kernel/qapplication_qpa.cpp
+++ /dev/null
@@ -1,493 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qapplication_p.h"
-#include "qcolormap.h"
-#include "qpalette.h"
-#include "qpixmapcache.h"
-#ifndef QT_NO_CURSOR
-#include "private/qcursor_p.h"
-#endif
-#include "qscreen.h"
-
-#include "private/qwidget_p.h"
-#include "private/qevent_p.h"
-
-#include <qpa/qplatformintegrationfactory_p.h>
-#include <qdesktopwidget.h>
-#include <qpa/qplatformcursor.h>
-#include <qpa/qplatformtheme.h>
-#include <qpa/qplatformwindow.h>
-
-#include <qdebug.h>
-#include <qpa/qwindowsysteminterface.h>
-#include <qpa/qwindowsysteminterface_p.h>
-#include <qpa/qplatformintegration.h>
-
-#include "qdesktopwidget_qpa_p.h"
-#include "qwidgetwindow_qpa_p.h"
-#include "qtooltip.h"
-
-#ifdef Q_OS_WIN
-# include <QtCore/qt_windows.h> // for qt_win_display_dc()
-#endif
-
-QT_BEGIN_NAMESPACE
-
-static QString appFont;
-static bool popupGrabOk;
-extern QWidget *qt_button_down;
-extern QWidget *qt_popup_down;
-extern bool qt_replay_popup_mouse_event;
-int openPopupCount = 0;
-extern QPointer<QWidget> qt_last_mouse_receiver;
-
-void QApplicationPrivate::createEventDispatcher()
-{
- QGuiApplicationPrivate::createEventDispatcher();
-}
-
-bool qt_try_modal(QWidget *widget, QEvent::Type type)
-{
- QWidget * top = 0;
-
- if (QApplicationPrivate::tryModalHelper(widget, &top))
- return true;
-
- bool block_event = false;
-
- switch (type) {
-#if 0
- case QEvent::Focus:
- if (!static_cast<QWSFocusEvent*>(event)->simpleData.get_focus)
- break;
- // drop through
-#endif
- case QEvent::MouseButtonPress: // disallow mouse/key events
- case QEvent::MouseButtonRelease:
- case QEvent::MouseMove:
- case QEvent::KeyPress:
- case QEvent::KeyRelease:
- block_event = true;
- break;
- default:
- break;
- }
-
- if (block_event && top && top->parentWidget() == 0)
- top->raise();
-
- return !block_event;
-}
-
-bool QApplicationPrivate::modalState()
-{
- return !self->modalWindowList.isEmpty();
-}
-
-QWidget *qt_tlw_for_window(QWindow *wnd)
-{
- // QTBUG-32177, wnd might be a QQuickView embedded via window container.
- while (wnd && !wnd->isTopLevel()) {
- QWindow *parent = wnd->parent();
- // Don't end up in windows not belonging to this application
- if (parent && parent->type() != Qt::ForeignWindow)
- wnd = wnd->parent();
- else
- break;
- }
- if (wnd)
- foreach (QWidget *tlw, qApp->topLevelWidgets())
- if (tlw->windowHandle() == wnd)
- return tlw;
- return 0;
-}
-
-void QApplicationPrivate::notifyActiveWindowChange(QWindow *previous)
-{
- Q_UNUSED(previous);
- QWindow *wnd = QGuiApplicationPrivate::focus_window;
- if (inPopupMode()) // some delayed focus event to ignore
- return;
- QWidget *tlw = qt_tlw_for_window(wnd);
- QApplication::setActiveWindow(tlw);
-}
-
-static void ungrabKeyboardForPopup(QWidget *popup)
-{
- if (QWidget::keyboardGrabber())
- qt_widget_private(QWidget::keyboardGrabber())->stealKeyboardGrab(true);
- else
- qt_widget_private(popup)->stealKeyboardGrab(false);
-}
-
-static void ungrabMouseForPopup(QWidget *popup)
-{
- if (QWidget::mouseGrabber())
- qt_widget_private(QWidget::mouseGrabber())->stealMouseGrab(true);
- else
- qt_widget_private(popup)->stealMouseGrab(false);
-}
-
-static void grabForPopup(QWidget *popup)
-{
- Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
- popupGrabOk = qt_widget_private(popup)->stealKeyboardGrab(true);
- if (popupGrabOk) {
- popupGrabOk = qt_widget_private(popup)->stealMouseGrab(true);
- if (!popupGrabOk) {
- // transfer grab back to the keyboard grabber if any
- ungrabKeyboardForPopup(popup);
- }
- }
-}
-
-void QApplicationPrivate::closePopup(QWidget *popup)
-{
- if (!popupWidgets)
- return;
- popupWidgets->removeAll(popup);
-
- if (popup == qt_popup_down) {
- qt_button_down = 0;
- qt_popup_down = 0;
- }
-
- if (QApplicationPrivate::popupWidgets->count() == 0) { // this was the last popup
- delete QApplicationPrivate::popupWidgets;
- QApplicationPrivate::popupWidgets = 0;
-
- if (popupGrabOk) {
- popupGrabOk = false;
-
- if (popup->geometry().contains(QPoint(QGuiApplicationPrivate::mousePressX,
- QGuiApplicationPrivate::mousePressY))
- || popup->testAttribute(Qt::WA_NoMouseReplay)) {
- // mouse release event or inside
- qt_replay_popup_mouse_event = false;
- } else { // mouse press event
- qt_replay_popup_mouse_event = true;
- }
-
- // transfer grab back to mouse grabber if any, otherwise release the grab
- ungrabMouseForPopup(popup);
-
- // transfer grab back to keyboard grabber if any, otherwise release the grab
- ungrabKeyboardForPopup(popup);
- }
-
- if (active_window) {
- if (QWidget *fw = active_window->focusWidget()) {
- if (fw != QApplication::focusWidget()) {
- fw->setFocus(Qt::PopupFocusReason);
- } else {
- QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
- QCoreApplication::sendEvent(fw, &e);
- }
- }
- }
-
- } else {
- // A popup was closed, so the previous popup gets the focus.
- QWidget* aw = QApplicationPrivate::popupWidgets->last();
- if (QWidget *fw = aw->focusWidget())
- fw->setFocus(Qt::PopupFocusReason);
-
- if (QApplicationPrivate::popupWidgets->count() == 1) // grab mouse/keyboard
- grabForPopup(aw);
- }
-
-}
-
-void QApplicationPrivate::openPopup(QWidget *popup)
-{
- openPopupCount++;
- if (!popupWidgets) // create list
- popupWidgets = new QWidgetList;
- popupWidgets->append(popup); // add to end of list
-
- if (QApplicationPrivate::popupWidgets->count() == 1) // grab mouse/keyboard
- grabForPopup(popup);
-
- // popups are not focus-handled by the window system (the first
- // popup grabbed the keyboard), so we have to do that manually: A
- // new popup gets the focus
- if (popup->focusWidget()) {
- popup->focusWidget()->setFocus(Qt::PopupFocusReason);
- } else if (popupWidgets->count() == 1) { // this was the first popup
- if (QWidget *fw = QApplication::focusWidget()) {
- QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
- QApplication::sendEvent(fw, &e);
- }
- }
-}
-
-void QApplicationPrivate::initializeMultitouch_sys()
-{
-}
-
-void QApplicationPrivate::cleanupMultitouch_sys()
-{
-}
-
-static void setPossiblePalette(const QPalette *palette, const char *className)
-{
- if (palette == 0)
- return;
- QApplicationPrivate::setPalette_helper(*palette, className, false);
-}
-
-
-void QApplicationPrivate::initializeWidgetPaletteHash()
-{
- QPlatformTheme *platformTheme = QGuiApplicationPrivate::platformTheme();
- if (!platformTheme)
- return;
- qt_app_palettes_hash()->clear();
-
- setPossiblePalette(platformTheme->palette(QPlatformTheme::ToolButtonPalette), "QToolButton");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::ButtonPalette), "QAbstractButton");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::CheckBoxPalette), "QCheckBox");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::RadioButtonPalette), "QRadioButton");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::HeaderPalette), "QHeaderView");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::ItemViewPalette), "QAbstractItemView");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::MessageBoxLabelPalette), "QMessageBoxLabel");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::TabBarPalette), "QTabBar");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::LabelPalette), "QLabel");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::GroupBoxPalette), "QGroupBox");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::MenuPalette), "QMenu");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::MenuBarPalette), "QMenuBar");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::TextEditPalette), "QTextEdit");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::TextEditPalette), "QTextControl");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::TextLineEditPalette), "QLineEdit");
-}
-
-void QApplicationPrivate::initializeWidgetFontHash()
-{
- const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
- if (!theme)
- return;
- FontHash *fontHash = qt_app_fonts_hash();
- fontHash->clear();
-
- if (const QFont *font = theme->font(QPlatformTheme::MenuFont))
- fontHash->insert(QByteArrayLiteral("QMenu"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::MenuBarFont))
- fontHash->insert(QByteArrayLiteral("QMenuBar"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::MenuItemFont))
- fontHash->insert(QByteArrayLiteral("QMenuItem"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::MessageBoxFont))
- fontHash->insert(QByteArrayLiteral("QMessageBox"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::LabelFont))
- fontHash->insert(QByteArrayLiteral("QLabel"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::TipLabelFont))
- fontHash->insert(QByteArrayLiteral("QTipLabel"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::TitleBarFont))
- fontHash->insert(QByteArrayLiteral("QTitleBar"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::StatusBarFont))
- fontHash->insert(QByteArrayLiteral("QStatusBar"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::MdiSubWindowTitleFont))
- fontHash->insert(QByteArrayLiteral("QMdiSubWindowTitleBar"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::DockWidgetTitleFont))
- fontHash->insert(QByteArrayLiteral("QDockWidgetTitle"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::PushButtonFont))
- fontHash->insert(QByteArrayLiteral("QPushButton"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::CheckBoxFont))
- fontHash->insert(QByteArrayLiteral("QCheckBox"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::RadioButtonFont))
- fontHash->insert(QByteArrayLiteral("QRadioButton"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::ToolButtonFont))
- fontHash->insert(QByteArrayLiteral("QToolButton"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::ItemViewFont))
- fontHash->insert(QByteArrayLiteral("QAbstractItemView"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::ListViewFont))
- fontHash->insert(QByteArrayLiteral("QListViewFont"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::HeaderViewFont))
- fontHash->insert(QByteArrayLiteral("QHeaderViewFont"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::ListBoxFont))
- fontHash->insert(QByteArrayLiteral("QListBox"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::ComboMenuItemFont))
- fontHash->insert(QByteArrayLiteral("QComboMenuItemFont"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::ComboLineEditFont))
- fontHash->insert(QByteArrayLiteral("QComboLineEditFont"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::SmallFont))
- fontHash->insert(QByteArrayLiteral("QSmallFont"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::MiniFont))
- fontHash->insert(QByteArrayLiteral("QMiniFont"), *font);
-}
-
-#ifndef QT_NO_WHEELEVENT
-void QApplication::setWheelScrollLines(int lines)
-{
- QApplicationPrivate::wheel_scroll_lines = lines;
-}
-
-int QApplication::wheelScrollLines()
-{
- return QApplicationPrivate::wheel_scroll_lines;
-}
-#endif
-
-static inline int uiEffectToFlag(Qt::UIEffect effect)
-{
- switch (effect) {
- case Qt::UI_General:
- return QPlatformTheme::GeneralUiEffect;
- case Qt::UI_AnimateMenu:
- return QPlatformTheme::AnimateMenuUiEffect;
- case Qt::UI_FadeMenu:
- return QPlatformTheme::FadeMenuUiEffect;
- case Qt::UI_AnimateCombo:
- return QPlatformTheme::AnimateComboUiEffect;
- case Qt::UI_AnimateTooltip:
- return QPlatformTheme::AnimateTooltipUiEffect;
- case Qt::UI_FadeTooltip:
- return QPlatformTheme::FadeTooltipUiEffect;
- case Qt::UI_AnimateToolBox:
- return QPlatformTheme::AnimateToolBoxUiEffect;
- }
- return 0;
-}
-
-void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
-{
- int effectFlags = uiEffectToFlag(effect);
- if (enable) {
- if (effectFlags & QPlatformTheme::FadeMenuUiEffect)
- effectFlags |= QPlatformTheme::AnimateMenuUiEffect;
- if (effectFlags & QPlatformTheme::FadeTooltipUiEffect)
- effectFlags |= QPlatformTheme::AnimateTooltipUiEffect;
- QApplicationPrivate::enabledAnimations |= effectFlags;
- } else {
- QApplicationPrivate::enabledAnimations &= ~effectFlags;
- }
-}
-
-bool QApplication::isEffectEnabled(Qt::UIEffect effect)
-{
- return QColormap::instance().depth() >= 16
- && (QApplicationPrivate::enabledAnimations & QPlatformTheme::GeneralUiEffect)
- && (QApplicationPrivate::enabledAnimations & uiEffectToFlag(effect));
-}
-
-QWidget *QApplication::topLevelAt(const QPoint &pos)
-{
- QList<QScreen *> screens = QGuiApplication::screens();
- QList<QScreen *>::const_iterator screen = screens.constBegin();
- QList<QScreen *>::const_iterator end = screens.constEnd();
-
- while (screen != end) {
- if ((*screen)->geometry().contains(pos)) {
- QWidgetWindow *w = qobject_cast<QWidgetWindow *>((*screen)->handle()->topLevelAt(pos));
- return w ? w->widget() : 0;
- }
- ++screen;
- }
- return 0;
-}
-
-void QApplication::beep()
-{
- QMetaObject::invokeMethod(QGuiApplication::platformNativeInterface(), "beep");
-}
-
-void QApplication::alert(QWidget *widget, int duration)
-{
- if (widget) {
- if (widget->window()->isActiveWindow() && !(widget->window()->windowState() & Qt::WindowMinimized))
- return;
- if (QWindow *window= QApplicationPrivate::windowForWidget(widget))
- window->alert(duration);
- } else {
- foreach (QWidget *topLevel, topLevelWidgets())
- QApplication::alert(topLevel, duration);
- }
-}
-
-void qt_init_tooltip_palette()
-{
-#ifndef QT_NO_TOOLTIP
- if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::ToolTipPalette))
- QToolTip::setPalette(*toolTipPalette);
-#endif
-}
-
-void qt_init(QApplicationPrivate *priv, int type)
-{
- Q_UNUSED(priv);
- Q_UNUSED(type);
-
- QColormap::initialize();
-
- qt_init_tooltip_palette();
-
- QApplicationPrivate::initializeWidgetFontHash();
-}
-
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
-// #fixme: Remove.
-static HDC displayDC = 0; // display device context
-
-Q_WIDGETS_EXPORT HDC qt_win_display_dc() // get display DC
-{
- Q_ASSERT(qApp && qApp->thread() == QThread::currentThread());
- if (!displayDC)
- displayDC = GetDC(0);
- return displayDC;
-}
-#endif
-
-void qt_cleanup()
-{
- QPixmapCache::clear();
- QColormap::cleanup();
-
- QApplicationPrivate::active_window = 0; //### this should not be necessary
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
- if (displayDC) {
- ReleaseDC(0, displayDC);
- displayDC = 0;
- }
-#endif
-}
-
-
-QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qdesktopwidget.cpp b/src/widgets/kernel/qdesktopwidget.cpp
index 649978a912..3975e423a0 100644
--- a/src/widgets/kernel/qdesktopwidget.cpp
+++ b/src/widgets/kernel/qdesktopwidget.cpp
@@ -41,6 +41,8 @@
#include "qglobal.h"
#include "qdesktopwidget.h"
+#include "qdesktopwidget_p.h"
+#include "qscreen.h"
#include "qwidget_p.h"
QT_BEGIN_NAMESPACE
@@ -72,5 +74,145 @@ const QRect QDesktopWidget::availableGeometry(const QWidget *widget) const
return rect;
}
+void QDesktopWidgetPrivate::_q_updateScreens()
+{
+ Q_Q(QDesktopWidget);
+ const QList<QScreen *> screenList = QGuiApplication::screens();
+ const int targetLength = screenList.length();
+ const int oldLength = screens.length();
+ int currentLength = oldLength;
+
+ // Add or remove screen widgets as necessary
+ if(currentLength > targetLength) {
+ QDesktopScreenWidget *screen;
+ while (currentLength-- > targetLength) {
+ screen = screens.takeLast();
+ delete screen;
+ }
+ }
+ else if (currentLength < targetLength) {
+ while (currentLength < targetLength) {
+ QScreen *qScreen = screenList.at(currentLength);
+ QDesktopScreenWidget *screenWidget = new QDesktopScreenWidget(currentLength++);
+ screenWidget->setGeometry(qScreen->geometry());
+ QObject::connect(qScreen, SIGNAL(geometryChanged(QRect)),
+ q, SLOT(_q_updateScreens()), Qt::QueuedConnection);
+ QObject::connect(qScreen, SIGNAL(destroyed()),
+ q, SLOT(_q_updateScreens()), Qt::QueuedConnection);
+ screens.append(screenWidget);
+ }
+ }
+
+ QRegion virtualGeometry;
+
+ // update the geometry of each screen widget, determine virtual geometry
+ // and emit change signals afterwards.
+ QList<int> changedScreens;
+ for (int i = 0; i < screens.length(); i++) {
+ const QRect screenGeometry = screenList.at(i)->geometry();
+ if (screenGeometry != screens.at(i)->geometry()) {
+ screens.at(i)->setGeometry(screenGeometry);
+ changedScreens.push_back(i);
+ }
+ virtualGeometry += screenGeometry;
+ }
+
+ q->setGeometry(virtualGeometry.boundingRect());
+
+ if (oldLength != targetLength)
+ emit q->screenCountChanged(targetLength);
+
+ foreach (int changedScreen, changedScreens) {
+ emit q->resized(changedScreen);
+ emit q->workAreaResized(changedScreen);
+ }
+}
+
+QDesktopWidget::QDesktopWidget()
+ : QWidget(*new QDesktopWidgetPrivate, 0, Qt::Desktop)
+{
+ Q_D(QDesktopWidget);
+ setObjectName(QLatin1String("desktop"));
+ d->_q_updateScreens();
+ connect(qApp, SIGNAL(screenAdded(QScreen*)), this, SLOT(_q_updateScreens()));
+}
+
+QDesktopWidget::~QDesktopWidget()
+{
+}
+
+bool QDesktopWidget::isVirtualDesktop() const
+{
+ return QGuiApplication::primaryScreen()->virtualSiblings().size() > 1;
+}
+
+int QDesktopWidget::primaryScreen() const
+{
+ return 0;
+}
+
+int QDesktopWidget::numScreens() const
+{
+ return qMax(QGuiApplication::screens().size(), 1);
+}
+
+QWidget *QDesktopWidget::screen(int screen)
+{
+ Q_D(QDesktopWidget);
+ if (screen < 0 || screen >= d->screens.length())
+ return d->screens.at(0);
+ return d->screens.at(screen);
+}
+
+const QRect QDesktopWidget::availableGeometry(int screenNo) const
+{
+ QList<QScreen *> screens = QGuiApplication::screens();
+ if (screenNo == -1)
+ screenNo = 0;
+ if (screenNo < 0 || screenNo >= screens.size())
+ return QRect();
+ else
+ return screens.at(screenNo)->availableGeometry();
+}
+
+const QRect QDesktopWidget::screenGeometry(int screenNo) const
+{
+ QList<QScreen *> screens = QGuiApplication::screens();
+ if (screenNo == -1)
+ screenNo = 0;
+ if (screenNo < 0 || screenNo >= screens.size())
+ return QRect();
+ else
+ return screens.at(screenNo)->geometry();
+}
+
+int QDesktopWidget::screenNumber(const QWidget *w) const
+{
+ if (!w)
+ return 0;
+
+ QRect frame = w->frameGeometry();
+ if (!w->isWindow())
+ frame.moveTopLeft(w->mapToGlobal(QPoint(0, 0)));
+ const QPoint midpoint = (frame.topLeft() + frame.bottomRight()) / 2;
+ return screenNumber(midpoint);
+}
+
+int QDesktopWidget::screenNumber(const QPoint &p) const
+{
+ QList<QScreen *> screens = QGuiApplication::screens();
+
+ for (int i = 0; i < screens.size(); ++i)
+ if (screens.at(i)->geometry().contains(p))
+ return i;
+
+ return primaryScreen(); //even better would be closest screen
+}
+
+void QDesktopWidget::resizeEvent(QResizeEvent *)
+{
+}
+
QT_END_NAMESPACE
+#include "moc_qdesktopwidget.cpp"
diff --git a/src/widgets/kernel/qdesktopwidget_qpa_p.h b/src/widgets/kernel/qdesktopwidget_p.h
index f461869f1b..160807cf23 100644
--- a/src/widgets/kernel/qdesktopwidget_qpa_p.h
+++ b/src/widgets/kernel/qdesktopwidget_p.h
@@ -50,8 +50,8 @@
// We mean it.
//
-#ifndef QDESKTOPWIDGET_QPA_P_H
-#define QDESKTOPWIDGET_QPA_P_H
+#ifndef QDESKTOPWIDGET_P_H
+#define QDESKTOPWIDGET_P_H
#include "QDesktopWidget"
#include "private/qwidget_p.h"
diff --git a/src/widgets/kernel/qdesktopwidget_qpa.cpp b/src/widgets/kernel/qdesktopwidget_qpa.cpp
deleted file mode 100644
index 015573dfbe..0000000000
--- a/src/widgets/kernel/qdesktopwidget_qpa.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qdesktopwidget.h"
-#include "qscreen.h"
-#include "private/qapplication_p.h"
-#include <QWidget>
-#include "private/qwidget_p.h"
-#include "private/qdesktopwidget_qpa_p.h"
-QT_BEGIN_NAMESPACE
-
-QT_USE_NAMESPACE
-
-void QDesktopWidgetPrivate::_q_updateScreens()
-{
- Q_Q(QDesktopWidget);
- const QList<QScreen *> screenList = QGuiApplication::screens();
- const int targetLength = screenList.length();
- const int oldLength = screens.length();
- int currentLength = oldLength;
-
- // Add or remove screen widgets as necessary
- if(currentLength > targetLength) {
- QDesktopScreenWidget *screen;
- while (currentLength-- > targetLength) {
- screen = screens.takeLast();
- delete screen;
- }
- }
- else if (currentLength < targetLength) {
- while (currentLength < targetLength) {
- QScreen *qScreen = screenList.at(currentLength);
- QDesktopScreenWidget *screenWidget = new QDesktopScreenWidget(currentLength++);
- screenWidget->setGeometry(qScreen->geometry());
- QObject::connect(qScreen, SIGNAL(geometryChanged(QRect)),
- q, SLOT(_q_updateScreens()), Qt::QueuedConnection);
- QObject::connect(qScreen, SIGNAL(destroyed()),
- q, SLOT(_q_updateScreens()), Qt::QueuedConnection);
- screens.append(screenWidget);
- }
- }
-
- QRegion virtualGeometry;
-
- // update the geometry of each screen widget, determine virtual geometry
- // and emit change signals afterwards.
- QList<int> changedScreens;
- for (int i = 0; i < screens.length(); i++) {
- const QRect screenGeometry = screenList.at(i)->geometry();
- if (screenGeometry != screens.at(i)->geometry()) {
- screens.at(i)->setGeometry(screenGeometry);
- changedScreens.push_back(i);
- }
- virtualGeometry += screenGeometry;
- }
-
- q->setGeometry(virtualGeometry.boundingRect());
-
- if (oldLength != targetLength)
- emit q->screenCountChanged(targetLength);
-
- foreach (int changedScreen, changedScreens) {
- emit q->resized(changedScreen);
- emit q->workAreaResized(changedScreen);
- }
-}
-
-QDesktopWidget::QDesktopWidget()
- : QWidget(*new QDesktopWidgetPrivate, 0, Qt::Desktop)
-{
- Q_D(QDesktopWidget);
- setObjectName(QLatin1String("desktop"));
- d->_q_updateScreens();
- connect(qApp, SIGNAL(screenAdded(QScreen*)), this, SLOT(_q_updateScreens()));
-}
-
-QDesktopWidget::~QDesktopWidget()
-{
-}
-
-bool QDesktopWidget::isVirtualDesktop() const
-{
- return QGuiApplication::primaryScreen()->virtualSiblings().size() > 1;
-}
-
-int QDesktopWidget::primaryScreen() const
-{
- return 0;
-}
-
-int QDesktopWidget::numScreens() const
-{
- return qMax(QGuiApplication::screens().size(), 1);
-}
-
-QWidget *QDesktopWidget::screen(int screen)
-{
- Q_D(QDesktopWidget);
- if (screen < 0 || screen >= d->screens.length())
- return d->screens.at(0);
- return d->screens.at(screen);
-}
-
-const QRect QDesktopWidget::availableGeometry(int screenNo) const
-{
- QList<QScreen *> screens = QGuiApplication::screens();
- if (screenNo == -1)
- screenNo = 0;
- if (screenNo < 0 || screenNo >= screens.size())
- return QRect();
- else
- return screens.at(screenNo)->availableGeometry();
-}
-
-const QRect QDesktopWidget::screenGeometry(int screenNo) const
-{
- QList<QScreen *> screens = QGuiApplication::screens();
- if (screenNo == -1)
- screenNo = 0;
- if (screenNo < 0 || screenNo >= screens.size())
- return QRect();
- else
- return screens.at(screenNo)->geometry();
-}
-
-int QDesktopWidget::screenNumber(const QWidget *w) const
-{
- if (!w)
- return 0;
-
- QRect frame = w->frameGeometry();
- if (!w->isWindow())
- frame.moveTopLeft(w->mapToGlobal(QPoint(0, 0)));
- const QPoint midpoint = (frame.topLeft() + frame.bottomRight()) / 2;
- return screenNumber(midpoint);
-}
-
-int QDesktopWidget::screenNumber(const QPoint &p) const
-{
- QList<QScreen *> screens = QGuiApplication::screens();
-
- for (int i = 0; i < screens.size(); ++i)
- if (screens.at(i)->geometry().contains(p))
- return i;
-
- return primaryScreen(); //even better would be closest screen
-}
-
-void QDesktopWidget::resizeEvent(QResizeEvent *)
-{
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qdesktopwidget.cpp"
diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp
index 929e5e2fcf..532cea1f67 100644
--- a/src/widgets/kernel/qgesturemanager.cpp
+++ b/src/widgets/kernel/qgesturemanager.cpp
@@ -46,7 +46,7 @@
#include "private/qgraphicsitem_p.h"
#include "private/qevent_p.h"
#include "private/qapplication_p.h"
-#include "private/qwidgetwindow_qpa_p.h"
+#include "private/qwidgetwindow_p.h"
#include "qgesture.h"
#include "qevent.h"
#include "qgraphicsitem.h"
diff --git a/src/widgets/kernel/qshortcut.cpp b/src/widgets/kernel/qshortcut.cpp
index dcf6aed591..217f0386cb 100644
--- a/src/widgets/kernel/qshortcut.cpp
+++ b/src/widgets/kernel/qshortcut.cpp
@@ -51,7 +51,7 @@
#include <private/qapplication_p.h>
#include <private/qshortcutmap_p.h>
#include <private/qaction_p.h>
-#include <private/qwidgetwindow_qpa_p.h>
+#include <private/qwidgetwindow_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 7396808442..e692a985eb 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -69,7 +69,7 @@
# include <private/qmainwindowlayout_p.h>
#endif
#include <qpa/qplatformwindow.h>
-#include "private/qwidgetwindow_qpa_p.h"
+#include "private/qwidgetwindow_p.h"
#include "qpainter.h"
#include "qtooltip.h"
#include "qwhatsthis.h"
@@ -357,6 +357,13 @@ void QWidgetPrivate::scrollChildren(int dx, int dy)
}
}
+void QWidgetPrivate::setWSGeometry()
+{
+ Q_Q(QWidget);
+ if (QWindow *window = q->windowHandle())
+ window->setGeometry(data.crect);
+}
+
void QWidgetPrivate::updateWidgetTransform(QEvent *event)
{
Q_Q(QWidget);
@@ -1065,7 +1072,11 @@ void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
// interpret WindowSystemMenuHint as a close button and we can't change that behavior
// we can't just add this in.
#ifndef Q_WS_MAC
- if (flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint)) {
+ if ((flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint))
+# ifdef Q_OS_WIN
+ && type != Qt::Dialog // QTBUG-2027, allow for menu-less dialogs.
+# endif
+ ) {
flags |= Qt::WindowSystemMenuHint;
#else
if (flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint
@@ -1348,6 +1359,155 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
d->updateFrameStrut();
}
+void q_createNativeChildrenAndSetParent(const QWidget *parentWidget)
+{
+ QObjectList children = parentWidget->children();
+ for (int i = 0; i < children.size(); i++) {
+ if (children.at(i)->isWidgetType()) {
+ const QWidget *childWidget = qobject_cast<const QWidget *>(children.at(i));
+ if (childWidget) { // should not be necessary
+ if (childWidget->testAttribute(Qt::WA_NativeWindow)) {
+ if (!childWidget->internalWinId())
+ childWidget->winId();
+ if (childWidget->windowHandle()) {
+ QWindow *parentWindow = childWidget->nativeParentWidget()->windowHandle();
+ if (childWidget->isWindow())
+ childWidget->windowHandle()->setTransientParent(parentWindow);
+ else
+ childWidget->windowHandle()->setParent(parentWindow);
+ }
+ } else {
+ q_createNativeChildrenAndSetParent(childWidget);
+ }
+ }
+ }
+ }
+
+}
+
+void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
+{
+ Q_Q(QWidget);
+
+ Q_UNUSED(window);
+ Q_UNUSED(initializeWindow);
+ Q_UNUSED(destroyOldWindow);
+
+ Qt::WindowFlags flags = data.window_flags;
+
+ if (!q->testAttribute(Qt::WA_NativeWindow) && !q->isWindow())
+ return; // we only care about real toplevels
+
+ QWindow *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) {
+ createTLSysExtra();
+ win = topData()->window;
+ }
+
+ foreach (const QByteArray &propertyName, q->dynamicPropertyNames()) {
+ if (!qstrncmp(propertyName, "_q_platform_", 12))
+ win->setProperty(propertyName, q->property(propertyName));
+ }
+
+#ifdef Q_OS_OSX
+ if (q->testAttribute(Qt::WA_ShowWithoutActivating))
+ win->setProperty("_q_showWithoutActivating", QVariant(true));
+#endif
+ win->setFlags(data.window_flags);
+ fixPosIncludesFrame();
+ if (q->testAttribute(Qt::WA_Moved)
+ || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
+ win->setGeometry(q->geometry());
+ else
+ win->resize(q->size());
+ if (win->isTopLevel())
+ win->setScreen(QGuiApplication::screens().value(topData()->screenIndex, 0));
+
+ QSurfaceFormat format = win->requestedFormat();
+ if ((flags & Qt::Window) && win->surfaceType() != QSurface::OpenGLSurface
+ && q->testAttribute(Qt::WA_TranslucentBackground)) {
+ format.setAlphaBufferSize(8);
+ }
+ win->setFormat(format);
+
+ if (QWidget *nativeParent = q->nativeParentWidget()) {
+ if (nativeParent->windowHandle()) {
+ if (flags & Qt::Window) {
+ win->setTransientParent(nativeParent->window()->windowHandle());
+ win->setParent(0);
+ } else {
+ win->setTransientParent(0);
+ win->setParent(nativeParent->windowHandle());
+ }
+ }
+ }
+
+ qt_window_private(win)->positionPolicy = topData()->posIncludesFrame ?
+ QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive;
+ win->create();
+ // Enable nonclient-area events for QDockWidget and other NonClientArea-mouse event processing.
+ if ((flags & Qt::Desktop) == Qt::Window)
+ win->handle()->setFrameStrutEventsEnabled(true);
+
+ data.window_flags = win->flags();
+
+ QBackingStore *store = q->backingStore();
+
+ if (!store) {
+ if (win && q->windowType() != Qt::Desktop) {
+ if (q->isTopLevel())
+ q->setBackingStore(new QBackingStore(win));
+ } else {
+ q->setAttribute(Qt::WA_PaintOnScreen, true);
+ }
+ }
+
+ setWindowModified_helper();
+ WId id = win->winId();
+ // See the QPlatformWindow::winId() documentation
+ Q_ASSERT(id != WId(0));
+ setWinId(id);
+
+ // Check children and create windows for them if necessary
+ q_createNativeChildrenAndSetParent(q);
+
+ if (extra && !extra->mask.isEmpty())
+ setMask_sys(extra->mask);
+
+ // If widget is already shown, set window visible, too
+ if (q->isVisible())
+ win->setVisible(true);
+}
+
+#ifdef Q_OS_WIN
+static const char activeXNativeParentHandleProperty[] = "_q_embedded_native_parent_handle";
+#endif
+
+void QWidgetPrivate::createTLSysExtra()
+{
+ Q_Q(QWidget);
+ if (!extra->topextra->window && (q->testAttribute(Qt::WA_NativeWindow) || q->isWindow())) {
+ extra->topextra->window = new QWidgetWindow(q);
+ if (extra->minw || extra->minh)
+ extra->topextra->window->setMinimumSize(QSize(extra->minw, extra->minh));
+ if (extra->maxw != QWIDGETSIZE_MAX || extra->maxh != QWIDGETSIZE_MAX)
+ extra->topextra->window->setMaximumSize(QSize(extra->maxw, extra->maxh));
+ if (extra->topextra->opacity != 255 && q->isWindow())
+ extra->topextra->window->setOpacity(qreal(extra->topextra->opacity) / qreal(255));
+#ifdef Q_OS_WIN
+ // Pass on native parent handle for Widget embedded into Active X.
+ const QVariant activeXNativeParentHandle = q->property(activeXNativeParentHandleProperty);
+ if (activeXNativeParentHandle.isValid())
+ extra->topextra->window->setProperty(activeXNativeParentHandleProperty, activeXNativeParentHandle);
+ if (q->inherits("QTipLabel") || q->inherits("QAlphaWidget"))
+ extra->topextra->window->setProperty("_q_windowsDropShadow", QVariant(true));
+#endif
+ }
+
+}
+
/*!
Destroys the widget.
@@ -1612,6 +1772,9 @@ void QWidgetPrivate::createExtra()
}
}
+void QWidgetPrivate::createSysExtra()
+{
+}
/*!
\internal
@@ -1642,6 +1805,46 @@ void QWidgetPrivate::deleteExtra()
}
}
+void QWidgetPrivate::deleteSysExtra()
+{
+}
+
+void QWidgetPrivate::deleteTLSysExtra()
+{
+ if (extra && extra->topextra) {
+ //the qplatformbackingstore may hold a reference to the window, so the backingstore
+ //needs to be deleted first. If the backingstore holds GL resources, we need to
+ // make the context current here, since the platform bs does not have a reference
+ // to the widget.
+
+#ifndef QT_NO_OPENGL
+ if (textureChildSeen && extra->topextra->shareContext)
+ extra->topextra->shareContext->makeCurrent(extra->topextra->window);
+#endif
+ extra->topextra->backingStoreTracker.destroy();
+ delete extra->topextra->backingStore;
+ extra->topextra->backingStore = 0;
+#ifndef QT_NO_OPENGL
+ if (textureChildSeen && extra->topextra->shareContext)
+ extra->topextra->shareContext->doneCurrent();
+ delete extra->topextra->shareContext;
+ extra->topextra->shareContext = 0;
+#endif
+
+ //the toplevel might have a context with a "qglcontext associated with it. We need to
+ //delete the qglcontext before we delete the qplatformopenglcontext.
+ //One unfortunate thing about this is that we potentially create a glContext just to
+ //delete it straight afterwards.
+ if (extra->topextra->window) {
+ extra->topextra->window->destroy();
+ }
+ setWinId(0);
+ delete extra->topextra->window;
+ extra->topextra->window = 0;
+
+ }
+}
+
/*
Returns \c true if there are widgets above this which overlap with
\a rect, which is in parent's coordinate system (same as crect).
@@ -2364,6 +2567,27 @@ WId QWidget::effectiveWinId() const
return 0;
}
+/*!
+ If this is a native widget, return the associated QWindow.
+ Otherwise return null.
+
+ Native widgets include toplevel widgets, QGLWidget, and child widgets
+ on which winId() was called.
+
+ \since 5.0
+
+ \sa winId()
+*/
+QWindow *QWidget::windowHandle() const
+{
+ Q_D(const QWidget);
+ QTLWExtra *extra = d->maybeTopData();
+ if (extra)
+ return extra->window;
+
+ return 0;
+}
+
#ifndef QT_NO_STYLE_STYLESHEET
/*!
@@ -2654,6 +2878,13 @@ void QWidget::setWindowModality(Qt::WindowModality windowModality)
setAttribute(Qt::WA_SetWindowModality, true);
}
+void QWidgetPrivate::setModal_sys()
+{
+ Q_Q(QWidget);
+ if (q->windowHandle())
+ q->windowHandle()->setModality(q->windowModality());
+}
+
/*!
\fn bool QWidget::underMouse() const
@@ -2747,6 +2978,17 @@ 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)
@@ -2777,6 +3019,39 @@ void QWidget::overrideWindowState(Qt::WindowStates newstate)
\sa Qt::WindowState, windowState()
*/
+void QWidget::setWindowState(Qt::WindowStates newstate)
+{
+ Q_D(QWidget);
+ Qt::WindowStates oldstate = windowState();
+ if (oldstate == newstate)
+ return;
+ if (isWindow() && !testAttribute(Qt::WA_WState_Created))
+ create();
+
+ data->window_state = newstate;
+ data->in_set_window_state = 1;
+ Qt::WindowState newEffectiveState = effectiveState(newstate);
+ Qt::WindowState oldEffectiveState = effectiveState(oldstate);
+ if (isWindow() && newEffectiveState != oldEffectiveState) {
+ // 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)
+ d->topData()->normalGeometry = geometry();
+
+ Q_ASSERT(windowHandle());
+ windowHandle()->setWindowState(newEffectiveState);
+ }
+ data->in_set_window_state = 0;
+
+ if (newstate & Qt::WindowActive)
+ activateWindow();
+
+ QWindowStateChangeEvent e(oldstate);
+ QApplication::sendEvent(this, &e);
+}
/*!
\property QWidget::fullScreen
@@ -3169,6 +3444,10 @@ void QWidget::setAcceptDrops(bool on)
}
+void QWidgetPrivate::registerDropSite(bool on)
+{
+ Q_UNUSED(on);
+}
/*!
Disables widget input events if \a disable is true; otherwise
@@ -3643,6 +3922,28 @@ bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
return true;
}
+void QWidgetPrivate::setConstraints_sys()
+{
+ Q_Q(QWidget);
+ if (extra && q->windowHandle()) {
+ QWindow *win = q->windowHandle();
+ QWindowPrivate *winp = qt_window_private(win);
+
+ winp->minimumSize = QSize(extra->minw, extra->minh);
+ winp->maximumSize = QSize(extra->maxw, extra->maxh);
+
+ if (extra->topextra) {
+ winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh);
+ winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
+ }
+
+ if (winp->platformWindow) {
+ fixPosIncludesFrame();
+ winp->platformWindow->propagateSizeHints();
+ }
+ }
+}
+
/*!
\overload
@@ -4293,6 +4594,10 @@ void QWidgetPrivate::setPalette_helper(const QPalette &palette)
updateIsOpaque();
}
+void QWidgetPrivate::updateSystemBackground()
+{
+}
+
/*!
\property QWidget::font
\brief the font currently set for the widget
@@ -4629,6 +4934,13 @@ void QWidget::setCursor(const QCursor &cursor)
QApplication::sendEvent(this, &event);
}
+void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
+{
+ Q_UNUSED(cursor);
+ Q_Q(QWidget);
+ qt_qpa_set_cursor(q, false);
+}
+
void QWidget::unsetCursor()
{
Q_D(QWidget);
@@ -4644,6 +4956,62 @@ void QWidget::unsetCursor()
QApplication::sendEvent(this, &event);
}
+void QWidgetPrivate::unsetCursor_sys()
+{
+ Q_Q(QWidget);
+ qt_qpa_set_cursor(q, false);
+}
+
+static inline void applyCursor(QWidget *w, QCursor c)
+{
+ if (QWindow *window = w->windowHandle())
+ window->setCursor(c);
+}
+
+static inline void unsetCursor(QWidget *w)
+{
+ if (QWindow *window = w->windowHandle())
+ window->unsetCursor();
+}
+
+void qt_qpa_set_cursor(QWidget *w, bool force)
+{
+ if (!w->testAttribute(Qt::WA_WState_Created))
+ return;
+
+ static QPointer<QWidget> lastUnderMouse = 0;
+ if (force) {
+ lastUnderMouse = w;
+ } else if (lastUnderMouse) {
+ const WId lastWinId = lastUnderMouse->effectiveWinId();
+ const WId winId = w->effectiveWinId();
+ if (lastWinId && lastWinId == winId)
+ w = lastUnderMouse;
+ } else if (!w->internalWinId()) {
+ return; // The mouse is not under this widget, and it's not native, so don't change it.
+ }
+
+ while (!w->internalWinId() && w->parentWidget() && !w->isWindow()
+ && !w->testAttribute(Qt::WA_SetCursor))
+ w = w->parentWidget();
+
+ QWidget *nativeParent = w;
+ if (!w->internalWinId())
+ nativeParent = w->nativeParentWidget();
+ if (!nativeParent || !nativeParent->internalWinId())
+ return;
+
+ if (w->isWindow() || w->testAttribute(Qt::WA_SetCursor)) {
+ if (w->isEnabled())
+ applyCursor(nativeParent, w->cursor());
+ else
+ // Enforce the windows behavior of clearing the cursor on
+ // disabled widgets.
+ unsetCursor(nativeParent);
+ } else {
+ unsetCursor(nativeParent);
+ }
+}
#endif
/*!
@@ -5148,9 +5516,17 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
if (renderToTexture) {
// This widget renders into a texture which is composed later. We just need to
// punch a hole in the backingstore, so the texture will be visible.
+#ifndef QT_NO_OPENGL
QPainter p(q);
- p.setCompositionMode(QPainter::CompositionMode_Source);
- p.fillRect(q->rect(), Qt::transparent);
+
+ if (backingStore) {
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.fillRect(q->rect(), Qt::transparent);
+ } else {
+ // We are not drawing to a backingstore: fall back to QImage
+ p.drawImage(q->rect(), grabFramebuffer());
+ }
+#endif
} else {
//actually send the paint event
QPaintEvent e(toBePainted);
@@ -5604,6 +5980,17 @@ void QWidgetPrivate::setWindowTitle_helper(const QString &title)
setWindowTitle_sys(qt_setWindowTitle_helperHelper(title, q));
}
+void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
+{
+ Q_Q(QWidget);
+ if (!q->isWindow())
+ return;
+
+ if (QWindow *window = q->windowHandle())
+ window->setTitle(caption);
+
+}
+
void QWidgetPrivate::setWindowIconText_helper(const QString &title)
{
Q_Q(QWidget);
@@ -5611,6 +5998,11 @@ void QWidgetPrivate::setWindowIconText_helper(const QString &title)
setWindowIconText_sys(qt_setWindowTitle_helperHelper(title, q));
}
+void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
+{
+ Q_UNUSED(iconText);
+}
+
/*!
\fn void QWidget::windowIconTextChanged(const QString &iconText)
@@ -5719,6 +6111,12 @@ void QWidget::setWindowIcon(const QIcon &icon)
emit windowIconChanged(icon);
}
+void QWidgetPrivate::setWindowIcon_sys()
+{
+ Q_Q(QWidget);
+ if (QWindow *window = q->windowHandle())
+ window->setIcon(q->windowIcon());
+}
/*!
\property QWidget::windowIconText
@@ -5794,6 +6192,16 @@ void QWidgetPrivate::setWindowFilePath_helper(const QString &filePath)
#endif
}
+void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath)
+{
+ Q_Q(QWidget);
+ if (!q->isWindow())
+ return;
+
+ if (QWindow *window = q->windowHandle())
+ window->setFilePath(filePath);
+}
+
/*!
Returns the window's role, or an empty string.
@@ -6053,6 +6461,21 @@ void QWidget::setFocus(Qt::FocusReason reason)
}
}
+void QWidgetPrivate::setFocus_sys()
+{
+ Q_Q(QWidget);
+ // Embedded native widget may have taken the focus; get it back to toplevel if that is the case
+ const QWidget *topLevel = q->window();
+ if (topLevel->windowType() != Qt::Popup) {
+ if (QWindow *nativeWindow = q->window()->windowHandle()) {
+ if (nativeWindow != QGuiApplication::focusWindow()
+ && q->testAttribute(Qt::WA_WState_Created)) {
+ nativeWindow->requestActivate();
+ }
+ }
+ }
+}
+
// updates focus_child on parent widgets to point into this widget
void QWidgetPrivate::updateFocusChild()
{
@@ -6554,6 +6977,31 @@ void QWidget::move(const QPoint &p)
QWindowContainer::parentWasMoved(this);
}
+// move() was invoked with Qt::WA_WState_Created not set (frame geometry
+// unknown), that is, crect has a position including the frame.
+// If we can determine the frame strut, fix that and clear the flag.
+void QWidgetPrivate::fixPosIncludesFrame()
+{
+ Q_Q(QWidget);
+ if (QTLWExtra *te = maybeTopData()) {
+ if (te->posIncludesFrame) {
+ // For Qt::WA_DontShowOnScreen, assume a frame of 0 (for
+ // example, in QGraphicsProxyWidget).
+ if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ te->posIncludesFrame = 0;
+ } else {
+ if (q->windowHandle()) {
+ updateFrameStrut();
+ if (!q->data->fstrut_dirty) {
+ data.crect.translate(te->frameStrut.x(), te->frameStrut.y());
+ te->posIncludesFrame = 0;
+ }
+ } // windowHandle()
+ } // !WA_DontShowOnScreen
+ } // posIncludesFrame
+ } // QTLWExtra
+}
+
/*! \fn void QWidget::resize(int w, int h)
\overload
@@ -6595,6 +7043,110 @@ void QWidget::setGeometry(const QRect &r)
QWindowContainer::parentWasMoved(this);
}
+void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
+{
+ Q_Q(QWidget);
+ if (extra) { // any size restrictions?
+ w = qMin(w,extra->maxw);
+ h = qMin(h,extra->maxh);
+ w = qMax(w,extra->minw);
+ h = qMax(h,extra->minh);
+ }
+
+ if (q->isWindow() && q->windowHandle()) {
+ QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration();
+ if (!integration->hasCapability(QPlatformIntegration::NonFullScreenWindows)) {
+ x = 0;
+ y = 0;
+ w = q->windowHandle()->width();
+ h = q->windowHandle()->height();
+ }
+ }
+
+ QPoint oldp = q->geometry().topLeft();
+ QSize olds = q->size();
+ QRect r(x, y, w, h);
+
+ bool isResize = olds != r.size();
+ isMove = oldp != r.topLeft(); //### why do we have isMove as a parameter?
+
+
+ // We only care about stuff that changes the geometry, or may
+ // cause the window manager to change its state
+ if (r.size() == olds && oldp == r.topLeft())
+ return;
+
+ if (!data.in_set_window_state) {
+ q->data->window_state &= ~Qt::WindowMaximized;
+ q->data->window_state &= ~Qt::WindowFullScreen;
+ if (q->isWindow())
+ topData()->normalGeometry = QRect(0, 0, -1, -1);
+ }
+
+ QPoint oldPos = q->pos();
+ data.crect = r;
+
+ bool needsShow = false;
+
+ if (!(data.window_state & Qt::WindowFullScreen) && (w == 0 || h == 0)) {
+ q->setAttribute(Qt::WA_OutsideWSRange, true);
+ if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
+ hide_sys();
+ data.crect = QRect(x, y, w, h);
+ } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) {
+ q->setAttribute(Qt::WA_OutsideWSRange, false);
+ needsShow = true;
+ }
+
+ if (q->isVisible()) {
+ if (!q->testAttribute(Qt::WA_DontShowOnScreen) && !q->testAttribute(Qt::WA_OutsideWSRange)) {
+ if (q->windowHandle()) {
+ if (q->isWindow()) {
+ q->windowHandle()->setGeometry(q->geometry());
+ } else {
+ QPoint posInNativeParent = q->mapTo(q->nativeParentWidget(),QPoint());
+ q->windowHandle()->setGeometry(QRect(posInNativeParent,r.size()));
+ }
+
+ if (needsShow)
+ show_sys();
+ }
+
+ if (!q->isWindow()) {
+ if (renderToTexture) {
+ QRegion updateRegion(q->geometry());
+ updateRegion += QRect(oldPos, olds);
+ q->parentWidget()->d_func()->invalidateBuffer(updateRegion);
+ } else if (isMove && !isResize) {
+ moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
+ } else {
+ invalidateBuffer_resizeHelper(oldPos, olds);
+ }
+ }
+ }
+
+ // generate a move event for QWidgets without window handles. QWidgets with native
+ // window handles already receive a move event from
+ // QGuiApplicationPrivate::processGeometryChangeEvent.
+ if (isMove && (!q->windowHandle() || q->testAttribute(Qt::WA_DontShowOnScreen))) {
+ QMoveEvent e(q->pos(), oldPos);
+ QApplication::sendEvent(q, &e);
+ }
+ if (isResize) {
+ QResizeEvent e(r.size(), olds);
+ QApplication::sendEvent(q, &e);
+ if (q->windowHandle())
+ q->update();
+ }
+ } else { // not visible
+ if (isMove && q->pos() != oldPos)
+ q->setAttribute(Qt::WA_PendingMoveEvent, true);
+ if (isResize)
+ q->setAttribute(Qt::WA_PendingResizeEvent, true);
+ }
+
+}
+
/*!
\since 4.2
Saves the current geometry and state for top-level widgets.
@@ -7208,6 +7760,62 @@ void QWidgetPrivate::show_helper()
data.in_show = false; // reset qws optimization
}
+void QWidgetPrivate::show_sys()
+{
+ Q_Q(QWidget);
+
+ QWindow *window = q->windowHandle();
+
+ if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ invalidateBuffer(q->rect());
+ q->setAttribute(Qt::WA_Mapped);
+ if (q->isWindow() && q->windowModality() != Qt::NonModal && window) {
+ // add our window to the modal window list
+ QGuiApplicationPrivate::showModalWindow(window);
+ }
+ return;
+ }
+
+ if (renderToTexture && !q->isWindow())
+ QApplication::postEvent(q->parentWidget(), new QUpdateLaterEvent(q->geometry()));
+ else
+ QApplication::postEvent(q, new QUpdateLaterEvent(q->rect()));
+
+ if (!q->isWindow() && !q->testAttribute(Qt::WA_NativeWindow))
+ return;
+
+ if (window) {
+ if (q->isWindow())
+ fixPosIncludesFrame();
+ QRect geomRect = q->geometry();
+ if (!q->isWindow()) {
+ QPoint topLeftOfWindow = q->mapTo(q->nativeParentWidget(),QPoint());
+ geomRect.moveTopLeft(topLeftOfWindow);
+ }
+ const QRect windowRect = window->geometry();
+ if (windowRect != geomRect) {
+ if (q->testAttribute(Qt::WA_Moved)
+ || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
+ window->setGeometry(geomRect);
+ else
+ window->resize(geomRect.size());
+ }
+
+#ifndef QT_NO_CURSOR
+ qt_qpa_set_cursor(q, false); // Needed in case cursor was set before show
+#endif
+ invalidateBuffer(q->rect());
+ window->setVisible(true);
+ // Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
+ if (window->isTopLevel()) {
+ const QPoint crectTopLeft = q->data->crect.topLeft();
+ const QPoint windowTopLeft = window->geometry().topLeft();
+ if (crectTopLeft == QPoint(0, 0) && windowTopLeft != crectTopLeft)
+ q->data->crect.moveTopLeft(windowTopLeft);
+ }
+ }
+}
+
/*!
Hides the widget. This function is equivalent to
setVisible(false).
@@ -7285,6 +7893,39 @@ void QWidgetPrivate::hide_helper()
#endif
}
+void QWidgetPrivate::hide_sys()
+{
+ Q_Q(QWidget);
+
+ QWindow *window = q->windowHandle();
+
+ if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ q->setAttribute(Qt::WA_Mapped, false);
+ if (q->isWindow() && q->windowModality() != Qt::NonModal && window) {
+ // remove our window from the modal window list
+ QGuiApplicationPrivate::hideModalWindow(window);
+ }
+ // do not return here, if window non-zero, we must hide it
+ }
+
+ deactivateWidgetCleanup();
+
+ if (!q->isWindow()) {
+ QWidget *p = q->parentWidget();
+ if (p &&p->isVisible()) {
+ if (renderToTexture)
+ p->d_func()->invalidateBuffer(q->geometry());
+ else
+ invalidateBuffer(q->rect());
+ }
+ } else {
+ invalidateBuffer(q->rect());
+ }
+
+ if (window)
+ window->setVisible(false);
+}
+
/*!
\fn bool QWidget::isHidden() const
@@ -8213,6 +8854,7 @@ bool QWidget::event(QEvent *event)
case QEvent::MacSizeChange:
case QEvent::ContentsRectChange:
case QEvent::ThemeChange:
+ case QEvent::ReadOnlyChange:
changeEvent(event);
break;
@@ -8386,7 +9028,7 @@ bool QWidget::event(QEvent *event)
QEvent::ModifiedChange, QEvent::MouseTrackingChange,
QEvent::ParentChange, QEvent::WindowStateChange,
QEvent::LanguageChange, QEvent::LocaleChange,
- QEvent::LayoutDirectionChange.
+ QEvent::LayoutDirectionChange, QEvent::ReadOnlyChange.
*/
void QWidget::changeEvent(QEvent * event)
@@ -9767,6 +10409,88 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
QWindowContainer::parentWasChanged(this);
}
+void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
+{
+ Q_Q(QWidget);
+
+ Qt::WindowFlags oldFlags = data.window_flags;
+ bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
+
+ int targetScreen = -1;
+ // Handle a request to move the widget to a particular screen
+ if (newparent && newparent->windowType() == Qt::Desktop) {
+ // make sure the widget is created on the same screen as the
+ // programmer specified desktop widget
+
+ // get the desktop's screen number
+ targetScreen = newparent->window()->d_func()->topData()->screenIndex;
+ newparent = 0;
+ }
+
+ setWinId(0);
+
+ if (parent != newparent) {
+ QObjectPrivate::setParent_helper(newparent); //### why does this have to be done in the _sys function???
+ if (q->windowHandle()) {
+ q->windowHandle()->setFlags(f);
+ QWidget *parentWithWindow =
+ newparent ? (newparent->windowHandle() ? newparent : newparent->nativeParentWidget()) : 0;
+ if (parentWithWindow) {
+ if (f & Qt::Window) {
+ q->windowHandle()->setTransientParent(parentWithWindow->windowHandle());
+ q->windowHandle()->setParent(0);
+ } else {
+ q->windowHandle()->setTransientParent(0);
+ q->windowHandle()->setParent(parentWithWindow->windowHandle());
+ }
+ } else {
+ q->windowHandle()->setTransientParent(0);
+ q->windowHandle()->setParent(0);
+ }
+ }
+ }
+
+ if (!newparent) {
+ f |= Qt::Window;
+ if (targetScreen == -1) {
+ if (parent)
+ targetScreen = q->parentWidget()->window()->d_func()->topData()->screenIndex;
+ }
+ }
+
+ bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
+
+ // Reparenting toplevel to child
+ if (wasCreated && !(f & Qt::Window) && (oldFlags & Qt::Window) && !q->testAttribute(Qt::WA_NativeWindow)) {
+ if (extra && extra->hasWindowContainer)
+ QWindowContainer::toplevelAboutToBeDestroyed(q);
+ q->destroy();
+ }
+
+ adjustFlags(f, q);
+ data.window_flags = f;
+ q->setAttribute(Qt::WA_WState_Created, false);
+ q->setAttribute(Qt::WA_WState_Visible, false);
+ q->setAttribute(Qt::WA_WState_Hidden, false);
+
+ if (newparent && wasCreated && (q->testAttribute(Qt::WA_NativeWindow) || (f & Qt::Window)))
+ q->createWinId();
+
+ if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden)
+ q->setAttribute(Qt::WA_WState_Hidden);
+ q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
+
+ // move the window to the selected screen
+ if (!newparent && targetScreen != -1) {
+ if (maybeTopData())
+ maybeTopData()->screenIndex = targetScreen;
+ // only if it is already created
+ if (q->testAttribute(Qt::WA_WState_Created)) {
+ q->windowHandle()->setScreen(QGuiApplication::screens().value(targetScreen, 0));
+ }
+ }
+}
+
/*!
Scrolls the widget including its children \a dx pixels to the
right and \a dy downward. Both \a dx and \a dy may be negative.
@@ -9812,6 +10536,13 @@ void QWidget::scroll(int dx, int dy)
d->scroll_sys(dx, dy);
}
+void QWidgetPrivate::scroll_sys(int dx, int dy)
+{
+ Q_Q(QWidget);
+ scrollChildren(dx, dy);
+ scrollRect(q->rect(), dx, dy);
+}
+
/*!
\overload
@@ -9846,6 +10577,11 @@ void QWidget::scroll(int dx, int dy, const QRect &r)
d->scroll_sys(dx, dy, r);
}
+void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
+{
+ scrollRect(r, dx, dy);
+}
+
/*!
Repaints the widget directly by calling paintEvent() immediately,
unless updates are disabled or the widget is hidden.
@@ -10093,7 +10829,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
#ifdef Q_OS_WIN
// ### Don't use PaintOnScreen+paintEngine() to do native painting in some future release
if (attribute == Qt::WA_PaintOnScreen && on && windowType() != Qt::Desktop && !inherits("QGLWidget")) {
- // see qwidget_qpa.cpp, ::paintEngine for details
+ // see ::paintEngine for details
paintEngine();
if (d->noPaintOnScreen)
return;
@@ -10417,6 +11153,13 @@ void QWidget::setWindowOpacity(qreal opacity)
#endif
}
+void QWidgetPrivate::setWindowOpacity_sys(qreal level)
+{
+ Q_Q(QWidget);
+ if (q->windowHandle())
+ q->windowHandle()->setOpacity(level);
+}
+
/*!
\property QWidget::windowModified
\brief whether the document shown in the window has unsaved changes
@@ -10586,12 +11329,21 @@ QString QWidget::whatsThis() const
\brief the widget's name as seen by assistive technologies
- This property is used by accessible clients to identify, find, or announce
- the widget for accessible clients.
+ This is the primary name by which assistive technology such as screen readers
+ announce this widget. For most widgets setting this property is not required.
+ For example for QPushButton the button's text will be used.
+
+ It is important to set this property when the widget does not provide any
+ text. For example a button that only contains an icon needs to set this
+ property to work with screen readers.
+ The name should be short and equivalent to the visual information conveyed
+ by the widget.
+
+ This property has to be \l{Internationalization with Qt}{localized}.
By default, this property contains an empty string.
- \sa QAccessibleInterface::text()
+ \sa QWidget::accessibleDescription, QAccessibleInterface::text()
*/
void QWidget::setAccessibleName(const QString &name)
{
@@ -10612,9 +11364,16 @@ QString QWidget::accessibleName() const
\brief the widget's description as seen by assistive technologies
- By default, this property contains an empty string.
+ The accessible description of a widget should convey what a widget does.
+ While the \l accessibleName should be a short and consise string (e.g. \gui{Save}),
+ the description should give more context, such as \gui{Saves the current document}.
- \sa QAccessibleInterface::text()
+ This property has to be \l{Internationalization with Qt}{localized}.
+
+ By default, this property contains an empty string and Qt falls back
+ to using the tool tip to provide this information.
+
+ \sa QWidget::accessibleName, QAccessibleInterface::text()
*/
void QWidget::setAccessibleDescription(const QString &description)
{
@@ -10774,6 +11533,19 @@ void QWidget::raise()
QApplication::sendEvent(this, &e);
}
+void QWidgetPrivate::raise_sys()
+{
+ Q_Q(QWidget);
+ if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
+ q->windowHandle()->raise();
+ } else if (renderToTexture) {
+ if (QWidget *p = q->parentWidget()) {
+ setDirtyOpaqueRegion();
+ p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
+ }
+ }
+}
+
/*!
Lowers the widget to the bottom of the parent widget's stack.
@@ -10811,6 +11583,17 @@ void QWidget::lower()
QApplication::sendEvent(this, &e);
}
+void QWidgetPrivate::lower_sys()
+{
+ Q_Q(QWidget);
+ if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ q->windowHandle()->lower();
+ } else if (QWidget *p = q->parentWidget()) {
+ setDirtyOpaqueRegion();
+ p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
+ }
+}
/*!
Places the widget under \a w in the parent widget's stack.
@@ -10847,6 +11630,14 @@ void QWidget::stackUnder(QWidget* w)
QApplication::sendEvent(this, &e);
}
+void QWidgetPrivate::stackUnder_sys(QWidget*)
+{
+ Q_Q(QWidget);
+ if (QWidget *p = q->parentWidget()) {
+ setDirtyOpaqueRegion();
+ p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
+ }
+}
/*!
\fn bool QWidget::isTopLevel() const
@@ -10907,6 +11698,24 @@ QRect QWidgetPrivate::frameStrut() const
return maybeTopData() ? maybeTopData()->frameStrut : QRect();
}
+void QWidgetPrivate::updateFrameStrut()
+{
+ Q_Q(QWidget);
+ if (q->data->fstrut_dirty) {
+ if (QTLWExtra *te = maybeTopData()) {
+ if (te->window) {
+ if (const QPlatformWindow *pw = te->window->handle()) {
+ const QMargins margins = pw->frameMargins();
+ if (!margins.isNull()) {
+ te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
+ q->data->fstrut_dirty = false;
+ }
+ }
+ }
+ }
+ }
+}
+
#ifdef QT_KEYPAD_NAVIGATION
/*!
\internal
@@ -11243,6 +12052,50 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
This function is usually called from the QWidget destructor.
*/
+void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
+{
+ Q_D(QWidget);
+
+ d->aboutToDestroy();
+ if (!isWindow() && parentWidget())
+ parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry()));
+ d->deactivateWidgetCleanup();
+
+ if ((windowType() == Qt::Popup) && qApp)
+ qApp->d_func()->closePopup(this);
+
+ if (this == QApplicationPrivate::active_window)
+ QApplication::setActiveWindow(0);
+ if (QWidget::mouseGrabber() == this)
+ releaseMouse();
+ if (QWidget::keyboardGrabber() == this)
+ releaseKeyboard();
+
+ setAttribute(Qt::WA_WState_Created, false);
+
+ if (windowType() != Qt::Desktop) {
+ if (destroySubWindows) {
+ QObjectList childList(children());
+ for (int i = 0; i < childList.size(); i++) {
+ QWidget *widget = qobject_cast<QWidget *>(childList.at(i));
+ if (widget && widget->testAttribute(Qt::WA_NativeWindow)) {
+ if (widget->windowHandle()) {
+ widget->destroy();
+ }
+ }
+ }
+ }
+ if (destroyWindow) {
+ d->deleteTLSysExtra();
+ } else {
+ if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) {
+ d->hide_sys();
+ }
+ }
+
+ d->setWinId(0);
+ }
+}
/*!
\fn QPaintEngine *QWidget::paintEngine() const
@@ -11254,6 +12107,30 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
function is called by Qt internally, and the default
implementation may not always return a valid pointer.
*/
+QPaintEngine *QWidget::paintEngine() const
+{
+ qWarning("QWidget::paintEngine: Should no longer be called");
+
+#ifdef Q_OS_WIN
+ // We set this bit which is checked in setAttribute for
+ // Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
+ //
+ // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
+ // Windows which would mean suddenly their widgets stop working.
+ //
+ // 2. Users set paint on screen and subclass paintEngine() to
+ // return 0, in which case we have a "hole" in the backingstore
+ // allowing use of GDI or DirectX directly.
+ //
+ // 1 is WRONG, but to minimize silent failures, we have set this
+ // bit to ignore the setAttribute call. 2. needs to be
+ // supported because its our only means of embedding native
+ // graphics stuff.
+ const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
+#endif
+
+ return 0; //##### @@@
+}
/*!
\fn QPoint QWidget::mapToGlobal(const QPoint &pos) const
@@ -11264,6 +12141,21 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\sa mapFromGlobal(), mapTo(), mapToParent()
*/
+QPoint QWidget::mapToGlobal(const QPoint &pos) const
+{
+ int x = pos.x(), y = pos.y();
+ const QWidget *w = this;
+ while (w) {
+ QWindow *window = w->windowHandle();
+ if (window && window->handle())
+ return window->mapToGlobal(QPoint(x, y));
+
+ x += w->data->crect.x();
+ y += w->data->crect.y();
+ w = w->isWindow() ? 0 : w->parentWidget();
+ }
+ return QPoint(x, y);
+}
/*!
\fn QPoint QWidget::mapFromGlobal(const QPoint &pos) const
@@ -11273,6 +12165,75 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\sa mapToGlobal(), mapFrom(), mapFromParent()
*/
+QPoint QWidget::mapFromGlobal(const QPoint &pos) const
+{
+ int x = pos.x(), y = pos.y();
+ const QWidget *w = this;
+ while (w) {
+ QWindow *window = w->windowHandle();
+ if (window && window->handle())
+ return window->mapFromGlobal(QPoint(x, y));
+
+ x -= w->data->crect.x();
+ y -= w->data->crect.y();
+ w = w->isWindow() ? 0 : w->parentWidget();
+ }
+ return QPoint(x, y);
+}
+
+QWidget *qt_pressGrab = 0;
+QWidget *qt_mouseGrb = 0;
+static bool mouseGrabWithCursor = false;
+static QWidget *keyboardGrb = 0;
+
+static inline QWindow *grabberWindow(const QWidget *w)
+{
+ QWindow *window = w->windowHandle();
+ if (!window)
+ if (const QWidget *nativeParent = w->nativeParentWidget())
+ window = nativeParent->windowHandle();
+ return window;
+}
+
+#ifndef QT_NO_CURSOR
+static void grabMouseForWidget(QWidget *widget, const QCursor *cursor = 0)
+#else
+static void grabMouseForWidget(QWidget *widget)
+#endif
+{
+ if (qt_mouseGrb)
+ qt_mouseGrb->releaseMouse();
+
+ mouseGrabWithCursor = false;
+ if (QWindow *window = grabberWindow(widget)) {
+#ifndef QT_NO_CURSOR
+ if (cursor) {
+ mouseGrabWithCursor = true;
+ QGuiApplication::setOverrideCursor(*cursor);
+ }
+#endif // !QT_NO_CURSOR
+ window->setMouseGrabEnabled(true);
+ }
+
+ qt_mouseGrb = widget;
+ qt_pressGrab = 0;
+}
+
+static void releaseMouseGrabOfWidget(QWidget *widget)
+{
+ if (qt_mouseGrb == widget) {
+ if (QWindow *window = grabberWindow(widget)) {
+#ifndef QT_NO_CURSOR
+ if (mouseGrabWithCursor) {
+ QGuiApplication::restoreOverrideCursor();
+ mouseGrabWithCursor = false;
+ }
+#endif // !QT_NO_CURSOR
+ window->setMouseGrabEnabled(false);
+ }
+ }
+ qt_mouseGrb = 0;
+}
/*!
\fn void QWidget::grabMouse()
@@ -11303,6 +12264,10 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\sa releaseMouse(), grabKeyboard(), releaseKeyboard()
*/
+void QWidget::grabMouse()
+{
+ grabMouseForWidget(this);
+}
/*!
\fn void QWidget::grabMouse(const QCursor &cursor)
@@ -11320,6 +12285,21 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor()
*/
+#ifndef QT_NO_CURSOR
+void QWidget::grabMouse(const QCursor &cursor)
+{
+ grabMouseForWidget(this, &cursor);
+}
+#endif
+
+bool QWidgetPrivate::stealMouseGrab(bool grab)
+{
+ // This is like a combination of grab/releaseMouse() but with error checking
+ // and it has no effect on the result of mouseGrabber().
+ Q_Q(QWidget);
+ QWindow *window = grabberWindow(q);
+ return window ? window->setMouseGrabEnabled(grab) : false;
+}
/*!
\fn void QWidget::releaseMouse()
@@ -11328,6 +12308,10 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\sa grabMouse(), grabKeyboard(), releaseKeyboard()
*/
+void QWidget::releaseMouse()
+{
+ releaseMouseGrabOfWidget(this);
+}
/*!
\fn void QWidget::grabKeyboard()
@@ -11348,6 +12332,23 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\sa releaseKeyboard(), grabMouse(), releaseMouse(), focusWidget()
*/
+void QWidget::grabKeyboard()
+{
+ if (keyboardGrb)
+ keyboardGrb->releaseKeyboard();
+ if (QWindow *window = grabberWindow(this))
+ window->setKeyboardGrabEnabled(true);
+ keyboardGrb = this;
+}
+
+bool QWidgetPrivate::stealKeyboardGrab(bool grab)
+{
+ // This is like a combination of grab/releaseKeyboard() but with error
+ // checking and it has no effect on the result of keyboardGrabber().
+ Q_Q(QWidget);
+ QWindow *window = grabberWindow(q);
+ return window ? window->setKeyboardGrabEnabled(grab) : false;
+}
/*!
\fn void QWidget::releaseKeyboard()
@@ -11356,6 +12357,14 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\sa grabKeyboard(), grabMouse(), releaseMouse()
*/
+void QWidget::releaseKeyboard()
+{
+ if (keyboardGrb == this) {
+ if (QWindow *window = grabberWindow(this))
+ window->setKeyboardGrabEnabled(false);
+ keyboardGrb = 0;
+ }
+}
/*!
\fn QWidget *QWidget::mouseGrabber()
@@ -11367,6 +12376,12 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\sa grabMouse(), keyboardGrabber()
*/
+QWidget *QWidget::mouseGrabber()
+{
+ if (qt_mouseGrb)
+ return qt_mouseGrb;
+ return qt_pressGrab;
+}
/*!
\fn QWidget *QWidget::keyboardGrabber()
@@ -11378,6 +12393,10 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\sa grabMouse(), mouseGrabber()
*/
+QWidget *QWidget::keyboardGrabber()
+{
+ return keyboardGrb;
+}
/*!
\fn void QWidget::activateWindow()
@@ -11403,6 +12422,13 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\sa isActiveWindow(), window(), show()
*/
+void QWidget::activateWindow()
+{
+ QWindow *const wnd = window()->windowHandle();
+
+ if (wnd)
+ wnd->requestActivate();
+}
/*!
\fn int QWidget::metric(PaintDeviceMetric m) const
@@ -11412,6 +12438,62 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\a m is the metric to get.
*/
+int QWidget::metric(PaintDeviceMetric m) const
+{
+ Q_D(const QWidget);
+
+ QWindow *topLevelWindow = 0;
+ QScreen *screen = 0;
+ if (QWidget *topLevel = window())
+ topLevelWindow = topLevel->windowHandle();
+
+ if (topLevelWindow) {
+ QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWindow(topLevelWindow);
+ if (platformScreen)
+ screen = platformScreen->screen();
+ }
+ if (!screen && QGuiApplication::primaryScreen())
+ screen = QGuiApplication::primaryScreen();
+
+ if (!screen) {
+ if (m == PdmDpiX || m == PdmDpiY)
+ return 72;
+ return QPaintDevice::metric(m);
+ }
+ int val;
+ if (m == PdmWidth) {
+ val = data->crect.width();
+ } else if (m == PdmWidthMM) {
+ val = data->crect.width() * screen->physicalSize().width() / screen->geometry().width();
+ } else if (m == PdmHeight) {
+ val = data->crect.height();
+ } else if (m == PdmHeightMM) {
+ val = data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
+ } else if (m == PdmDepth) {
+ return screen->depth();
+ } else if (m == PdmDpiX) {
+ if (d->extra && d->extra->customDpiX)
+ return d->extra->customDpiX;
+ else if (d->parent)
+ return static_cast<QWidget *>(d->parent)->metric(m);
+ return qRound(screen->logicalDotsPerInchX());
+ } else if (m == PdmDpiY) {
+ if (d->extra && d->extra->customDpiY)
+ return d->extra->customDpiY;
+ else if (d->parent)
+ return static_cast<QWidget *>(d->parent)->metric(m);
+ return qRound(screen->logicalDotsPerInchY());
+ } else if (m == PdmPhysicalDpiX) {
+ return qRound(screen->physicalDotsPerInchX());
+ } else if (m == PdmPhysicalDpiY) {
+ return qRound(screen->physicalDotsPerInchY());
+ } else if (m == PdmDevicePixelRatio) {
+ return topLevelWindow ? topLevelWindow->devicePixelRatio() : qApp->devicePixelRatio();
+ } else {
+ val = QPaintDevice::metric(m);// XXX
+ }
+ return val;
+}
/*!
Initializes the \a painter pen, background and font to the same as
@@ -11517,6 +12599,14 @@ void QWidget::setMask(const QRegion &newMask)
#endif
}
+void QWidgetPrivate::setMask_sys(const QRegion &region)
+{
+ Q_Q(QWidget);
+ if (const QWindow *window = q->windowHandle())
+ if (QPlatformWindow *platformWindow = window->handle())
+ platformWindow->setMask(region);
+}
+
/*!
\fn void QWidget::setMask(const QBitmap &bitmap)
diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h
index 159011b824..9c22ad7c3d 100644
--- a/src/widgets/kernel/qwidget.h
+++ b/src/widgets/kernel/qwidget.h
@@ -694,7 +694,6 @@ private:
friend class QPixmap; // for QPixmap::fill()
friend class QFontMetrics;
friend class QFontInfo;
- friend class QETWidget;
friend class QLayout;
friend class QWidgetItem;
friend class QWidgetItemV2;
diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
index 9586d1a8c9..6520832943 100644
--- a/src/widgets/kernel/qwidget_p.h
+++ b/src/widgets/kernel/qwidget_p.h
@@ -627,7 +627,7 @@ public:
#ifndef QT_NO_OPENGL
virtual GLuint textureId() const { return 0; }
-
+ virtual QImage grabFramebuffer() const { return QImage(); }
void setRenderToTexture() { renderToTexture = true; setTextureChildSeen(); }
void setTextureChildSeen()
{
@@ -732,7 +732,7 @@ public:
// *************************** Platform specific ************************************
#if defined(Q_OS_WIN)
- uint noPaintOnScreen : 1; // see qwidget_qpa.cpp ::paintEngine()
+ uint noPaintOnScreen : 1; // see qwidget.cpp ::paintEngine()
#endif
#if defined(Q_WS_X11) // <----------------------------------------------------------- X11
Qt::HANDLE picture;
diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp
deleted file mode 100644
index 5a4bd33672..0000000000
--- a/src/widgets/kernel/qwidget_qpa.cpp
+++ /dev/null
@@ -1,1126 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "QtWidgets/qwidget.h"
-#include "QtGui/qevent.h"
-#include "QtWidgets/qapplication.h"
-#include "private/qwidgetbackingstore_p.h"
-#include "private/qwidget_p.h"
-#include "private/qwidgetwindow_qpa_p.h"
-#include "private/qapplication_p.h"
-#include "QtWidgets/qdesktopwidget.h"
-#include <qpa/qplatformwindow.h>
-#include "QtGui/qsurfaceformat.h"
-#include <QtGui/qopenglcontext.h>
-#include <qpa/qplatformopenglcontext.h>
-#include <qpa/qplatformintegration.h>
-#include "QtGui/private/qwindow_p.h"
-#include "QtGui/private/qguiapplication_p.h"
-#include <private/qwindowcontainer_p.h>
-
-#include <qpa/qplatformcursor.h>
-#include <QtGui/QGuiApplication>
-#include <QtGui/QScreen>
-#include <QtCore/QMargins>
-
-QT_BEGIN_NAMESPACE
-
-void q_createNativeChildrenAndSetParent(const QWidget *parentWidget)
-{
- QObjectList children = parentWidget->children();
- for (int i = 0; i < children.size(); i++) {
- if (children.at(i)->isWidgetType()) {
- const QWidget *childWidget = qobject_cast<const QWidget *>(children.at(i));
- if (childWidget) { // should not be necessary
- if (childWidget->testAttribute(Qt::WA_NativeWindow)) {
- if (!childWidget->internalWinId())
- childWidget->winId();
- if (childWidget->windowHandle()) {
- QWindow *parentWindow = childWidget->nativeParentWidget()->windowHandle();
- if (childWidget->isWindow())
- childWidget->windowHandle()->setTransientParent(parentWindow);
- else
- childWidget->windowHandle()->setParent(parentWindow);
- }
- } else {
- q_createNativeChildrenAndSetParent(childWidget);
- }
- }
- }
- }
-
-}
-
-void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
-{
- Q_Q(QWidget);
-
- Q_UNUSED(window);
- Q_UNUSED(initializeWindow);
- Q_UNUSED(destroyOldWindow);
-
- Qt::WindowFlags flags = data.window_flags;
-
- if (!q->testAttribute(Qt::WA_NativeWindow) && !q->isWindow())
- return; // we only care about real toplevels
-
- QWindow *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) {
- createTLSysExtra();
- win = topData()->window;
- }
-
- foreach (const QByteArray &propertyName, q->dynamicPropertyNames()) {
- if (!qstrncmp(propertyName, "_q_platform_", 12))
- win->setProperty(propertyName, q->property(propertyName));
- }
-
-#ifdef Q_OS_OSX
- if (q->testAttribute(Qt::WA_ShowWithoutActivating))
- win->setProperty("_q_showWithoutActivating", QVariant(true));
-#endif
- win->setFlags(data.window_flags);
- fixPosIncludesFrame();
- if (q->testAttribute(Qt::WA_Moved)
- || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
- win->setGeometry(q->geometry());
- else
- win->resize(q->size());
- win->setScreen(QGuiApplication::screens().value(topData()->screenIndex, 0));
-
- QSurfaceFormat format = win->requestedFormat();
- if ((flags & Qt::Window) && win->surfaceType() != QSurface::OpenGLSurface
- && q->testAttribute(Qt::WA_TranslucentBackground)) {
- format.setAlphaBufferSize(8);
- }
- win->setFormat(format);
-
- if (QWidget *nativeParent = q->nativeParentWidget()) {
- if (nativeParent->windowHandle()) {
- if (flags & Qt::Window) {
- win->setTransientParent(nativeParent->window()->windowHandle());
- win->setParent(0);
- } else {
- win->setTransientParent(0);
- win->setParent(nativeParent->windowHandle());
- }
- }
- }
-
- qt_window_private(win)->positionPolicy = topData()->posIncludesFrame ?
- QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive;
- win->create();
- // Enable nonclient-area events for QDockWidget and other NonClientArea-mouse event processing.
- if ((flags & Qt::Desktop) == Qt::Window)
- win->handle()->setFrameStrutEventsEnabled(true);
-
- data.window_flags = win->flags();
-
- QBackingStore *store = q->backingStore();
-
- if (!store) {
- if (win && q->windowType() != Qt::Desktop) {
- if (q->isTopLevel())
- q->setBackingStore(new QBackingStore(win));
- } else {
- q->setAttribute(Qt::WA_PaintOnScreen, true);
- }
- }
-
- setWindowModified_helper();
- WId id = win->winId();
- // See the QPlatformWindow::winId() documentation
- Q_ASSERT(id != WId(0));
- setWinId(id);
-
- // Check children and create windows for them if necessary
- q_createNativeChildrenAndSetParent(q);
-
- if (extra && !extra->mask.isEmpty())
- setMask_sys(extra->mask);
-
- // If widget is already shown, set window visible, too
- if (q->isVisible())
- win->setVisible(true);
-}
-
-void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
-{
- Q_D(QWidget);
-
- d->aboutToDestroy();
- if (!isWindow() && parentWidget())
- parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry()));
- d->deactivateWidgetCleanup();
-
- if ((windowType() == Qt::Popup) && qApp)
- qApp->d_func()->closePopup(this);
-
- if (this == QApplicationPrivate::active_window)
- QApplication::setActiveWindow(0);
- if (QWidget::mouseGrabber() == this)
- releaseMouse();
- if (QWidget::keyboardGrabber() == this)
- releaseKeyboard();
-
- setAttribute(Qt::WA_WState_Created, false);
-
- if (windowType() != Qt::Desktop) {
- if (destroySubWindows) {
- QObjectList childList(children());
- for (int i = 0; i < childList.size(); i++) {
- QWidget *widget = qobject_cast<QWidget *>(childList.at(i));
- if (widget && widget->testAttribute(Qt::WA_NativeWindow)) {
- if (widget->windowHandle()) {
- widget->destroy();
- }
- }
- }
- }
- if (destroyWindow) {
- d->deleteTLSysExtra();
- } else {
- if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) {
- d->hide_sys();
- }
- }
-
- d->setWinId(0);
- }
-}
-
-void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
-{
- Q_Q(QWidget);
-
- Qt::WindowFlags oldFlags = data.window_flags;
- bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
-
- int targetScreen = -1;
- // Handle a request to move the widget to a particular screen
- if (newparent && newparent->windowType() == Qt::Desktop) {
- // make sure the widget is created on the same screen as the
- // programmer specified desktop widget
-
- // get the desktop's screen number
- targetScreen = newparent->window()->d_func()->topData()->screenIndex;
- newparent = 0;
- }
-
- setWinId(0);
-
- if (parent != newparent) {
- QObjectPrivate::setParent_helper(newparent); //### why does this have to be done in the _sys function???
- if (q->windowHandle()) {
- q->windowHandle()->setFlags(f);
- QWidget *parentWithWindow =
- newparent ? (newparent->windowHandle() ? newparent : newparent->nativeParentWidget()) : 0;
- if (parentWithWindow) {
- if (f & Qt::Window) {
- q->windowHandle()->setTransientParent(parentWithWindow->windowHandle());
- q->windowHandle()->setParent(0);
- } else {
- q->windowHandle()->setTransientParent(0);
- q->windowHandle()->setParent(parentWithWindow->windowHandle());
- }
- } else {
- q->windowHandle()->setTransientParent(0);
- q->windowHandle()->setParent(0);
- }
- }
- }
-
- if (!newparent) {
- f |= Qt::Window;
- if (targetScreen == -1) {
- if (parent)
- targetScreen = q->parentWidget()->window()->d_func()->topData()->screenIndex;
- }
- }
-
- bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
-
- // Reparenting toplevel to child
- if (wasCreated && !(f & Qt::Window) && (oldFlags & Qt::Window) && !q->testAttribute(Qt::WA_NativeWindow)) {
- if (extra && extra->hasWindowContainer)
- QWindowContainer::toplevelAboutToBeDestroyed(q);
- q->destroy();
- }
-
- adjustFlags(f, q);
- data.window_flags = f;
- q->setAttribute(Qt::WA_WState_Created, false);
- q->setAttribute(Qt::WA_WState_Visible, false);
- q->setAttribute(Qt::WA_WState_Hidden, false);
-
- if (newparent && wasCreated && (q->testAttribute(Qt::WA_NativeWindow) || (f & Qt::Window)))
- q->createWinId();
-
- if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden)
- q->setAttribute(Qt::WA_WState_Hidden);
- q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
-
- // move the window to the selected screen
- if (!newparent && targetScreen != -1) {
- if (maybeTopData())
- maybeTopData()->screenIndex = targetScreen;
- // only if it is already created
- if (q->testAttribute(Qt::WA_WState_Created)) {
- q->windowHandle()->setScreen(QGuiApplication::screens().value(targetScreen, 0));
- }
- }
-}
-
-QPoint QWidget::mapToGlobal(const QPoint &pos) const
-{
- int x = pos.x(), y = pos.y();
- const QWidget *w = this;
- while (w) {
- QWindow *window = w->windowHandle();
- if (window && window->handle())
- return window->mapToGlobal(QPoint(x, y));
-
- x += w->data->crect.x();
- y += w->data->crect.y();
- w = w->isWindow() ? 0 : w->parentWidget();
- }
- return QPoint(x, y);
-}
-
-QPoint QWidget::mapFromGlobal(const QPoint &pos) const
-{
- int x = pos.x(), y = pos.y();
- const QWidget *w = this;
- while (w) {
- QWindow *window = w->windowHandle();
- if (window && window->handle())
- return window->mapFromGlobal(QPoint(x, y));
-
- x -= w->data->crect.x();
- y -= w->data->crect.y();
- w = w->isWindow() ? 0 : w->parentWidget();
- }
- return QPoint(x, y);
-}
-
-void QWidgetPrivate::updateSystemBackground() {}
-
-#ifndef QT_NO_CURSOR
-void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
-{
- Q_UNUSED(cursor);
- Q_Q(QWidget);
- qt_qpa_set_cursor(q, false);
-}
-
-void QWidgetPrivate::unsetCursor_sys()
-{
- Q_Q(QWidget);
- qt_qpa_set_cursor(q, false);
-}
-
-#endif //QT_NO_CURSOR
-
-void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
-{
- Q_Q(QWidget);
- if (!q->isWindow())
- return;
-
- if (QWindow *window = q->windowHandle())
- window->setTitle(caption);
-
-}
-
-void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath)
-{
- Q_Q(QWidget);
- if (!q->isWindow())
- return;
-
- if (QWindow *window = q->windowHandle())
- window->setFilePath(filePath);
-}
-
-void QWidgetPrivate::setWindowIcon_sys()
-{
- Q_Q(QWidget);
- if (QWindow *window = q->windowHandle())
- window->setIcon(q->windowIcon());
-}
-
-void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
-{
- Q_UNUSED(iconText);
-}
-
-QWidget *qt_pressGrab = 0;
-QWidget *qt_mouseGrb = 0;
-static QWidget *keyboardGrb = 0;
-
-static inline QWindow *grabberWindow(const QWidget *w)
-{
- QWindow *window = w->windowHandle();
- if (!window)
- if (const QWidget *nativeParent = w->nativeParentWidget())
- window = nativeParent->windowHandle();
- return window;
-}
-
-void QWidget::grabMouse()
-{
- if (qt_mouseGrb)
- qt_mouseGrb->releaseMouse();
-
- if (QWindow *window = grabberWindow(this))
- window->setMouseGrabEnabled(true);
-
- qt_mouseGrb = this;
- qt_pressGrab = 0;
-}
-
-#ifndef QT_NO_CURSOR
-void QWidget::grabMouse(const QCursor &cursor)
-{
- Q_UNUSED(cursor);
- grabMouse();
-}
-#endif
-
-bool QWidgetPrivate::stealMouseGrab(bool grab)
-{
- // This is like a combination of grab/releaseMouse() but with error checking
- // and it has no effect on the result of mouseGrabber().
- Q_Q(QWidget);
- QWindow *window = grabberWindow(q);
- return window ? window->setMouseGrabEnabled(grab) : false;
-}
-
-void QWidget::releaseMouse()
-{
- if (qt_mouseGrb == this) {
- if (QWindow *window = grabberWindow(this))
- window->setMouseGrabEnabled(false);
- qt_mouseGrb = 0;
- }
-}
-
-void QWidget::grabKeyboard()
-{
- if (keyboardGrb)
- keyboardGrb->releaseKeyboard();
- if (QWindow *window = grabberWindow(this))
- window->setKeyboardGrabEnabled(true);
- keyboardGrb = this;
-}
-
-bool QWidgetPrivate::stealKeyboardGrab(bool grab)
-{
- // This is like a combination of grab/releaseKeyboard() but with error
- // checking and it has no effect on the result of keyboardGrabber().
- Q_Q(QWidget);
- QWindow *window = grabberWindow(q);
- return window ? window->setKeyboardGrabEnabled(grab) : false;
-}
-
-void QWidget::releaseKeyboard()
-{
- if (keyboardGrb == this) {
- if (QWindow *window = grabberWindow(this))
- window->setKeyboardGrabEnabled(false);
- keyboardGrb = 0;
- }
-}
-
-QWidget *QWidget::mouseGrabber()
-{
- if (qt_mouseGrb)
- return qt_mouseGrb;
- return qt_pressGrab;
-}
-
-QWidget *QWidget::keyboardGrabber()
-{
- return keyboardGrb;
-}
-
-void QWidget::activateWindow()
-{
- QWindow *const wnd = window()->windowHandle();
-
- if (wnd)
- wnd->requestActivate();
-}
-
-// move() was invoked with Qt::WA_WState_Created not set (frame geometry
-// unknown), that is, crect has a position including the frame.
-// If we can determine the frame strut, fix that and clear the flag.
-void QWidgetPrivate::fixPosIncludesFrame()
-{
- Q_Q(QWidget);
- if (QTLWExtra *te = maybeTopData()) {
- if (te->posIncludesFrame) {
- // For Qt::WA_DontShowOnScreen, assume a frame of 0 (for
- // example, in QGraphicsProxyWidget).
- if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
- te->posIncludesFrame = 0;
- } else {
- if (q->windowHandle()) {
- updateFrameStrut();
- if (!q->data->fstrut_dirty) {
- data.crect.translate(te->frameStrut.x(), te->frameStrut.y());
- te->posIncludesFrame = 0;
- }
- } // windowHandle()
- } // !WA_DontShowOnScreen
- } // posIncludesFrame
- } // QTLWExtra
-}
-
-void QWidgetPrivate::show_sys()
-{
- Q_Q(QWidget);
-
- QWindow *window = q->windowHandle();
-
- if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
- invalidateBuffer(q->rect());
- q->setAttribute(Qt::WA_Mapped);
- if (q->isWindow() && q->windowModality() != Qt::NonModal && window) {
- // add our window to the modal window list
- QGuiApplicationPrivate::showModalWindow(window);
- }
- return;
- }
-
- if (renderToTexture && !q->isWindow())
- QApplication::postEvent(q->parentWidget(), new QUpdateLaterEvent(q->geometry()));
- else
- QApplication::postEvent(q, new QUpdateLaterEvent(q->rect()));
-
- if (!q->isWindow() && !q->testAttribute(Qt::WA_NativeWindow))
- return;
-
- if (window) {
- if (q->isWindow())
- fixPosIncludesFrame();
- QRect geomRect = q->geometry();
- if (!q->isWindow()) {
- QPoint topLeftOfWindow = q->mapTo(q->nativeParentWidget(),QPoint());
- geomRect.moveTopLeft(topLeftOfWindow);
- }
- const QRect windowRect = window->geometry();
- if (windowRect != geomRect) {
- if (q->testAttribute(Qt::WA_Moved)
- || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
- window->setGeometry(geomRect);
- else
- window->resize(geomRect.size());
- }
-
-#ifndef QT_NO_CURSOR
- qt_qpa_set_cursor(q, false); // Needed in case cursor was set before show
-#endif
- invalidateBuffer(q->rect());
- window->setVisible(true);
- // Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
- if (window->isTopLevel()) {
- const QPoint crectTopLeft = q->data->crect.topLeft();
- const QPoint windowTopLeft = window->geometry().topLeft();
- if (crectTopLeft == QPoint(0, 0) && windowTopLeft != crectTopLeft)
- q->data->crect.moveTopLeft(windowTopLeft);
- }
- }
-}
-
-
-void QWidgetPrivate::hide_sys()
-{
- Q_Q(QWidget);
-
- QWindow *window = q->windowHandle();
-
- if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
- q->setAttribute(Qt::WA_Mapped, false);
- if (q->isWindow() && q->windowModality() != Qt::NonModal && window) {
- // remove our window from the modal window list
- QGuiApplicationPrivate::hideModalWindow(window);
- }
- // do not return here, if window non-zero, we must hide it
- }
-
- deactivateWidgetCleanup();
-
- if (!q->isWindow()) {
- QWidget *p = q->parentWidget();
- if (p &&p->isVisible()) {
- if (renderToTexture)
- p->d_func()->invalidateBuffer(q->geometry());
- else
- invalidateBuffer(q->rect());
- }
- } else {
- invalidateBuffer(q->rect());
- }
-
- if (window)
- window->setVisible(false);
-}
-
-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;
- }
-
-void QWidget::setWindowState(Qt::WindowStates newstate)
-{
- Q_D(QWidget);
- Qt::WindowStates oldstate = windowState();
- if (oldstate == newstate)
- return;
- if (isWindow() && !testAttribute(Qt::WA_WState_Created))
- create();
-
- data->window_state = newstate;
- data->in_set_window_state = 1;
- Qt::WindowState newEffectiveState = effectiveState(newstate);
- Qt::WindowState oldEffectiveState = effectiveState(oldstate);
- if (isWindow() && newEffectiveState != oldEffectiveState) {
- // 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)
- d->topData()->normalGeometry = geometry();
-
- Q_ASSERT(windowHandle());
- windowHandle()->setWindowState(newEffectiveState);
- }
- data->in_set_window_state = 0;
-
- if (newstate & Qt::WindowActive)
- activateWindow();
-
- QWindowStateChangeEvent e(oldstate);
- QApplication::sendEvent(this, &e);
-}
-
-void QWidgetPrivate::setFocus_sys()
-{
- Q_Q(QWidget);
- // Embedded native widget may have taken the focus; get it back to toplevel if that is the case
- const QWidget *topLevel = q->window();
- if (topLevel->windowType() != Qt::Popup) {
- if (QWindow *nativeWindow = q->window()->windowHandle()) {
- if (nativeWindow != QGuiApplication::focusWindow()
- && q->testAttribute(Qt::WA_WState_Created)) {
- nativeWindow->requestActivate();
- }
- }
- }
-}
-
-void QWidgetPrivate::raise_sys()
-{
- Q_Q(QWidget);
- if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
- q->windowHandle()->raise();
- } else if (renderToTexture) {
- if (QWidget *p = q->parentWidget()) {
- setDirtyOpaqueRegion();
- p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
- }
- }
-}
-
-void QWidgetPrivate::lower_sys()
-{
- Q_Q(QWidget);
- if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
- Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
- q->windowHandle()->lower();
- } else if (QWidget *p = q->parentWidget()) {
- setDirtyOpaqueRegion();
- p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
- }
-}
-
-void QWidgetPrivate::stackUnder_sys(QWidget*)
-{
- Q_Q(QWidget);
- if (QWidget *p = q->parentWidget()) {
- setDirtyOpaqueRegion();
- p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
- }
-}
-
-void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
-{
- Q_Q(QWidget);
- if (extra) { // any size restrictions?
- w = qMin(w,extra->maxw);
- h = qMin(h,extra->maxh);
- w = qMax(w,extra->minw);
- h = qMax(h,extra->minh);
- }
-
- if (q->isWindow() && q->windowHandle()) {
- QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration();
- if (!integration->hasCapability(QPlatformIntegration::NonFullScreenWindows)) {
- x = 0;
- y = 0;
- w = q->windowHandle()->width();
- h = q->windowHandle()->height();
- }
- }
-
- QPoint oldp = q->geometry().topLeft();
- QSize olds = q->size();
- QRect r(x, y, w, h);
-
- bool isResize = olds != r.size();
- isMove = oldp != r.topLeft(); //### why do we have isMove as a parameter?
-
-
- // We only care about stuff that changes the geometry, or may
- // cause the window manager to change its state
- if (r.size() == olds && oldp == r.topLeft())
- return;
-
- if (!data.in_set_window_state) {
- q->data->window_state &= ~Qt::WindowMaximized;
- q->data->window_state &= ~Qt::WindowFullScreen;
- if (q->isWindow())
- topData()->normalGeometry = QRect(0, 0, -1, -1);
- }
-
- QPoint oldPos = q->pos();
- data.crect = r;
-
- bool needsShow = false;
-
- if (!(data.window_state & Qt::WindowFullScreen) && (w == 0 || h == 0)) {
- q->setAttribute(Qt::WA_OutsideWSRange, true);
- if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
- hide_sys();
- data.crect = QRect(x, y, w, h);
- } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) {
- q->setAttribute(Qt::WA_OutsideWSRange, false);
- needsShow = true;
- }
-
- if (q->isVisible()) {
- if (!q->testAttribute(Qt::WA_DontShowOnScreen) && !q->testAttribute(Qt::WA_OutsideWSRange)) {
- if (q->windowHandle()) {
- if (q->isWindow()) {
- q->windowHandle()->setGeometry(q->geometry());
- } else {
- QPoint posInNativeParent = q->mapTo(q->nativeParentWidget(),QPoint());
- q->windowHandle()->setGeometry(QRect(posInNativeParent,r.size()));
- }
-
- if (needsShow)
- show_sys();
- }
-
- if (!q->isWindow()) {
- if (renderToTexture) {
- QRegion updateRegion(q->geometry());
- updateRegion += QRect(oldPos, olds);
- q->parentWidget()->d_func()->invalidateBuffer(updateRegion);
- } else if (isMove && !isResize) {
- moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
- } else {
- invalidateBuffer_resizeHelper(oldPos, olds);
- }
- }
- }
-
- // generate a move event for QWidgets without window handles. QWidgets with native
- // window handles already receive a move event from
- // QGuiApplicationPrivate::processGeometryChangeEvent.
- if (isMove && (!q->windowHandle() || q->testAttribute(Qt::WA_DontShowOnScreen))) {
- QMoveEvent e(q->pos(), oldPos);
- QApplication::sendEvent(q, &e);
- }
- if (isResize) {
- QResizeEvent e(r.size(), olds);
- QApplication::sendEvent(q, &e);
- if (q->windowHandle())
- q->update();
- }
- } else { // not visible
- if (isMove && q->pos() != oldPos)
- q->setAttribute(Qt::WA_PendingMoveEvent, true);
- if (isResize)
- q->setAttribute(Qt::WA_PendingResizeEvent, true);
- }
-
-}
-
-void QWidgetPrivate::setConstraints_sys()
-{
- Q_Q(QWidget);
- if (extra && q->windowHandle()) {
- QWindow *win = q->windowHandle();
- QWindowPrivate *winp = qt_window_private(win);
-
- winp->minimumSize = QSize(extra->minw, extra->minh);
- winp->maximumSize = QSize(extra->maxw, extra->maxh);
-
- if (extra->topextra) {
- winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh);
- winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
- }
-
- if (winp->platformWindow) {
- fixPosIncludesFrame();
- winp->platformWindow->propagateSizeHints();
- }
- }
-}
-
-void QWidgetPrivate::scroll_sys(int dx, int dy)
-{
- Q_Q(QWidget);
- scrollChildren(dx, dy);
- scrollRect(q->rect(), dx, dy);
-}
-
-void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
-{
- scrollRect(r, dx, dy);
-}
-
-int QWidget::metric(PaintDeviceMetric m) const
-{
- Q_D(const QWidget);
-
- QWindow *topLevelWindow = 0;
- QScreen *screen = 0;
- if (QWidget *topLevel = window())
- topLevelWindow = topLevel->windowHandle();
-
- if (topLevelWindow) {
- QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWindow(topLevelWindow);
- if (platformScreen)
- screen = platformScreen->screen();
- }
- if (!screen && QGuiApplication::primaryScreen())
- screen = QGuiApplication::primaryScreen();
-
- if (!screen) {
- if (m == PdmDpiX || m == PdmDpiY)
- return 72;
- return QPaintDevice::metric(m);
- }
- int val;
- if (m == PdmWidth) {
- val = data->crect.width();
- } else if (m == PdmWidthMM) {
- val = data->crect.width() * screen->physicalSize().width() / screen->geometry().width();
- } else if (m == PdmHeight) {
- val = data->crect.height();
- } else if (m == PdmHeightMM) {
- val = data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
- } else if (m == PdmDepth) {
- return screen->depth();
- } else if (m == PdmDpiX) {
- if (d->extra && d->extra->customDpiX)
- return d->extra->customDpiX;
- else if (d->parent)
- return static_cast<QWidget *>(d->parent)->metric(m);
- return qRound(screen->logicalDotsPerInchX());
- } else if (m == PdmDpiY) {
- if (d->extra && d->extra->customDpiY)
- return d->extra->customDpiY;
- else if (d->parent)
- return static_cast<QWidget *>(d->parent)->metric(m);
- return qRound(screen->logicalDotsPerInchY());
- } else if (m == PdmPhysicalDpiX) {
- return qRound(screen->physicalDotsPerInchX());
- } else if (m == PdmPhysicalDpiY) {
- return qRound(screen->physicalDotsPerInchY());
- } else if (m == PdmDevicePixelRatio) {
- return topLevelWindow ? topLevelWindow->devicePixelRatio() : qApp->devicePixelRatio();
- } else {
- val = QPaintDevice::metric(m);// XXX
- }
- return val;
-}
-
-/*!
- If this is a native widget, return the associated QWindow.
- Otherwise return null.
-
- Native widgets include toplevel widgets, QGLWidget, and child widgets
- on which winId() was called.
-
- \since 5.0
-
- \sa winId()
-*/
-QWindow *QWidget::windowHandle() const
-{
- Q_D(const QWidget);
- QTLWExtra *extra = d->maybeTopData();
- if (extra)
- return extra->window;
-
- return 0;
-}
-
-void QWidgetPrivate::createSysExtra()
-{
-}
-
-void QWidgetPrivate::deleteSysExtra()
-{
-
-}
-
-#ifdef Q_OS_WIN
-static const char activeXNativeParentHandleProperty[] = "_q_embedded_native_parent_handle";
-#endif
-
-void QWidgetPrivate::createTLSysExtra()
-{
- Q_Q(QWidget);
- if (!extra->topextra->window && (q->testAttribute(Qt::WA_NativeWindow) || q->isWindow())) {
- extra->topextra->window = new QWidgetWindow(q);
- if (extra->minw || extra->minh)
- extra->topextra->window->setMinimumSize(QSize(extra->minw, extra->minh));
- if (extra->maxw != QWIDGETSIZE_MAX || extra->maxh != QWIDGETSIZE_MAX)
- extra->topextra->window->setMaximumSize(QSize(extra->maxw, extra->maxh));
- if (extra->topextra->opacity != 255 && q->isWindow())
- extra->topextra->window->setOpacity(qreal(extra->topextra->opacity) / qreal(255));
-#ifdef Q_OS_WIN
- // Pass on native parent handle for Widget embedded into Active X.
- const QVariant activeXNativeParentHandle = q->property(activeXNativeParentHandleProperty);
- if (activeXNativeParentHandle.isValid())
- extra->topextra->window->setProperty(activeXNativeParentHandleProperty, activeXNativeParentHandle);
- if (q->inherits("QTipLabel") || q->inherits("QAlphaWidget"))
- extra->topextra->window->setProperty("_q_windowsDropShadow", QVariant(true));
-#endif
- }
-
-}
-
-void QWidgetPrivate::deleteTLSysExtra()
-{
- if (extra && extra->topextra) {
- //the qplatformbackingstore may hold a reference to the window, so the backingstore
- //needs to be deleted first. If the backingstore holds GL resources, we need to
- // make the context current here, since the platform bs does not have a reference
- // to the widget.
-
-#ifndef QT_NO_OPENGL
- if (textureChildSeen && extra->topextra->shareContext)
- extra->topextra->shareContext->makeCurrent(extra->topextra->window);
-#endif
- extra->topextra->backingStoreTracker.destroy();
- delete extra->topextra->backingStore;
- extra->topextra->backingStore = 0;
-#ifndef QT_NO_OPENGL
- if (textureChildSeen && extra->topextra->shareContext)
- extra->topextra->shareContext->doneCurrent();
- delete extra->topextra->shareContext;
- extra->topextra->shareContext = 0;
-#endif
-
- //the toplevel might have a context with a "qglcontext associated with it. We need to
- //delete the qglcontext before we delete the qplatformopenglcontext.
- //One unfortunate thing about this is that we potentially create a glContext just to
- //delete it straight afterwards.
- if (extra->topextra->window) {
- extra->topextra->window->destroy();
- }
- setWinId(0);
- delete extra->topextra->window;
- extra->topextra->window = 0;
-
- }
-}
-
-void QWidgetPrivate::registerDropSite(bool on)
-{
- Q_UNUSED(on);
-}
-
-void QWidgetPrivate::setMask_sys(const QRegion &region)
-{
- if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowMasks)) {
- qWarning("%s: Not supported on %s.", Q_FUNC_INFO, qPrintable(QGuiApplication::platformName()));
- return;
- }
- Q_Q(QWidget);
- if (const QWindow *window = q->windowHandle())
- if (QPlatformWindow *platformWindow = window->handle())
- platformWindow->setMask(region);
-}
-
-void QWidgetPrivate::updateFrameStrut()
-{
- Q_Q(QWidget);
- if (q->data->fstrut_dirty) {
- if (QTLWExtra *te = maybeTopData()) {
- if (te->window) {
- if (const QPlatformWindow *pw = te->window->handle()) {
- const QMargins margins = pw->frameMargins();
- if (!margins.isNull()) {
- te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
- q->data->fstrut_dirty = false;
- }
- }
- }
- }
- }
-}
-
-void QWidgetPrivate::setWindowOpacity_sys(qreal level)
-{
- Q_Q(QWidget);
- if (q->windowHandle())
- q->windowHandle()->setOpacity(level);
-}
-
-void QWidgetPrivate::setWSGeometry()
-{
- Q_Q(QWidget);
- if (QWindow *window = q->windowHandle())
- window->setGeometry(data.crect);
-}
-
-QPaintEngine *QWidget::paintEngine() const
-{
- qWarning("QWidget::paintEngine: Should no longer be called");
-
-#ifdef Q_OS_WIN
- // We set this bit which is checked in setAttribute for
- // Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
- //
- // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
- // Windows which would mean suddenly their widgets stop working.
- //
- // 2. Users set paint on screen and subclass paintEngine() to
- // return 0, in which case we have a "hole" in the backingstore
- // allowing use of GDI or DirectX directly.
- //
- // 1 is WRONG, but to minimize silent failures, we have set this
- // bit to ignore the setAttribute call. 2. needs to be
- // supported because its our only means of embedding native
- // graphics stuff.
- const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
-#endif
-
- return 0; //##### @@@
-}
-
-void QWidgetPrivate::setModal_sys()
-{
- Q_Q(QWidget);
- if (q->windowHandle())
- q->windowHandle()->setModality(q->windowModality());
-}
-
-#ifndef QT_NO_CURSOR
-static inline void applyCursor(QWidget *w, QCursor c)
-{
- if (QWindow *window = w->windowHandle())
- window->setCursor(c);
-}
-
-static inline void unsetCursor(QWidget *w)
-{
- if (QWindow *window = w->windowHandle())
- window->unsetCursor();
-}
-
-void qt_qpa_set_cursor(QWidget *w, bool force)
-{
- if (!w->testAttribute(Qt::WA_WState_Created))
- return;
-
- static QPointer<QWidget> lastUnderMouse = 0;
- if (force) {
- lastUnderMouse = w;
- } else if (lastUnderMouse) {
- const WId lastWinId = lastUnderMouse->effectiveWinId();
- const WId winId = w->effectiveWinId();
- if (lastWinId && lastWinId == winId)
- w = lastUnderMouse;
- } else if (!w->internalWinId()) {
- return; // The mouse is not under this widget, and it's not native, so don't change it.
- }
-
- while (!w->internalWinId() && w->parentWidget() && !w->isWindow()
- && !w->testAttribute(Qt::WA_SetCursor))
- w = w->parentWidget();
-
- QWidget *nativeParent = w;
- if (!w->internalWinId())
- nativeParent = w->nativeParentWidget();
- if (!nativeParent || !nativeParent->internalWinId())
- return;
-
- if (w->isWindow() || w->testAttribute(Qt::WA_SetCursor)) {
- if (w->isEnabled())
- applyCursor(nativeParent, w->cursor());
- else
- // Enforce the windows behavior of clearing the cursor on
- // disabled widgets.
- unsetCursor(nativeParent);
- } else {
- unsetCursor(nativeParent);
- }
-}
-#endif //QT_NO_CURSOR
-
-QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qwidgetbackingstore_p.h b/src/widgets/kernel/qwidgetbackingstore_p.h
index 473e9deef4..88404ce205 100644
--- a/src/widgets/kernel/qwidgetbackingstore_p.h
+++ b/src/widgets/kernel/qwidgetbackingstore_p.h
@@ -294,7 +294,6 @@ private:
friend QRegion qt_dirtyRegion(QWidget *);
friend class QWidgetPrivate;
friend class QWidget;
- friend class QETWidget;
friend class QBackingStore;
};
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index fc328e7af0..b255bc16f9 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -40,7 +40,7 @@
****************************************************************************/
#include "private/qwindow_p.h"
-#include "qwidgetwindow_qpa_p.h"
+#include "qwidgetwindow_p.h"
#include "private/qwidget_p.h"
#include "private/qapplication_p.h"
@@ -443,7 +443,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
// Use postEvent() to ensure the local QEventLoop terminates when called from QMenu::exec()
const QPoint localPos = win->mapFromGlobal(event->globalPos());
QMouseEvent *e = new QMouseEvent(QEvent::MouseButtonPress, localPos, localPos, event->globalPos(), event->button(), event->buttons(), event->modifiers());
- e->spont = 1;
+ QCoreApplicationPrivate::setEventSpontaneous(e, true);
QGuiApplicationPrivate::setMouseEventSource(e, QGuiApplicationPrivate::mouseEventSource(event));
e->setTimestamp(event->timestamp());
QCoreApplication::postEvent(win, e);
@@ -795,7 +795,7 @@ void QWidgetWindow::handleTabletEvent(QTabletEvent *event)
QPointF mapped = qt_tablet_target->mapFromGlobal(event->globalPos()) + delta;
QTabletEvent ev(event->type(), mapped, event->globalPosF(), event->device(), event->pointerType(),
event->pressure(), event->xTilt(), event->yTilt(), event->tangentialPressure(),
- event->rotation(), event->z(), event->modifiers(), event->uniqueId());
+ event->rotation(), event->z(), event->modifiers(), event->uniqueId(), event->button(), event->buttons());
ev.setTimestamp(event->timestamp());
QGuiApplication::sendSpontaneousEvent(qt_tablet_target, &ev);
}
diff --git a/src/widgets/kernel/qwidgetwindow_qpa_p.h b/src/widgets/kernel/qwidgetwindow_p.h
index 06ba8ea646..be2adddff5 100644
--- a/src/widgets/kernel/qwidgetwindow_qpa_p.h
+++ b/src/widgets/kernel/qwidgetwindow_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QWIDGETWINDOW_QPA_P_H
-#define QWIDGETWINDOW_QPA_P_H
+#ifndef QWIDGETWINDOW_P_H
+#define QWIDGETWINDOW_P_H
#include <QtGui/qwindow.h>
@@ -122,4 +122,4 @@ private:
QT_END_NAMESPACE
-#endif // QWIDGETWINDOW_QPA_P_H
+#endif // QWIDGETWINDOW_P_H
diff --git a/src/widgets/statemachine/qguistatemachine.cpp b/src/widgets/statemachine/qguistatemachine.cpp
index d737a1e323..9824b96334 100644
--- a/src/widgets/statemachine/qguistatemachine.cpp
+++ b/src/widgets/statemachine/qguistatemachine.cpp
@@ -312,6 +312,8 @@ static QEvent *cloneEvent(QEvent *e)
me2->setButtons(me->buttons());
me2->setButton(me->button());
me2->setModifiers(me->modifiers());
+ me2->setSource(me->source());
+ me2->setFlags(me->flags());
return me2;
}
diff --git a/src/widgets/styles/qandroidstyle.cpp b/src/widgets/styles/qandroidstyle.cpp
index ceb95aa125..9f241c42e1 100644
--- a/src/widgets/styles/qandroidstyle.cpp
+++ b/src/widgets/styles/qandroidstyle.cpp
@@ -118,6 +118,7 @@ QAndroidStyle::QAndroidStyle()
: QFusionStyle()
{
QPixmapCache::clear();
+ checkBoxControl = NULL;
QString stylePath(QLatin1String(qgetenv("MINISTRO_ANDROID_STYLE_PATH")));
const QLatin1Char slashChar('/');
if (!stylePath.isEmpty() && !stylePath.endsWith(slashChar))
@@ -127,8 +128,7 @@ QAndroidStyle::QAndroidStyle()
if (!androidTheme.isEmpty() && !androidTheme.endsWith(slashChar))
androidTheme += slashChar;
- if (stylePath.isEmpty())
- {
+ if (stylePath.isEmpty()) {
stylePath = QLatin1String("/data/data/org.kde.necessitas.ministro/files/dl/style/")
+ QLatin1String(qgetenv("QT_ANDROID_THEME_DISPLAY_DPI")) + slashChar;
}
@@ -143,7 +143,7 @@ QAndroidStyle::QAndroidStyle()
QJsonParseError error;
QJsonDocument document = QJsonDocument::fromJson(f.readAll(), &error);
- if (document.isNull()) {
+ if (document.isNull()) {
qCritical() << error.errorString();
return;
}
@@ -155,8 +155,8 @@ QAndroidStyle::QAndroidStyle()
QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
- QHash<int, QPalette> * palettes = reinterpret_cast<QHash<int, QPalette> *>(nativeInterface->nativeResourceForIntegration("AndroidStylePalettes"));
- QHash<int, QFont> * fonts = reinterpret_cast<QHash<int, QFont> *>(nativeInterface->nativeResourceForIntegration("AndroidStyleFonts"));
+ QHash<int, QPalette> *palettes = reinterpret_cast<QHash<int, QPalette> *>(nativeInterface->nativeResourceForIntegration("AndroidStylePalettes"));
+ QHash<int, QFont> *fonts = reinterpret_cast<QHash<int, QFont> *>(nativeInterface->nativeResourceForIntegration("AndroidStyleFonts"));
palettes->clear();
fonts->clear();
QJsonObject object = document.object();
@@ -214,7 +214,7 @@ QAndroidStyle::QAndroidStyle()
}
if (!qtClassName.isEmpty())
QApplication::setFont(font, qtClassName.toUtf8());
- if (ft>-1)
+ if (ft > -1)
fonts->insert(ft, font);
// Extract font information
}
@@ -256,6 +256,9 @@ QAndroidStyle::QAndroidStyle()
switch (itemType) {
case QC_Checkbox:
+ checkBoxControl = new AndroidCompoundButtonControl(item.toVariantMap(), itemType);
+ m_androidControlsHash[int(itemType)] = checkBoxControl;
+ break;
case QC_RadioButton:
m_androidControlsHash[int(itemType)] = new AndroidCompoundButtonControl(item.toVariantMap(),
itemType);
@@ -516,16 +519,31 @@ void QAndroidStyle::drawPrimitive(PrimitiveElement pe,
? m_androidControlsHash.find(itemType)
: m_androidControlsHash.end();
if (it != m_androidControlsHash.end()) {
- if (itemType != QC_EditText)
+ if (itemType != QC_EditText) {
it.value()->drawControl(opt, p, w);
- else {
+ } else {
QStyleOption copy(*opt);
copy.state &= ~QStyle::State_Sunken;
it.value()->drawControl(&copy, p, w);
}
- }
- else
+ } else if (pe == PE_FrameGroupBox) {
+ if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
+ const QStyleOptionFrameV2 *frame2 = qstyleoption_cast<const QStyleOptionFrameV2 *>(opt);
+ if (frame2 && (frame2->features & QStyleOptionFrameV2::Flat)) {
+ QRect fr = frame->rect;
+ QPoint p1(fr.x(), fr.y() + 1);
+ QPoint p2(fr.x() + fr.width(), p1.y());
+ qDrawShadeLine(p, p1, p2, frame->palette, true,
+ frame->lineWidth, frame->midLineWidth);
+ } else {
+ qDrawShadeRect(p, frame->rect.x(), frame->rect.y(), frame->rect.width(),
+ frame->rect.height(), frame->palette, true,
+ frame->lineWidth, frame->midLineWidth);
+ }
+ }
+ } else {
QFusionStyle::drawPrimitive(pe, opt, p, w);
+ }
}
@@ -575,6 +593,36 @@ void QAndroidStyle::drawControl(QStyle::ControlElement element,
default:
break;
}
+ } else if (element == CE_ItemViewItem) {
+ const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt);
+ if (vopt && vopt->features & QStyleOptionViewItem::HasCheckIndicator) {
+ p->save();
+ p->setClipRect(opt->rect);
+
+ QRect checkRect = proxy()->subElementRect(SE_ItemViewItemCheckIndicator, vopt, w);
+
+ // draw the background
+ proxy()->drawPrimitive(PE_PanelItemViewItem, opt, p, w);
+
+ // draw the check mark
+ QStyleOptionViewItem option(*vopt);
+ option.rect = checkRect;
+ option.state = option.state & ~QStyle::State_HasFocus;
+
+ switch (vopt->checkState) {
+ case Qt::Unchecked:
+ option.state |= QStyle::State_Off;
+ break;
+ default:
+ option.state |= QStyle::State_On;
+ break;
+ }
+ QPixmap pixmap = checkBoxControl->imgCheckBox(&option);
+ p->drawPixmap(checkRect, pixmap);
+ p->restore();
+ } else {
+ QFusionStyle::drawControl(element, opt, p, w);
+ }
} else {
QFusionStyle::drawControl(element, opt, p, w);
}
@@ -584,6 +632,8 @@ QRect QAndroidStyle::subElementRect(SubElement subElement,
const QStyleOption *option,
const QWidget *widget) const
{
+ if (subElement == SE_LineEditContents) // fix spinbox display problem
+ return QFusionStyle::subElementRect(subElement, option, widget);
const ItemType itemType = qtControl(subElement);
AndroidControlsHash::const_iterator it = itemType != QC_UnknownType
? m_androidControlsHash.find(itemType)
@@ -602,10 +652,74 @@ void QAndroidStyle::drawComplexControl(ComplexControl cc,
AndroidControlsHash::const_iterator it = itemType != QC_UnknownType
? m_androidControlsHash.find(itemType)
: m_androidControlsHash.end();
- if (it != m_androidControlsHash.end())
+ if (it != m_androidControlsHash.end()) {
it.value()->drawControl(opt, p, widget);
- else
- QFusionStyle::drawComplexControl(cc, opt, p, widget);
+ return;
+ }
+ if (cc == CC_GroupBox) {
+ if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
+ // Draw frame
+ QRect textRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, widget);
+ QRect checkBoxRect;
+ if (groupBox->subControls & SC_GroupBoxCheckBox)
+ checkBoxRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxCheckBox, widget);
+ if (groupBox->subControls & QStyle::SC_GroupBoxFrame) {
+ QStyleOptionFrameV2 frame;
+ frame.QStyleOption::operator=(*groupBox);
+ frame.features = groupBox->features;
+ frame.lineWidth = groupBox->lineWidth;
+ frame.midLineWidth = groupBox->midLineWidth;
+ frame.rect = subControlRect(CC_GroupBox, opt, SC_GroupBoxFrame, widget);
+ p->save();
+ QRegion region(groupBox->rect);
+ if (!groupBox->text.isEmpty()) {
+ bool ltr = groupBox->direction == Qt::LeftToRight;
+ QRect finalRect;
+ if (groupBox->subControls & QStyle::SC_GroupBoxCheckBox) {
+ finalRect = checkBoxRect.united(textRect);
+ finalRect.adjust(ltr ? -4 : 0, 0, ltr ? 0 : 4, 0);
+ } else {
+ finalRect = textRect;
+ }
+ region -= finalRect;
+ }
+ p->setClipRegion(region);
+ drawPrimitive(PE_FrameGroupBox, &frame, p, widget);
+ p->restore();
+ }
+
+ // Draw title
+ if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) {
+ QColor textColor = groupBox->textColor;
+ if (textColor.isValid())
+ p->setPen(textColor);
+ int alignment = int(groupBox->textAlignment);
+ if (!styleHint(QStyle::SH_UnderlineShortcut, opt, widget))
+ alignment |= Qt::TextHideMnemonic;
+
+ drawItemText(p, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | alignment,
+ groupBox->palette, groupBox->state & State_Enabled, groupBox->text,
+ textColor.isValid() ? QPalette::NoRole : QPalette::WindowText);
+
+ if (groupBox->state & State_HasFocus) {
+ QStyleOptionFocusRect fropt;
+ fropt.QStyleOption::operator=(*groupBox);
+ fropt.rect = textRect;
+ drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
+ }
+ }
+
+ // Draw checkbox
+ if (groupBox->subControls & SC_GroupBoxCheckBox) {
+ QStyleOptionButton box;
+ box.QStyleOption::operator=(*groupBox);
+ box.rect = checkBoxRect;
+ checkBoxControl->drawControl(&box, p, widget);
+ }
+ }
+ return;
+ }
+ QFusionStyle::drawComplexControl(cc, opt, p, widget);
}
QStyle::SubControl QAndroidStyle::hitTestComplexControl(ComplexControl cc,
@@ -649,6 +763,52 @@ QRect QAndroidStyle::subControlRect(ComplexControl cc,
: m_androidControlsHash.end();
if (it != m_androidControlsHash.end())
return it.value()->subControlRect(opt, sc, widget);
+ QRect rect = opt->rect;
+ switch (cc) {
+ case CC_GroupBox: {
+ if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
+ QSize textSize = opt->fontMetrics.boundingRect(groupBox->text).size() + QSize(2, 2);
+ QSize checkBoxSize = checkBoxControl->sizeCheckBox(opt);
+ int indicatorWidth = checkBoxSize.width();
+ int indicatorHeight = checkBoxSize.height();
+ QRect checkBoxRect;
+ if (opt->subControls & QStyle::SC_GroupBoxCheckBox) {
+ checkBoxRect.setWidth(indicatorWidth);
+ checkBoxRect.setHeight(indicatorHeight);
+ }
+ checkBoxRect.moveLeft(1);
+ QRect textRect = checkBoxRect;
+ textRect.setSize(textSize);
+ if (opt->subControls & QStyle::SC_GroupBoxCheckBox)
+ textRect.translate(indicatorWidth + 5, (indicatorHeight - textSize.height()) / 2);
+ if (sc == SC_GroupBoxFrame) {
+ rect = opt->rect.adjusted(0, 0, 0, 0);
+ rect.translate(0, textRect.height() / 2);
+ rect.setHeight(rect.height() - textRect.height() / 2);
+ } else if (sc == SC_GroupBoxContents) {
+ QRect frameRect = opt->rect.adjusted(0, 0, 0, -groupBox->lineWidth);
+ int margin = 3;
+ int leftMarginExtension = 0;
+ int topMargin = qMax(pixelMetric(PM_ExclusiveIndicatorHeight), opt->fontMetrics.height()) + groupBox->lineWidth;
+ frameRect.adjust(leftMarginExtension + margin, margin + topMargin, -margin, -margin - groupBox->lineWidth);
+ frameRect.translate(0, textRect.height() / 2);
+ rect = frameRect;
+ rect.setHeight(rect.height() - textRect.height() / 2);
+ } else if (sc == SC_GroupBoxCheckBox) {
+ rect = checkBoxRect;
+ } else if (sc == SC_GroupBoxLabel) {
+ rect = textRect;
+ }
+ return visualRect(opt->direction, opt->rect, rect);
+ }
+
+ return rect;
+ }
+
+ default:
+ break;
+ }
+
return QFusionStyle::subControlRect(cc, opt, sc, widget);
}
@@ -664,6 +824,10 @@ int QAndroidStyle::pixelMetric(PixelMetric metric, const QStyleOption *option,
case PM_SpinBoxFrameWidth:
case PM_ScrollBarExtent:
return 0;
+ case PM_IndicatorWidth:
+ return checkBoxControl->sizeCheckBox(option).width();
+ case PM_IndicatorHeight:
+ return checkBoxControl->sizeCheckBox(option).height();
default:
return QFusionStyle::pixelMetric(metric, option, widget);
}
@@ -676,12 +840,61 @@ QSize QAndroidStyle::sizeFromContents(ContentsType ct,
const QWidget *w) const
{
QSize sz = QFusionStyle::sizeFromContents(ct, opt, contentsSize, w);
+ if (ct == CT_HeaderSection) {
+ if (const QStyleOptionHeader *hdr = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
+ bool nullIcon = hdr->icon.isNull();
+ int margin = pixelMetric(QStyle::PM_HeaderMargin, hdr, w);
+ int iconSize = nullIcon ? 0 : checkBoxControl->sizeCheckBox(opt).width();
+ QSize txt;
+/*
+ * These next 4 lines are a bad hack to fix a bug in case a QStyleSheet is applied at QApplication level.
+ * In that case, even if the stylesheet does not refer to headers, the header font is changed to application
+ * font, which is wrong. Even worst, hdr->fontMetrics(...) does not report the proper size.
+ */
+ if (qApp->styleSheet().isEmpty())
+ txt = hdr->fontMetrics.size(0, hdr->text);
+ else
+ txt = qApp->fontMetrics().size(0, hdr->text);
+
+ sz.setHeight(margin + qMax(iconSize, txt.height()) + margin);
+ sz.setWidth((nullIcon ? 0 : margin) + iconSize
+ + (hdr->text.isNull() ? 0 : margin) + txt.width() + margin);
+ if (hdr->sortIndicator != QStyleOptionHeader::None) {
+ int margin = pixelMetric(QStyle::PM_HeaderMargin, hdr, w);
+ if (hdr->orientation == Qt::Horizontal)
+ sz.rwidth() += sz.height() + margin;
+ else
+ sz.rheight() += sz.width() + margin;
+ }
+ return sz;
+ }
+ }
const ItemType itemType = qtControl(ct);
AndroidControlsHash::const_iterator it = itemType != QC_UnknownType
? m_androidControlsHash.find(itemType)
: m_androidControlsHash.end();
if (it != m_androidControlsHash.end())
return it.value()->sizeFromContents(opt, sz, w);
+ if (ct == CT_GroupBox) {
+ if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
+ QSize textSize = opt->fontMetrics.boundingRect(groupBox->text).size() + QSize(2, 2);
+ QSize checkBoxSize = checkBoxControl->sizeCheckBox(opt);
+ int indicatorWidth = checkBoxSize.width();
+ int indicatorHeight = checkBoxSize.height();
+ QRect checkBoxRect;
+ if (groupBox->subControls & QStyle::SC_GroupBoxCheckBox) {
+ checkBoxRect.setWidth(indicatorWidth);
+ checkBoxRect.setHeight(indicatorHeight);
+ }
+ checkBoxRect.moveLeft(1);
+ QRect textRect = checkBoxRect;
+ textRect.setSize(textSize);
+ if (groupBox->subControls & QStyle::SC_GroupBoxCheckBox)
+ textRect.translate(indicatorWidth + 5, (indicatorHeight - textSize.height()) / 2);
+ QRect u = textRect.united(checkBoxRect);
+ sz = QSize(sz.width(), sz.height() + u.height());
+ }
+ }
return sz;
}
@@ -712,7 +925,7 @@ int QAndroidStyle::styleHint(QStyle::StyleHint hint, const QStyleOption *option,
return RSIP_OnMouseClick;
default:
- return QFusionStyle::styleHint(hint,option, widget, returnData);
+ return QFusionStyle::styleHint(hint, option, widget, returnData);
}
}
@@ -761,6 +974,13 @@ QSize QAndroidStyle::AndroidDrawable::size() const
return QSize();
}
+QPixmap QAndroidStyle::AndroidDrawable::img() const
+{
+ if (type() == Image || type() == NinePatch)
+ return static_cast<const QAndroidStyle::AndroidImageDrawable *>(this)->img();
+
+ return QPixmap();
+}
QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidDrawable::fromMap(const QVariantMap &drawable,
ItemType itemType)
@@ -828,6 +1048,18 @@ void QAndroidStyle::AndroidImageDrawable::draw(QPainter *painter, const QStyleOp
painter->drawPixmap(opt->rect.x(), (opt->rect.height() - pm.height()) / 2, pm);
}
+QPixmap QAndroidStyle::AndroidImageDrawable::img() const
+{
+ if (m_hashKey.isEmpty())
+ m_hashKey = QFileInfo(m_filePath).fileName();
+
+ QPixmap pm;
+ if (!QPixmapCache::find(m_hashKey, &pm)) {
+ pm.load(m_filePath);
+ QPixmapCache::insert(m_hashKey, pm);
+ }
+ return pm;
+}
QSize QAndroidStyle::AndroidImageDrawable::size() const
{
@@ -886,7 +1118,7 @@ void QAndroidStyle::Android9PatchDrawable::extractIntArray(const QVariantList &v
}
-void QAndroidStyle::Android9PatchDrawable::draw(QPainter * painter, const QStyleOption *opt) const
+void QAndroidStyle::Android9PatchDrawable::draw(QPainter *painter, const QStyleOption *opt) const
{
if (m_hashKey.isEmpty())
m_hashKey = QFileInfo(m_filePath).fileName();
@@ -897,7 +1129,7 @@ void QAndroidStyle::Android9PatchDrawable::draw(QPainter * painter, const QStyle
QPixmapCache::insert(m_hashKey, pixmap);
}
- const QRect &bounds=opt->rect;
+ const QRect &bounds = opt->rect;
// shamelessly stolen from Android's sources (NinepatchImpl.cpp) and adapted for Qt
const int pixmapWidth = pixmap.width();
@@ -1052,11 +1284,11 @@ QAndroidStyle::AndroidGradientDrawable::AndroidGradientDrawable(const QVariantMa
QVariantList colors = drawable.value(QLatin1String("colors")).toList();
QVariantList positions = drawable.value(QLatin1String("positions")).toList();
- int min=colors.size() < positions.size() ? colors.size() : positions.size();
+ int min = colors.size() < positions.size() ? colors.size() : positions.size();
for (int i = 0; i < min; i++)
m_gradient.setColorAt(positions.at(i).toDouble(), QRgb(colors.at(i).toInt()));
- QByteArray orientation=drawable.value(QLatin1String("orientation")).toByteArray();
+ QByteArray orientation = drawable.value(QLatin1String("orientation")).toByteArray();
if (orientation == "TOP_BOTTOM") // draw the gradient from the top to the bottom
m_orientation = TOP_BOTTOM;
else if (orientation == "TR_BL") // draw the gradient from the top-right to the bottom-left
@@ -1089,43 +1321,43 @@ void QAndroidStyle::AndroidGradientDrawable::draw(QPainter *painter, const QStyl
switch (m_orientation) {
case TOP_BOTTOM:
// draw the gradient from the top to the bottom
- m_gradient.setStart(width/2,0);
- m_gradient.setFinalStop(width/2,height);
+ m_gradient.setStart(width / 2, 0);
+ m_gradient.setFinalStop(width / 2, height);
break;
case TR_BL:
// draw the gradient from the top-right to the bottom-left
- m_gradient.setStart(width,0);
- m_gradient.setFinalStop(0,height);
+ m_gradient.setStart(width, 0);
+ m_gradient.setFinalStop(0, height);
break;
case RIGHT_LEFT:
// draw the gradient from the right to the left
- m_gradient.setStart(width,height/2);
- m_gradient.setFinalStop(0,height/2);
+ m_gradient.setStart(width, height / 2);
+ m_gradient.setFinalStop(0, height / 2);
break;
case BR_TL:
// draw the gradient from the bottom-right to the top-left
- m_gradient.setStart(width,height);
- m_gradient.setFinalStop(0,0);
+ m_gradient.setStart(width, height);
+ m_gradient.setFinalStop(0, 0);
break;
case BOTTOM_TOP:
// draw the gradient from the bottom to the top
- m_gradient.setStart(width/2,height);
- m_gradient.setFinalStop(width/2,0);
+ m_gradient.setStart(width / 2, height);
+ m_gradient.setFinalStop(width / 2, 0);
break;
case BL_TR:
// draw the gradient from the bottom-left to the top-right
- m_gradient.setStart(0,height);
- m_gradient.setFinalStop(width,0);
+ m_gradient.setStart(0, height);
+ m_gradient.setFinalStop(width, 0);
break;
case LEFT_RIGHT:
// draw the gradient from the left to the right
- m_gradient.setStart(0,height/2);
- m_gradient.setFinalStop(width,height/2);
+ m_gradient.setStart(0, height / 2);
+ m_gradient.setFinalStop(width, height / 2);
break;
case TL_BR:
// draw the gradient from the top-left to the bottom-right
- m_gradient.setStart(0,0);
- m_gradient.setFinalStop(width,height);
+ m_gradient.setStart(0, 0);
+ m_gradient.setFinalStop(width, height);
break;
}
@@ -1140,7 +1372,7 @@ void QAndroidStyle::AndroidGradientDrawable::draw(QPainter *painter, const QStyl
QSize QAndroidStyle::AndroidGradientDrawable::size() const
{
- return QSize(m_radius*2, m_radius*2);
+ return QSize(m_radius * 2, m_radius * 2);
}
QAndroidStyle::AndroidClipDrawable::AndroidClipDrawable(const QVariantMap &drawable,
@@ -1172,9 +1404,9 @@ void QAndroidStyle::AndroidClipDrawable::draw(QPainter *painter, const QStyleOpt
{
QStyleOption copy(*opt);
if (m_orientation == Qt::Horizontal)
- copy.rect.setWidth(copy.rect.width()*m_factor);
+ copy.rect.setWidth(copy.rect.width() * m_factor);
else
- copy.rect.setHeight(copy.rect.height()*m_factor);
+ copy.rect.setHeight(copy.rect.height() * m_factor);
m_drawable->draw(painter, &copy);
}
@@ -1212,12 +1444,28 @@ QAndroidStyle::AndroidDrawableType QAndroidStyle::AndroidStateDrawable::type() c
void QAndroidStyle::AndroidStateDrawable::draw(QPainter *painter, const QStyleOption *opt) const
{
- const AndroidDrawable *drawable=bestAndroidStateMatch(opt);
+ const AndroidDrawable *drawable = bestAndroidStateMatch(opt);
if (drawable)
drawable->draw(painter, opt);
}
+QSize QAndroidStyle::AndroidStateDrawable::sizeImage(const QStyleOption *opt) const
+{
+ QSize s;
+ const AndroidDrawable *drawable = bestAndroidStateMatch(opt);
+ if (drawable)
+ s = drawable->size();
+ return s;
+}
+QPixmap QAndroidStyle::AndroidStateDrawable::img(const QStyleOption *opt) const
+{
+ QPixmap pm;
+ const AndroidDrawable *drawable = bestAndroidStateMatch(opt);
+ if (drawable)
+ pm = drawable->img();
+ return pm;
+}
-const QAndroidStyle::AndroidDrawable* QAndroidStyle::AndroidStateDrawable::bestAndroidStateMatch(const QStyleOption *opt) const
+const QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidStateDrawable::bestAndroidStateMatch(const QStyleOption *opt) const
{
const AndroidDrawable *bestMatch = 0;
if (!opt) {
@@ -1226,7 +1474,7 @@ const QAndroidStyle::AndroidDrawable* QAndroidStyle::AndroidStateDrawable::bestA
return bestMatch;
}
- uint bestCost=0xffff;
+ uint bestCost = 0xffff;
foreach (const StateType & state, m_states) {
if (int(opt->state) == state.first)
return state.second;
@@ -1376,15 +1624,13 @@ void QAndroidStyle::AndroidLayerDrawable::setFactor(int id, double factor, Qt::O
void QAndroidStyle::AndroidLayerDrawable::draw(QPainter *painter, const QStyleOption *opt) const
{
- foreach (const LayerType &layer, m_layers)
- {
- if (layer.first == m_id)
- {
+ foreach (const LayerType &layer, m_layers) {
+ if (layer.first == m_id) {
QStyleOption copy(*opt);
if (m_orientation == Qt::Horizontal)
- copy.rect.setWidth(copy.rect.width()*m_factor);
+ copy.rect.setWidth(copy.rect.width() * m_factor);
else
- copy.rect.setHeight(copy.rect.height()*m_factor);
+ copy.rect.setHeight(copy.rect.height() * m_factor);
layer.second->draw(painter, &copy);
} else {
layer.second->draw(painter, opt);
@@ -1418,7 +1664,7 @@ QAndroidStyle::AndroidControl::AndroidControl(const QVariantMap &control,
m_background = 0;
it = control.find(QLatin1String("View_minWidth"));
- if (it!=control.end())
+ if (it != control.end())
m_minSize.setWidth(it.value().toInt());
it = control.find(QLatin1String("View_minHeight"));
@@ -1534,10 +1780,9 @@ QSize QAndroidStyle::AndroidControl::sizeFromContents(const QStyleOption *opt,
QMargins QAndroidStyle::AndroidControl::padding()
{
- if (const AndroidDrawable *drawable = m_background)
- {
+ if (const AndroidDrawable *drawable = m_background) {
if (drawable->type() == State)
- drawable=static_cast<const AndroidStateDrawable *>(m_background)->bestAndroidStateMatch(0);
+ drawable = static_cast<const AndroidStateDrawable *>(m_background)->bestAndroidStateMatch(0);
return drawable->padding();
}
return QMargins();
@@ -1573,8 +1818,17 @@ void QAndroidStyle::AndroidCompoundButtonControl::drawControl(const QStyleOption
if (m_button)
m_button->draw(p, opt);
}
-
-const QAndroidStyle::AndroidDrawable *QAndroidStyle::AndroidCompoundButtonControl::backgroundDrawable() const
+QSize QAndroidStyle::AndroidCompoundButtonControl::sizeCheckBox(const QStyleOption *opt) const
+{
+ const AndroidDrawable *drawable = m_button;
+ return static_cast<const QAndroidStyle::AndroidStateDrawable *>(drawable)->sizeImage(opt);
+}
+QPixmap QAndroidStyle::AndroidCompoundButtonControl::imgCheckBox(const QStyleOption *opt) const
+{
+ const AndroidDrawable *drawable = m_button;
+ return static_cast<const QAndroidStyle::AndroidStateDrawable *>(drawable)->img(opt);
+}
+const QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidCompoundButtonControl::backgroundDrawable() const
{
return m_background ? m_background : m_button;
}
@@ -1637,10 +1891,10 @@ void QAndroidStyle::AndroidProgressBarControl::drawControl(const QStyleOption *o
if (m_progressDrawable->type() == QAndroidStyle::Layer) {
QAndroidStyle::AndroidDrawable *clipDrawable = static_cast<QAndroidStyle::AndroidLayerDrawable *>(m_progressDrawable)->layer(m_progressId);
if (clipDrawable->type() == QAndroidStyle::Clip)
- static_cast<QAndroidStyle::AndroidClipDrawable *>(clipDrawable)->setFactor(double(progressBarV2.progress)/double(progressBarV2.maximum-progressBarV2.minimum),
+ static_cast<QAndroidStyle::AndroidClipDrawable *>(clipDrawable)->setFactor(double(progressBarV2.progress) / double(progressBarV2.maximum - progressBarV2.minimum),
progressBarV2.orientation);
else
- static_cast<QAndroidStyle::AndroidLayerDrawable *>(m_progressDrawable)->setFactor(m_progressId,double(progressBarV2.progress)/double(progressBarV2.maximum-progressBarV2.minimum),
+ static_cast<QAndroidStyle::AndroidLayerDrawable *>(m_progressDrawable)->setFactor(m_progressId, double(progressBarV2.progress) / double(progressBarV2.maximum - progressBarV2.minimum),
progressBarV2.orientation);
}
m_progressDrawable->draw(p, option);
@@ -1659,11 +1913,11 @@ QRect QAndroidStyle::AndroidProgressBarControl::subElementRect(QStyle::SubElemen
return option->rect;
QMargins padding = m_background->padding();
- QRect p(padding.left(), padding.top(), padding.right()-padding.left(), padding.bottom()-padding.top());
+ QRect p(padding.left(), padding.top(), padding.right() - padding.left(), padding.bottom() - padding.top());
padding = m_indeterminateDrawable->padding();
- p |= QRect(padding.left(), padding.top(), padding.right()-padding.left(), padding.bottom()-padding.top());
+ p |= QRect(padding.left(), padding.top(), padding.right() - padding.left(), padding.bottom() - padding.top());
padding = m_progressDrawable->padding();
- p |= QRect(padding.left(), padding.top(), padding.right()-padding.left(), padding.bottom()-padding.top());
+ p |= QRect(padding.left(), padding.top(), padding.right() - padding.left(), padding.bottom() - padding.top());
QRect r = option->rect.adjusted(p.left(), p.top(), -p.right(), -p.bottom());
@@ -1734,26 +1988,27 @@ void QAndroidStyle::AndroidSeekBarControl::drawControl(const QStyleOption *optio
if (const QStyleOptionSlider *styleOption =
qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- double factor = double(styleOption->sliderPosition)/double(styleOption->maximum-styleOption->minimum);
- if (m_progressDrawable->type()==QAndroidStyle::Layer) {
+ double factor = double(styleOption->sliderPosition - styleOption->minimum)
+ / double(styleOption->maximum - styleOption->minimum);
+ if (m_progressDrawable->type() == QAndroidStyle::Layer) {
QAndroidStyle::AndroidDrawable *clipDrawable = static_cast<QAndroidStyle::AndroidLayerDrawable *>(m_progressDrawable)->layer(m_progressId);
if (clipDrawable->type() == QAndroidStyle::Clip)
static_cast<QAndroidStyle::AndroidClipDrawable *>(clipDrawable)->setFactor(factor, styleOption->orientation);
else
static_cast<QAndroidStyle::AndroidLayerDrawable *>(m_progressDrawable)->setFactor(m_progressId, factor, styleOption->orientation);
}
- const AndroidDrawable *drawable=m_seekBarThumb;
+ const AndroidDrawable *drawable = m_seekBarThumb;
if (drawable->type() == State)
drawable = static_cast<const QAndroidStyle::AndroidStateDrawable *>(m_seekBarThumb)->bestAndroidStateMatch(option);
QStyleOption copy(*option);
- copy.rect.setY((copy.rect.height()-m_minSize.height())/2);
+ copy.rect.setY((copy.rect.height() - m_minSize.height()) / 2);
copy.rect.setHeight(m_minSize.height());
copy.rect.setWidth(copy.rect.width() - drawable->size().width());
- copy.rect.translate(drawable->size().width()/2, 0);
+ copy.rect.translate(drawable->size().width() / 2, 0);
m_progressDrawable->draw(p, &copy);
if (styleOption->orientation == Qt::Vertical)
qCritical() << "Vertical slider are not supported";
- int pos = copy.rect.width()*factor - drawable->size().width()/2;
+ int pos = copy.rect.width()*factor - drawable->size().width() / 2;
copy.rect.translate(pos, 0);
copy.rect.setSize(drawable->size());
m_seekBarThumb->draw(p, &copy);
@@ -1767,7 +2022,7 @@ QSize QAndroidStyle::AndroidSeekBarControl::sizeFromContents(const QStyleOption
QSize sz = AndroidProgressBarControl::sizeFromContents(opt, contentsSize, w);
if (!m_seekBarThumb)
return sz;
- const AndroidDrawable *drawable=m_seekBarThumb;
+ const AndroidDrawable *drawable = m_seekBarThumb;
if (drawable->type() == State)
drawable = static_cast<const QAndroidStyle::AndroidStateDrawable *>(m_seekBarThumb)->bestAndroidStateMatch(opt);
return sz.expandedTo(drawable->size());
@@ -1786,7 +2041,8 @@ QRect QAndroidStyle::AndroidSeekBarControl::subControlRect(const QStyleOptionCom
drawable = static_cast<const QAndroidStyle::AndroidStateDrawable *>(m_seekBarThumb)->bestAndroidStateMatch(option);
QRect r(option->rect);
- double factor = double(styleOption->sliderPosition) / (styleOption->maximum - styleOption->minimum);
+ double factor = double(styleOption->sliderPosition - styleOption->minimum)
+ / (styleOption->maximum - styleOption->minimum);
int pos = option->rect.width() * factor - double(drawable->size().width() / 2);
r.setX(r.x() + pos);
r.setSize(drawable->size());
diff --git a/src/widgets/styles/qandroidstyle_p.h b/src/widgets/styles/qandroidstyle_p.h
index d64e37b9db..5334882908 100644
--- a/src/widgets/styles/qandroidstyle_p.h
+++ b/src/widgets/styles/qandroidstyle_p.h
@@ -132,6 +132,7 @@ public:
static AndroidDrawable *fromMap(const QVariantMap &drawable, ItemType itemType);
static QMargins extractMargins(const QVariantMap &value);
virtual void setPaddingLeftToSizeWidth();
+ QPixmap img() const;
protected:
ItemType m_itemType;
QMargins m_padding;
@@ -156,6 +157,7 @@ public:
virtual void draw(QPainter *painter,const QStyleOption *opt) const;
virtual QSize size() const;
+ QPixmap img() const;
protected:
QString m_filePath;
mutable QString m_hashKey;
@@ -228,7 +230,8 @@ public:
inline const AndroidDrawable *bestAndroidStateMatch(const QStyleOption *opt) const;
static int extractState(const QVariantMap &value);
virtual void setPaddingLeftToSizeWidth();
-
+ QSize sizeImage(const QStyleOption *opt) const;
+ QPixmap img(const QStyleOption *opt) const;
private:
typedef QPair<int, const AndroidDrawable *> StateType;
QList<StateType> m_states;
@@ -281,7 +284,8 @@ public:
AndroidCompoundButtonControl(const QVariantMap &control, ItemType itemType);
virtual ~AndroidCompoundButtonControl();
virtual void drawControl(const QStyleOption *opt, QPainter *p, const QWidget *w);
-
+ QSize sizeCheckBox(const QStyleOption *opt) const;
+ QPixmap imgCheckBox(const QStyleOption *opt) const;
protected:
virtual const AndroidDrawable * backgroundDrawable() const;
const AndroidDrawable *m_button;
@@ -387,6 +391,7 @@ private:
typedef QHash<int, AndroidControl *> AndroidControlsHash;
AndroidControlsHash m_androidControlsHash;
QPalette m_standardPalette;
+ AndroidCompoundButtonControl *checkBoxControl;
};
#endif // QT_NO_STYLE_ANDROID
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index d7030c5d72..94498f48c9 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -4930,6 +4930,9 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget
ret = hint.toChar().unicode();
break;
}
+ case SH_LineEdit_PasswordMaskDelay:
+ ret = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::PasswordMaskDelay).toInt();
+ break;
case SH_ToolBox_SelectedPageTitleBold:
ret = 1;
break;
diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp
index 82c53def7d..8db563379a 100644
--- a/src/widgets/styles/qfusionstyle.cpp
+++ b/src/widgets/styles/qfusionstyle.cpp
@@ -749,6 +749,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
painter->drawRect(rect);
QColor checkMarkColor = option->palette.text().color().darker(120);
+ const int checkMarkPadding = QStyleHelper::dpiScaled(3);
if (checkbox->state & State_NoChange) {
gradient = QLinearGradient(rect.topLeft(), rect.bottomLeft());
@@ -759,10 +760,10 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
checkMarkColor.setAlpha(180);
painter->setPen(QPen(checkMarkColor, 1));
painter->setBrush(gradient);
- painter->drawRect(rect.adjusted(3, 3, -3, -3));
+ painter->drawRect(rect.adjusted(checkMarkPadding, checkMarkPadding, -checkMarkPadding, -checkMarkPadding));
} else if (checkbox->state & (State_On)) {
- QPen checkPen = QPen(checkMarkColor, 1.8);
+ QPen checkPen = QPen(checkMarkColor, QStyleHelper::dpiScaled(1.8));
checkMarkColor.setAlpha(210);
painter->translate(-1, 0.5);
painter->setPen(checkPen);
@@ -771,9 +772,9 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
// Draw checkmark
QPainterPath path;
- path.moveTo(5, rect.height() / 2.0);
- path.lineTo(rect.width() / 2.0 - 0, rect.height() - 3);
- path.lineTo(rect.width() - 2.5, 3);
+ path.moveTo(2 + checkMarkPadding, rect.height() / 2.0);
+ path.lineTo(rect.width() / 2.0, rect.height() - checkMarkPadding);
+ path.lineTo(rect.width() - checkMarkPadding - 0.5, checkMarkPadding);
painter->drawPath(path.translated(rect.topLeft()));
}
}
@@ -786,7 +787,9 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
painter->setBrush((state & State_Sunken) ? pressedColor : option->palette.base().color());
painter->setRenderHint(QPainter::Antialiasing, true);
QPainterPath circle;
- circle.addEllipse(rect.center() + QPoint(1.0, 1.0), 6.5, 6.5);
+ const QPointF circleCenter = rect.center() + QPoint(1, 1);
+ const qreal outlineRadius = (rect.width() + (rect.width() + 1) % 2) / 2.0 - 1;
+ circle.addEllipse(circleCenter, outlineRadius, outlineRadius);
painter->setPen(QPen(option->palette.background().color().darker(150)));
if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
painter->setPen(QPen(highlightedOutline));
@@ -794,7 +797,8 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
if (state & (State_On )) {
circle = QPainterPath();
- circle.addEllipse(rect.center() + QPoint(1, 1), 2.8, 2.8);
+ const qreal checkmarkRadius = outlineRadius / 2.32;
+ circle.addEllipse(circleCenter, checkmarkRadius, checkmarkRadius);
QColor checkMarkColor = option->palette.text().color().darker(120);
checkMarkColor.setAlpha(200);
painter->setPen(checkMarkColor);
@@ -3016,97 +3020,120 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
*/
int QFusionStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
{
+ int val = -1;
switch (metric) {
case PM_SliderTickmarkOffset:
- return 4;
+ val = 4;
+ break;
case PM_HeaderMargin:
- return 2;
case PM_ToolTipLabelFrameWidth:
- return 2;
+ val = 2;
+ break;
case PM_ButtonDefaultIndicator:
- return 0;
case PM_ButtonShiftHorizontal:
case PM_ButtonShiftVertical:
- return 0;
+ val = 0;
+ break;
case PM_MessageBoxIconSize:
- return 48;
+ val = 48;
+ break;
case PM_ListViewIconSize:
- return 24;
+ val = 24;
+ break;
case PM_DialogButtonsSeparator:
case PM_ScrollBarSliderMin:
- return 26;
+ val = 26;
+ break;
case PM_TitleBarHeight:
- return 24;
+ val = 24;
+ break;
case PM_ScrollBarExtent:
- return 14;
+ val = 14;
+ break;
case PM_SliderThickness:
- return 15;
case PM_SliderLength:
- return 15;
+ val = 15;
+ break;
case PM_DockWidgetTitleMargin:
- return 1;
- case PM_DefaultFrameWidth:
- return 1;
+ val = 1;
+ break;
case PM_SpinBoxFrameWidth:
- return 3;
+ val = 3;
+ break;
case PM_MenuVMargin:
case PM_MenuHMargin:
- return 0;
case PM_MenuPanelWidth:
- return 0;
+ val = 0;
+ break;
case PM_MenuBarItemSpacing:
- return 6;
+ val = 6;
+ break;
case PM_MenuBarVMargin:
- return 0;
case PM_MenuBarHMargin:
- return 0;
case PM_MenuBarPanelWidth:
- return 0;
+ val = 0;
+ break;
case PM_ToolBarHandleExtent:
- return 9;
+ val = 9;
+ break;
case PM_ToolBarItemSpacing:
- return 1;
+ val = 1;
+ break;
case PM_ToolBarFrameWidth:
- return 2;
case PM_ToolBarItemMargin:
- return 2;
+ val = 2;
+ break;
case PM_SmallIconSize:
- return 16;
case PM_ButtonIconSize:
- return 16;
+ val = 16;
+ break;
case PM_DockWidgetTitleBarButtonMargin:
- return 2;
+ val = 2;
+ break;
case PM_MaximumDragDistance:
- return -1;
+ val = -1;
+ break;
case PM_TabCloseIndicatorWidth:
case PM_TabCloseIndicatorHeight:
- return 20;
+ val = 20;
+ break;
case PM_TabBarTabVSpace:
- return 12;
+ val = 12;
+ break;
case PM_TabBarTabOverlap:
- return 1;
+ val = 1;
+ break;
case PM_TabBarBaseOverlap:
- return 2;
+ val = 2;
+ break;
case PM_SubMenuOverlap:
- return -1;
+ val = -1;
+ break;
case PM_DockWidgetHandleExtent:
case PM_SplitterWidth:
- return 4;
+ val = 4;
+ break;
case PM_IndicatorHeight:
case PM_IndicatorWidth:
case PM_ExclusiveIndicatorHeight:
case PM_ExclusiveIndicatorWidth:
- return 14;
+ val = 14;
+ break;
case PM_ScrollView_ScrollBarSpacing:
- return 0;
+ val = 0;
+ break;
case PM_ScrollView_ScrollBarOverlap:
if (proxy()->styleHint(SH_ScrollBar_Transient, option, widget))
return proxy()->pixelMetric(PM_ScrollBarExtent, option, widget);
- return 0;
- default:
+ val = 0;
break;
+ case PM_DefaultFrameWidth:
+ return 1; // Do not dpi-scale because the drawn frame is always exactly 1 pixel thick
+ break;
+ default:
+ return QCommonStyle::pixelMetric(metric, option, widget);
}
- return QCommonStyle::pixelMetric(metric, option, widget);
+ return QStyleHelper::dpiScaled(val);
}
/*!
@@ -3309,14 +3336,15 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom
break;
case SC_SliderGroove: {
QPoint grooveCenter = slider->rect.center();
+ const int grooveThickness = QStyleHelper::dpiScaled(7);
if (slider->orientation == Qt::Horizontal) {
- rect.setHeight(7);
+ rect.setHeight(grooveThickness);
if (slider->tickPosition & QSlider::TicksAbove)
grooveCenter.ry() += tickSize;
if (slider->tickPosition & QSlider::TicksBelow)
grooveCenter.ry() -= tickSize;
} else {
- rect.setWidth(7);
+ rect.setWidth(grooveThickness);
if (slider->tickPosition & QSlider::TicksAbove)
grooveCenter.rx() += tickSize;
if (slider->tickPosition & QSlider::TicksBelow)
@@ -3332,27 +3360,25 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom
break;
case CC_SpinBox:
if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
- QSize bs;
int center = spinbox->rect.height() / 2;
- int fw = spinbox->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
+ int fw = spinbox->frame ? 3 : 0; // Is drawn with 3 pixels width in drawComplexControl, independently from PM_SpinBoxFrameWidth
int y = fw;
- bs.setHeight(qMax(8, spinbox->rect.height()/2 - y));
- bs.setWidth(14);
+ const int buttonWidth = QStyleHelper::dpiScaled(14);
int x, lx, rx;
- x = spinbox->rect.width() - y - bs.width() + 2;
+ x = spinbox->rect.width() - y - buttonWidth + 2;
lx = fw;
rx = x - fw;
switch (subControl) {
case SC_SpinBoxUp:
if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
return QRect();
- rect = QRect(x, fw, bs.width(), center - fw);
+ rect = QRect(x, fw, buttonWidth, center - fw);
break;
case SC_SpinBoxDown:
if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
return QRect();
- rect = QRect(x, center, bs.width(), spinbox->rect.bottom() - center - fw + 1);
+ rect = QRect(x, center, buttonWidth, spinbox->rect.bottom() - center - fw + 1);
break;
case SC_SpinBoxEditField:
if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) {
diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm
index b3c0463bca..531f538820 100644
--- a/src/widgets/styles/qmacstyle_mac.mm
+++ b/src/widgets/styles/qmacstyle_mac.mm
@@ -152,13 +152,32 @@ static uint qHash(const QPointer<QObject> &ptr)
return qHash(ptr.data());
}
-// These colors specify the titlebar gradient colors on
-// Leopard. Ideally we should get them from the system.
-static const QColor titlebarGradientActiveBegin(220, 220, 220);
-static const QColor titlebarGradientActiveEnd(151, 151, 151);
+// Title bar gradient colors for Lion were determined by inspecting PSDs exported
+// using CoreUI's CoreThemeDocument; there is no public API to retrieve them
+
+static QLinearGradient titlebarGradientActive()
+{
+ static QLinearGradient gradient;
+ if (gradient == QLinearGradient()) {
+ gradient.setColorAt(0, QColor(235, 235, 235));
+ gradient.setColorAt(0.5, QColor(210, 210, 210));
+ gradient.setColorAt(0.75, QColor(195, 195, 195));
+ gradient.setColorAt(1, QColor(180, 180, 180));
+ }
+ return gradient;
+}
+
+static QLinearGradient titlebarGradientInactive()
+{
+ static QLinearGradient gradient;
+ if (gradient == QLinearGradient()) {
+ gradient.setColorAt(0, QColor(250, 250, 250));
+ gradient.setColorAt(1, QColor(225, 225, 225));
+ }
+ return gradient;
+}
+
static const QColor titlebarSeparatorLineActive(111, 111, 111);
-static const QColor titlebarGradientInactiveBegin(241, 241, 241);
-static const QColor titlebarGradientInactiveEnd(207, 207, 207);
static const QColor titlebarSeparatorLineInactive(131, 131, 131);
// Gradient colors used for the dock widget title bar and
@@ -526,25 +545,6 @@ public:
};
} // anonymous namespace
-static QColor qcolorFromCGColor(CGColorRef cgcolor)
-{
- QColor pc;
- CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(cgcolor));
- const CGFloat *components = CGColorGetComponents(cgcolor);
- if (model == kCGColorSpaceModelRGB) {
- pc.setRgbF(components[0], components[1], components[2], components[3]);
- } else if (model == kCGColorSpaceModelCMYK) {
- pc.setCmykF(components[0], components[1], components[2], components[3]);
- } else if (model == kCGColorSpaceModelMonochrome) {
- pc.setRgbF(components[0], components[0], components[0], components[1]);
- } else {
- // Colorspace we can't deal with.
- qWarning("Qt: qcolorFromCGColor: cannot convert from colorspace model: %d", model);
- Q_ASSERT(false);
- }
- return pc;
-}
-
OSStatus qt_mac_shape2QRegionHelper(int inMessage, HIShapeRef, const CGRect *inRect, void *inRefcon)
{
QRegion *region = static_cast<QRegion *>(inRefcon);
@@ -702,7 +702,6 @@ static bool qt_macWindowMainWindow(const QWidget *window)
const int qt_mac_hitheme_version = 0; //the HITheme version we speak
const int macItemFrame = 2; // menu item frame width
const int macItemHMargin = 3; // menu item hor text margin
-const int macItemVMargin = 2; // menu item ver text margin
const int macRightBorder = 12; // right border on mac
const ThemeWindowType QtWinType = kThemeDocumentWindow; // Window type we use for QTitleBar.
QPixmap *qt_mac_backgroundPattern = 0; // stores the standard widget background.
@@ -3150,7 +3149,8 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
[triangleCell setButtonType:NSOnOffButton];
[triangleCell setState:(opt->state & State_Open) ? NSOnState : NSOffState];
[triangleCell setBezelStyle:NSDisclosureBezelStyle];
- [triangleCell setBackgroundStyle:((opt->state & State_Selected) && w->hasFocus()) ? NSBackgroundStyleDark : NSBackgroundStyleLight];
+ bool viewHasFocus = (w && w->hasFocus()) || (opt->state & State_HasFocus);
+ [triangleCell setBackgroundStyle:((opt->state & State_Selected) && viewHasFocus) ? NSBackgroundStyleDark : NSBackgroundStyleLight];
CGContextSaveGState(cg);
[NSGraphicsContext saveGraphicsState];
@@ -3263,14 +3263,15 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
} break;
case PE_PanelStatusBar: {
// Fill the status bar with the titlebar gradient.
- QLinearGradient linearGrad(0, opt->rect.top(), 0, opt->rect.bottom());
+ QLinearGradient linearGrad;
if (w ? qt_macWindowMainWindow(w->window()) : (opt->state & QStyle::State_Active)) {
- linearGrad.setColorAt(0, titlebarGradientActiveBegin);
- linearGrad.setColorAt(1, titlebarGradientActiveEnd);
+ linearGrad = titlebarGradientActive();
} else {
- linearGrad.setColorAt(0, titlebarGradientInactiveBegin);
- linearGrad.setColorAt(1, titlebarGradientInactiveEnd);
+ linearGrad = titlebarGradientInactive();
}
+
+ linearGrad.setStart(0, opt->rect.top());
+ linearGrad.setFinalStop(0, opt->rect.bottom());
p->fillRect(opt->rect, linearGrad);
// Draw the black separator line at the top of the status bar.
diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp
index 4c5c7cd17e..8774d71c0c 100644
--- a/src/widgets/styles/qstyle.cpp
+++ b/src/widgets/styles/qstyle.cpp
@@ -1784,6 +1784,9 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
\value SH_LineEdit_PasswordCharacter The Unicode character to be
used for passwords.
+ \value SH_LineEdit_PasswordMaskDelay Determines the delay before visible character is masked
+ with password character, in milliseconds. This enum value was added in Qt 5.4.
+
\value SH_Table_GridLineColor The RGB value of the grid for a table.
\value SH_UnderlineShortcut Whether shortcuts are underlined.
diff --git a/src/widgets/styles/qstyle.h b/src/widgets/styles/qstyle.h
index 136daa9abd..ea012faf46 100644
--- a/src/widgets/styles/qstyle.h
+++ b/src/widgets/styles/qstyle.h
@@ -703,6 +703,7 @@ public:
SH_Widget_Animate,
SH_Splitter_OpaqueResize,
SH_ComboBox_UseNativePopup,
+ SH_LineEdit_PasswordMaskDelay,
// Add new style hint values here
SH_CustomBase = 0xf0000000
diff --git a/src/widgets/styles/qstyleoption.cpp b/src/widgets/styles/qstyleoption.cpp
index 5913b2f261..f642a05d13 100644
--- a/src/widgets/styles/qstyleoption.cpp
+++ b/src/widgets/styles/qstyleoption.cpp
@@ -3702,6 +3702,8 @@ QStyleOptionGraphicsItem::QStyleOptionGraphicsItem(int version)
of the painter used to draw the item. By default, if no
transformations are applied, its value is 1. If zoomed out 1:2, the level
of detail will be 0.5, and if zoomed in 2:1, its value is 2.
+
+ \sa QGraphicsScene::minimumRenderSize()
*/
qreal QStyleOptionGraphicsItem::levelOfDetailFromTransform(const QTransform &worldTransform)
{
diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp
index 60bfc8e075..b82aa1b5a0 100644
--- a/src/widgets/styles/qstylesheetstyle.cpp
+++ b/src/widgets/styles/qstylesheetstyle.cpp
@@ -645,6 +645,7 @@ static const char *knownStyleHints[] = {
"icon-size",
"leftarrow-icon",
"lineedit-password-character",
+ "lineedit-password-mask-delay",
"mdi-fill-space-on-maximize",
"menu-scrollable",
"menubar-altkey-navigation",
@@ -5143,6 +5144,7 @@ int QStyleSheetStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWi
QString s;
switch (sh) {
case SH_LineEdit_PasswordCharacter: s = QLatin1String("lineedit-password-character"); break;
+ case SH_LineEdit_PasswordMaskDelay: s = QLatin1String("lineedit-password-mask-delay"); break;
case SH_DitherDisabledText: s = QLatin1String("dither-disabled-text"); break;
case SH_EtchDisabledText: s = QLatin1String("etch-disabled-text"); break;
case SH_ItemView_ActivateItemOnSingleClick: s = QLatin1String("activate-on-singleclick"); break;
@@ -5804,6 +5806,25 @@ QRect QStyleSheetStyle::subElementRect(SubElement se, const QStyleOption *opt, c
break;
#endif //QT_NO_TOOLBAR
+ // On mac we make pixel adjustments to layouts which are not
+ // desireable when you have custom style sheets on them
+ case SE_CheckBoxLayoutItem:
+ case SE_ComboBoxLayoutItem:
+ case SE_DateTimeEditLayoutItem:
+ case SE_LabelLayoutItem:
+ case SE_ProgressBarLayoutItem:
+ case SE_PushButtonLayoutItem:
+ case SE_RadioButtonLayoutItem:
+ case SE_SliderLayoutItem:
+ case SE_SpinBoxLayoutItem:
+ case SE_ToolButtonLayoutItem:
+ case SE_FrameLayoutItem:
+ case SE_GroupBoxLayoutItem:
+ case SE_TabWidgetLayoutItem:
+ if (!rule.hasNativeBorder())
+ return opt->rect;
+ break;
+
default:
break;
}
diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp
index bc78ea3296..e3699da7ef 100644
--- a/src/widgets/styles/qwindowsvistastyle.cpp
+++ b/src/widgets/styles/qwindowsvistastyle.cpp
@@ -1421,15 +1421,14 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
}
break;
case CE_DockWidgetTitle:
- if (const QDockWidget *dockWidget = qobject_cast<const QDockWidget *>(widget)) {
+ if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) {
+ const QDockWidget *dockWidget = qobject_cast<const QDockWidget *>(widget);
QRect rect = option->rect;
- if (dockWidget->isFloating()) {
+ if (dockWidget && dockWidget->isFloating()) {
QWindowsXPStyle::drawControl(element, option, painter, widget);
break; //otherwise fall through
}
- if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) {
-
const QStyleOptionDockWidgetV2 *v2
= qstyleoption_cast<const QStyleOptionDockWidgetV2*>(dwOpt);
bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar;
@@ -1490,7 +1489,6 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
}
}
break;
- }
#ifndef QT_NO_ITEMVIEWS
case CE_ItemViewItem:
{
diff --git a/src/widgets/util/qflickgesture.cpp b/src/widgets/util/qflickgesture.cpp
index b0cd4a9540..a372a7fe0d 100644
--- a/src/widgets/util/qflickgesture.cpp
+++ b/src/widgets/util/qflickgesture.cpp
@@ -101,6 +101,8 @@ static QMouseEvent *copyMouseEvent(QEvent *e)
copy->setButtons(me->buttons());
copy->setButton(me->button());
copy->setModifiers(me->modifiers());
+ copy->setSource(me->source());
+ copy->setFlags(me->flags());
return copy;
#endif
}
diff --git a/src/widgets/util/qsystemtrayicon.cpp b/src/widgets/util/qsystemtrayicon.cpp
index f1a69e6b36..fa318f3233 100644
--- a/src/widgets/util/qsystemtrayicon.cpp
+++ b/src/widgets/util/qsystemtrayicon.cpp
@@ -672,6 +672,74 @@ void QBalloonTip::timerEvent(QTimerEvent *e)
QWidget::timerEvent(e);
}
+//////////////////////////////////////////////////////////////////////
+void QSystemTrayIconPrivate::install_sys_qpa()
+{
+ qpa_sys->init();
+ QObject::connect(qpa_sys, SIGNAL(activated(QPlatformSystemTrayIcon::ActivationReason)),
+ q_func(), SLOT(_q_emitActivated(QPlatformSystemTrayIcon::ActivationReason)));
+ QObject::connect(qpa_sys, &QPlatformSystemTrayIcon::messageClicked,
+ q_func(), &QSystemTrayIcon::messageClicked);
+ updateMenu_sys();
+ updateIcon_sys();
+ updateToolTip_sys();
+}
+
+void QSystemTrayIconPrivate::remove_sys_qpa()
+{
+ qpa_sys->cleanup();
+}
+
+QRect QSystemTrayIconPrivate::geometry_sys_qpa() const
+{
+ return qpa_sys->geometry();
+}
+
+void QSystemTrayIconPrivate::updateIcon_sys_qpa()
+{
+ qpa_sys->updateIcon(icon);
+}
+
+void QSystemTrayIconPrivate::updateMenu_sys_qpa()
+{
+ if (menu) {
+ if (!menu->platformMenu()) {
+ QPlatformMenu *platformMenu = qpa_sys->createMenu();
+ if (platformMenu)
+ menu->setPlatformMenu(platformMenu);
+ }
+ qpa_sys->updateMenu(menu->platformMenu());
+ }
+}
+
+void QSystemTrayIconPrivate::updateToolTip_sys_qpa()
+{
+ qpa_sys->updateToolTip(toolTip);
+}
+
+void QSystemTrayIconPrivate::showMessage_sys_qpa(const QString &message,
+ const QString &title,
+ QSystemTrayIcon::MessageIcon icon,
+ int msecs)
+{
+ QIcon notificationIcon;
+ switch (icon) {
+ case QSystemTrayIcon::Information:
+ notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation);
+ break;
+ case QSystemTrayIcon::Warning:
+ notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning);
+ break;
+ case QSystemTrayIcon::Critical:
+ notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical);
+ break;
+ default:
+ break;
+ }
+ qpa_sys->showMessage(message, title, notificationIcon,
+ static_cast<QPlatformSystemTrayIcon::MessageIcon>(icon), msecs);
+}
+
QT_END_NAMESPACE
#endif // QT_NO_SYSTEMTRAYICON
diff --git a/src/widgets/util/qsystemtrayicon_p.h b/src/widgets/util/qsystemtrayicon_p.h
index 211ef308f1..317664a365 100644
--- a/src/widgets/util/qsystemtrayicon_p.h
+++ b/src/widgets/util/qsystemtrayicon_p.h
@@ -98,6 +98,15 @@ public:
QSystemTrayIconSys *sys;
QPlatformSystemTrayIcon *qpa_sys;
bool visible;
+
+private:
+ void install_sys_qpa();
+ void remove_sys_qpa();
+ void updateIcon_sys_qpa();
+ void updateToolTip_sys_qpa();
+ void updateMenu_sys_qpa();
+ QRect geometry_sys_qpa() const;
+ void showMessage_sys_qpa(const QString &msg, const QString &title, QSystemTrayIcon::MessageIcon icon, int secs);
};
class QBalloonTip : public QWidget
diff --git a/src/widgets/util/qsystemtrayicon_qpa.cpp b/src/widgets/util/qsystemtrayicon_qpa.cpp
index f98aeaf678..045641c509 100644
--- a/src/widgets/util/qsystemtrayicon_qpa.cpp
+++ b/src/widgets/util/qsystemtrayicon_qpa.cpp
@@ -65,28 +65,20 @@ QSystemTrayIconPrivate::~QSystemTrayIconPrivate()
void QSystemTrayIconPrivate::install_sys()
{
- if (qpa_sys) {
- qpa_sys->init();
- QObject::connect(qpa_sys, SIGNAL(activated(QPlatformSystemTrayIcon::ActivationReason)),
- q_func(), SLOT(_q_emitActivated(QPlatformSystemTrayIcon::ActivationReason)));
- QObject::connect(qpa_sys, SIGNAL(messageClicked()),
- q_func(), SIGNAL(messageClicked()));
- updateMenu_sys();
- updateIcon_sys();
- updateToolTip_sys();
- }
+ if (qpa_sys)
+ install_sys_qpa();
}
void QSystemTrayIconPrivate::remove_sys()
{
if (qpa_sys)
- qpa_sys->cleanup();
+ remove_sys_qpa();
}
QRect QSystemTrayIconPrivate::geometry_sys() const
{
if (qpa_sys)
- return qpa_sys->geometry();
+ return geometry_sys_qpa();
else
return QRect();
}
@@ -94,25 +86,19 @@ QRect QSystemTrayIconPrivate::geometry_sys() const
void QSystemTrayIconPrivate::updateIcon_sys()
{
if (qpa_sys)
- qpa_sys->updateIcon(icon);
+ updateIcon_sys_qpa();
}
void QSystemTrayIconPrivate::updateMenu_sys()
{
- if (qpa_sys && menu) {
- if (!menu->platformMenu()) {
- QPlatformMenu *platformMenu = qpa_sys->createMenu();
- if (platformMenu)
- menu->setPlatformMenu(platformMenu);
- }
- qpa_sys->updateMenu(menu->platformMenu());
- }
+ if (qpa_sys)
+ updateMenu_sys_qpa();
}
void QSystemTrayIconPrivate::updateToolTip_sys()
{
if (qpa_sys)
- qpa_sys->updateToolTip(toolTip);
+ updateToolTip_sys_qpa();
}
bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys()
@@ -138,25 +124,8 @@ void QSystemTrayIconPrivate::showMessage_sys(const QString &message,
QSystemTrayIcon::MessageIcon icon,
int msecs)
{
- if (!qpa_sys)
- return;
-
- QIcon notificationIcon;
- switch (icon) {
- case QSystemTrayIcon::Information:
- notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation);
- break;
- case QSystemTrayIcon::Warning:
- notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning);
- break;
- case QSystemTrayIcon::Critical:
- notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical);
- break;
- default:
- break;
- }
- qpa_sys->showMessage(message, title, notificationIcon,
- static_cast<QPlatformSystemTrayIcon::MessageIcon>(icon), msecs);
+ if (qpa_sys)
+ showMessage_sys_qpa(message, title, icon, msecs);
}
QT_END_NAMESPACE
diff --git a/src/widgets/util/qsystemtrayicon_x11.cpp b/src/widgets/util/qsystemtrayicon_x11.cpp
index 21ce23437f..e7007e4091 100644
--- a/src/widgets/util/qsystemtrayicon_x11.cpp
+++ b/src/widgets/util/qsystemtrayicon_x11.cpp
@@ -55,6 +55,9 @@
#include <qscreen.h>
#include <qbackingstore.h>
#include <qpa/qplatformnativeinterface.h>
+#include <qpa/qplatformsystemtrayicon.h>
+#include <qpa/qplatformtheme.h>
+#include <private/qguiapplication_p.h>
#include <qdebug.h>
#ifndef QT_NO_SYSTEMTRAYICON
@@ -101,11 +104,24 @@ QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *qIn)
setObjectName(QStringLiteral("QSystemTrayIconSys"));
setToolTip(q->toolTip());
setAttribute(Qt::WA_AlwaysShowToolTips, true);
- setAttribute(Qt::WA_TranslucentBackground, true);
setAttribute(Qt::WA_QuitOnClose, false);
const QSize size(22, 22); // Gnome, standard size
setGeometry(QRect(QPoint(0, 0), size));
setMinimumSize(size);
+
+ // We need two different behaviors depending on whether the X11 visual for the system tray
+ // (a) exists and (b) supports an alpha channel, i.e. is 32 bits.
+ // If we have a visual that has an alpha channel, we can paint this widget with a transparent
+ // background and it will work.
+ // However, if there's no alpha channel visual, in order for transparent tray icons to work,
+ // we do not have a transparent background on the widget, but call xcb_clear_region before
+ // painting the icon
+ bool hasAlphaChannel = false;
+ QMetaObject::invokeMethod(QGuiApplication::platformNativeInterface(),
+ "systrayVisualHasAlphaChannel", Qt::DirectConnection,
+ Q_RETURN_ARG(bool, hasAlphaChannel));
+ setAttribute(Qt::WA_TranslucentBackground, hasAlphaChannel);
+
addToTray();
}
@@ -196,12 +212,21 @@ bool QSystemTrayIconSys::event(QEvent *e)
void QSystemTrayIconSys::paintEvent(QPaintEvent *)
{
- // Note: Transparent pixels require a particular Visual which XCB
- // currently does not support yet.
const QRect rect(QPoint(0, 0), geometry().size());
QPainter painter(this);
- painter.setCompositionMode(QPainter::CompositionMode_Source);
- painter.fillRect(rect, Qt::transparent);
+
+ // If we have Qt::WA_TranslucentBackground set, during widget creation
+ // we detected the systray visual supported an alpha channel
+ if (testAttribute(Qt::WA_TranslucentBackground)) {
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+ painter.fillRect(rect, Qt::transparent);
+ } else {
+ QMetaObject::invokeMethod(QGuiApplication::platformNativeInterface(),
+ "clearRegion", Qt::DirectConnection,
+ Q_ARG(const QWindow *, windowHandle()),
+ Q_ARG(const QRect&, rect)
+ );
+ }
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
q->icon().paint(&painter, rect);
}
@@ -215,16 +240,22 @@ void QSystemTrayIconSys::resizeEvent(QResizeEvent *)
QSystemTrayIconPrivate::QSystemTrayIconPrivate()
: sys(0),
+ qpa_sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon()),
visible(false)
{
}
QSystemTrayIconPrivate::~QSystemTrayIconPrivate()
{
+ delete qpa_sys;
}
void QSystemTrayIconPrivate::install_sys()
{
+ if (qpa_sys) {
+ install_sys_qpa();
+ return;
+ }
Q_Q(QSystemTrayIcon);
if (!sys && locateSystemTray()) {
sys = new QSystemTrayIconSys(q);
@@ -235,6 +266,8 @@ void QSystemTrayIconPrivate::install_sys()
QRect QSystemTrayIconPrivate::geometry_sys() const
{
+ if (qpa_sys)
+ return geometry_sys_qpa();
if (!sys)
return QRect();
return sys->globalGeometry();
@@ -242,6 +275,10 @@ QRect QSystemTrayIconPrivate::geometry_sys() const
void QSystemTrayIconPrivate::remove_sys()
{
+ if (qpa_sys) {
+ remove_sys_qpa();
+ return;
+ }
if (!sys)
return;
QBalloonTip::hideBalloon();
@@ -252,17 +289,26 @@ void QSystemTrayIconPrivate::remove_sys()
void QSystemTrayIconPrivate::updateIcon_sys()
{
+ if (qpa_sys) {
+ updateIcon_sys_qpa();
+ return;
+ }
if (sys)
sys->updateIcon();
}
void QSystemTrayIconPrivate::updateMenu_sys()
{
-
+ if (qpa_sys)
+ updateMenu_sys_qpa();
}
void QSystemTrayIconPrivate::updateToolTip_sys()
{
+ if (qpa_sys) {
+ updateToolTip_sys_qpa();
+ return;
+ }
if (!sys)
return;
#ifndef QT_NO_TOOLTIP
@@ -272,6 +318,11 @@ void QSystemTrayIconPrivate::updateToolTip_sys()
bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys()
{
+ QScopedPointer<QPlatformSystemTrayIcon> sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon());
+ if (sys)
+ return sys->isSystemTrayAvailable();
+
+ // no QPlatformSystemTrayIcon so fall back to default xcb platform behavior
const QString platform = QGuiApplication::platformName();
if (platform.compare(QStringLiteral("xcb"), Qt::CaseInsensitive) == 0)
return locateSystemTray();
@@ -280,12 +331,21 @@ bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys()
bool QSystemTrayIconPrivate::supportsMessages_sys()
{
+ QScopedPointer<QPlatformSystemTrayIcon> sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon());
+ if (sys)
+ return sys->supportsMessages();
+
+ // no QPlatformSystemTrayIcon so fall back to default xcb platform behavior
return true;
}
void QSystemTrayIconPrivate::showMessage_sys(const QString &message, const QString &title,
QSystemTrayIcon::MessageIcon icon, int msecs)
{
+ if (qpa_sys) {
+ showMessage_sys_qpa(message, title, icon, msecs);
+ return;
+ }
if (!sys)
return;
const QPoint g = sys->globalGeometry().topLeft();
diff --git a/src/widgets/widgets.pro b/src/widgets/widgets.pro
index b12e2836d4..d819436f66 100644
--- a/src/widgets/widgets.pro
+++ b/src/widgets/widgets.pro
@@ -9,8 +9,7 @@ win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x65000000
irix-cc*:QMAKE_CXXFLAGS += -no_prelink -ptused
MODULE_PLUGIN_TYPES += \
- styles \
- accessible/libqtaccessiblewidgets.so
+ styles
QMAKE_DOCS = $$PWD/doc/qtwidgets.qdocconf
diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp
index 92af91b66e..43f5d6fd31 100644
--- a/src/widgets/widgets/qabstractspinbox.cpp
+++ b/src/widgets/widgets/qabstractspinbox.cpp
@@ -315,6 +315,8 @@ void QAbstractSpinBox::setReadOnly(bool enable)
Q_D(QAbstractSpinBox);
d->readOnly = enable;
d->edit->setReadOnly(enable);
+ QEvent event(QEvent::ReadOnlyChange);
+ QApplication::sendEvent(this, &event);
update();
}
diff --git a/src/widgets/widgets/qcheckbox.h b/src/widgets/widgets/qcheckbox.h
index 9adf5f6567..db6be7d1c0 100644
--- a/src/widgets/widgets/qcheckbox.h
+++ b/src/widgets/widgets/qcheckbox.h
@@ -86,6 +86,7 @@ protected:
private:
Q_DECLARE_PRIVATE(QCheckBox)
Q_DISABLE_COPY(QCheckBox)
+ friend class QAccessibleButton;
};
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp
index 066b3c7a86..5a40ceb2f7 100644
--- a/src/widgets/widgets/qdockarealayout.cpp
+++ b/src/widgets/widgets/qdockarealayout.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -44,6 +44,7 @@
#include "QtWidgets/qtabbar.h"
#include "QtWidgets/qstyle.h"
#include "QtWidgets/qdesktopwidget.h"
+#include "QtWidgets/qapplication.h"
#include "QtCore/qvariant.h"
#include "qdockarealayout_p.h"
#include "qdockwidget.h"
@@ -2978,8 +2979,9 @@ bool QDockAreaLayout::restoreDockWidget(QDockWidget *dockWidget)
item.widgetItem = new QDockWidgetItem(dockWidget);
if (placeHolder->window) {
- QDesktopWidget desktop;
- QRect r = constrainedRect(placeHolder->topLevelRect, desktop.screenGeometry(dockWidget));
+ const QRect screenGeometry =
+ QApplication::desktop()->screenGeometry(placeHolder->topLevelRect.center());
+ const QRect r = constrainedRect(placeHolder->topLevelRect, screenGeometry);
dockWidget->d_func()->setWindowState(true, true, r);
}
dockWidget->setVisible(!placeHolder->hidden);
diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp
index ad9481a928..3efa89edb3 100644
--- a/src/widgets/widgets/qdockwidget.cpp
+++ b/src/widgets/widgets/qdockwidget.cpp
@@ -591,10 +591,6 @@ void QDockWidgetPrivate::init()
QObject::connect(button, SIGNAL(clicked()), q, SLOT(close()));
layout->setWidgetForRole(QDockWidgetLayout::CloseButton, button);
- resizer = new QWidgetResizeHandler(q);
- resizer->setMovingEnabled(false);
- resizer->setActive(false);
-
#ifndef QT_NO_ACTION
toggleViewAction = new QAction(q);
toggleViewAction->setCheckable(true);
@@ -760,13 +756,12 @@ void QDockWidgetPrivate::endDrag(bool abort)
Qt::WindowFlags flags = q->windowFlags();
flags &= ~Qt::X11BypassWindowManagerHint;
q->setWindowFlags(flags);
- resizer->setActive(QWidgetResizeHandler::Resize, true);
+ setResizerActive(true);
q->show();
} else {
QDockWidgetLayout *myLayout
= qobject_cast<QDockWidgetLayout*>(layout);
- resizer->setActive(QWidgetResizeHandler::Resize,
- myLayout->widgetForRole(QDockWidgetLayout::TitleBar) != 0);
+ setResizerActive(myLayout->widgetForRole(QDockWidgetLayout::TitleBar) != 0);
}
undockedGeometry = q->geometry();
q->activateWindow();
@@ -779,6 +774,17 @@ void QDockWidgetPrivate::endDrag(bool abort)
state = 0;
}
+void QDockWidgetPrivate::setResizerActive(bool active)
+{
+ Q_Q(QDockWidget);
+ if (active && !resizer) {
+ resizer = new QWidgetResizeHandler(q);
+ resizer->setMovingEnabled(false);
+ }
+ if (resizer)
+ resizer->setActive(QWidgetResizeHandler::Resize, active);
+}
+
bool QDockWidgetPrivate::isAnimating() const
{
Q_Q(const QDockWidget);
@@ -1052,7 +1058,7 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect
}
}
- resizer->setActive(QWidgetResizeHandler::Resize, !unplug && floating && !nativeDeco);
+ setResizerActive(!unplug && floating && !nativeDeco);
}
/*!
diff --git a/src/widgets/widgets/qdockwidget_p.h b/src/widgets/widgets/qdockwidget_p.h
index f7cd8c0039..a4dc68dd7d 100644
--- a/src/widgets/widgets/qdockwidget_p.h
+++ b/src/widgets/widgets/qdockwidget_p.h
@@ -88,7 +88,7 @@ public:
features(QDockWidget::DockWidgetClosable
| QDockWidget::DockWidgetMovable
| QDockWidget::DockWidgetFloatable),
- allowedAreas(Qt::AllDockWidgetAreas)
+ allowedAreas(Qt::AllDockWidgetAreas), resizer(0)
{ }
void init();
@@ -101,8 +101,6 @@ public:
QDockWidget::DockWidgetFeatures features;
Qt::DockWidgetAreas allowedAreas;
- QWidgetResizeHandler *resizer;
-
#ifndef QT_NO_ACTION
QAction *toggleViewAction;
#endif
@@ -124,8 +122,12 @@ public:
void unplug(const QRect &rect);
void plug(const QRect &rect);
+ void setResizerActive(bool active);
bool isAnimating() const;
+
+private:
+ QWidgetResizeHandler *resizer;
};
class Q_WIDGETS_EXPORT QDockWidgetLayout : public QLayout
diff --git a/src/widgets/widgets/qgroupbox.cpp b/src/widgets/widgets/qgroupbox.cpp
index 168f0bbd67..42b0c68971 100644
--- a/src/widgets/widgets/qgroupbox.cpp
+++ b/src/widgets/widgets/qgroupbox.cpp
@@ -405,6 +405,8 @@ void QGroupBox::childEvent(QChildEvent *c)
if (c->type() != QEvent::ChildAdded || !c->child()->isWidgetType())
return;
QWidget *w = (QWidget*)c->child();
+ if (w->isWindow())
+ return;
if (d->checkable) {
if (d->checked) {
if (!w->testAttribute(Qt::WA_ForceDisabled))
diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp
index ba4dbcc878..b6b7ffb1a2 100644
--- a/src/widgets/widgets/qlineedit.cpp
+++ b/src/widgets/widgets/qlineedit.cpp
@@ -1348,6 +1348,8 @@ void QLineEdit::setReadOnly(bool enable)
#ifndef QT_NO_CURSOR
setCursor(enable ? Qt::ArrowCursor : Qt::IBeamCursor);
#endif
+ QEvent event(QEvent::ReadOnlyChange);
+ QCoreApplication::sendEvent(this, &event);
update();
}
}
@@ -2188,6 +2190,7 @@ void QLineEdit::changeEvent(QEvent *ev)
QStyleOptionFrameV2 opt;
initStyleOption(&opt);
d->control->setPasswordCharacter(style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, this));
+ d->control->setPasswordMaskDelay(style()->styleHint(QStyle::SH_LineEdit_PasswordMaskDelay, &opt, this));
}
d->m_iconSize = QSize();
update();
diff --git a/src/widgets/widgets/qlineedit.h b/src/widgets/widgets/qlineedit.h
index 3d52863db2..d53437c479 100644
--- a/src/widgets/widgets/qlineedit.h
+++ b/src/widgets/widgets/qlineedit.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -261,6 +261,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_selectionChanged())
Q_PRIVATE_SLOT(d_func(), void _q_updateNeeded(const QRect &))
Q_PRIVATE_SLOT(d_func(), void _q_textChanged(const QString &))
+ Q_PRIVATE_SLOT(d_func(), void _q_clearButtonClicked())
};
#endif // QT_NO_LINEEDIT
diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp
index 10689b2fc3..7ad893a54e 100644
--- a/src/widgets/widgets/qlineedit_p.cpp
+++ b/src/widgets/widgets/qlineedit_p.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -205,6 +205,7 @@ void QLineEditPrivate::init(const QString& txt)
QStyleOptionFrameV2 opt;
q->initStyleOption(&opt);
control->setPasswordCharacter(q->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, q));
+ control->setPasswordMaskDelay(q->style()->styleHint(QStyle::SH_LineEdit_PasswordMaskDelay, &opt, q));
#ifndef QT_NO_CURSOR
q->setCursor(Qt::IBeamCursor);
#endif
@@ -372,6 +373,15 @@ void QLineEditPrivate::_q_textChanged(const QString &text)
}
}
+void QLineEditPrivate::_q_clearButtonClicked()
+{
+ Q_Q(QLineEdit);
+ if (!q->text().isEmpty()) {
+ q->clear();
+ emit q->textEdited(QString());
+ }
+}
+
QSize QLineEditPrivate::iconSize() const
{
if (!m_iconSize.isValid()) // This might require style-specific handling (pixel metric).
@@ -447,7 +457,7 @@ QWidget *QLineEditPrivate::addAction(QAction *newAction, QAction *before, QLineE
toolButton->setIcon(newAction->icon());
toolButton->setOpacity(lastTextSize > 0 || !(flags & SideWidgetFadeInWithText) ? 1 : 0);
if (flags & SideWidgetClearButton)
- QObject::connect(toolButton, SIGNAL(clicked()), q, SLOT(clear()));
+ QObject::connect(toolButton, SIGNAL(clicked()), q, SLOT(_q_clearButtonClicked()));
toolButton->setDefaultAction(newAction);
w = toolButton;
}
diff --git a/src/widgets/widgets/qlineedit_p.h b/src/widgets/widgets/qlineedit_p.h
index db8edee005..08365521d5 100644
--- a/src/widgets/widgets/qlineedit_p.h
+++ b/src/widgets/widgets/qlineedit_p.h
@@ -195,6 +195,7 @@ public:
void drag();
#endif
void _q_textChanged(const QString &);
+ void _q_clearButtonClicked();
int leftTextMargin; // use effectiveLeftTextMargin() in case of icon.
int topTextMargin;
diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp
index 36ca90ba00..79f42a13ed 100644
--- a/src/widgets/widgets/qmainwindow.cpp
+++ b/src/widgets/widgets/qmainwindow.cpp
@@ -468,6 +468,10 @@ void QMainWindow::setIconSize(const QSize &iconSize)
/*! \property QMainWindow::toolButtonStyle
\brief style of toolbar buttons in this mainwindow.
+ To have the style of toolbuttons follow the system settings, set this property to Qt::ToolButtonFollowStyle.
+ On Unix, the user settings from the desktop environment will be used.
+ On other platforms, Qt::ToolButtonFollowStyle means icon only.
+
The default is Qt::ToolButtonIconOnly.
*/
diff --git a/src/widgets/widgets/qmainwindow.h b/src/widgets/widgets/qmainwindow.h
index 8411bf9f6b..6c392ca4cc 100644
--- a/src/widgets/widgets/qmainwindow.h
+++ b/src/widgets/widgets/qmainwindow.h
@@ -155,7 +155,6 @@ public:
void removeToolBar(QToolBar *toolbar);
void removeToolBarBreak(QToolBar *before);
- void setUnifiedTitleAndToolBarOnMac(bool set);
bool unifiedTitleAndToolBarOnMac() const;
Qt::ToolBarArea toolBarArea(QToolBar *toolbar) const;
@@ -182,12 +181,14 @@ public:
virtual QMenu *createPopupMenu();
#endif
-
-#ifndef QT_NO_DOCKWIDGET
public Q_SLOTS:
+#ifndef QT_NO_DOCKWIDGET
void setAnimated(bool enabled);
void setDockNestingEnabled(bool enabled);
#endif
+#ifndef QT_NO_TOOLBAR
+ void setUnifiedTitleAndToolBarOnMac(bool set);
+#endif
Q_SIGNALS:
void iconSizeChanged(const QSize &iconSize);
diff --git a/src/widgets/widgets/qmdiarea.cpp b/src/widgets/widgets/qmdiarea.cpp
index 17f73b2809..beabaa87da 100644
--- a/src/widgets/widgets/qmdiarea.cpp
+++ b/src/widgets/widgets/qmdiarea.cpp
@@ -169,7 +169,7 @@
#include <QResizeEvent>
#include <QScrollBar>
#include <QtAlgorithms>
-#include <QMutableListIterator>
+#include <QMutableVectorIterator>
#include <QPainter>
#include <QFontMetrics>
#include <QStyleOption>
@@ -413,7 +413,7 @@ void IconTiler::rearrange(QList<QWidget *> &widgets, const QRect &domain) const
\internal
Calculates the accumulated overlap (intersection area) between 'source' and 'rects'.
*/
-int MinOverlapPlacer::accumulatedOverlap(const QRect &source, const QList<QRect> &rects)
+int MinOverlapPlacer::accumulatedOverlap(const QRect &source, const QVector<QRect> &rects)
{
int accOverlap = 0;
foreach (const QRect &rect, rects) {
@@ -429,7 +429,7 @@ int MinOverlapPlacer::accumulatedOverlap(const QRect &source, const QList<QRect>
Finds among 'source' the rectangle with the minimum accumulated overlap with the
rectangles in 'rects'.
*/
-QRect MinOverlapPlacer::findMinOverlapRect(const QList<QRect> &source, const QList<QRect> &rects)
+QRect MinOverlapPlacer::findMinOverlapRect(const QVector<QRect> &source, const QVector<QRect> &rects)
{
int minAccOverlap = -1;
QRect minAccOverlapRect;
@@ -447,28 +447,37 @@ QRect MinOverlapPlacer::findMinOverlapRect(const QList<QRect> &source, const QLi
\internal
Gets candidates for the final placement.
*/
-void MinOverlapPlacer::getCandidatePlacements(const QSize &size, const QList<QRect> &rects,
- const QRect &domain,QList<QRect> &candidates)
+QVector<QRect> MinOverlapPlacer::getCandidatePlacements(const QSize &size, const QVector<QRect> &rects,
+ const QRect &domain)
{
- QSet<int> xset;
- QSet<int> yset;
- xset << domain.left() << domain.right() - size.width() + 1;
- yset << domain.top();
+ QVector<QRect> result;
+
+ QVector<int> xlist;
+ xlist.reserve(2 + rects.size());
+ xlist << domain.left() << domain.right() - size.width() + 1;
+
+ QVector<int> ylist;
+ ylist.reserve(2 + rects.size());
+ ylist << domain.top();
if (domain.bottom() - size.height() + 1 >= 0)
- yset << domain.bottom() - size.height() + 1;
+ ylist << domain.bottom() - size.height() + 1;
+
foreach (const QRect &rect, rects) {
- xset << rect.right() + 1;
- yset << rect.bottom() + 1;
+ xlist << rect.right() + 1;
+ ylist << rect.bottom() + 1;
}
- QList<int> xlist = xset.values();
std::sort(xlist.begin(), xlist.end());
- QList<int> ylist = yset.values();
+ xlist.erase(std::unique(xlist.begin(), xlist.end()), xlist.end());
+
std::sort(ylist.begin(), ylist.end());
+ ylist.erase(std::unique(ylist.begin(), ylist.end()), ylist.end());
+ result.reserve(ylist.size() * xlist.size());
foreach (int y, ylist)
foreach (int x, xlist)
- candidates << QRect(QPoint(x, y), size);
+ result << QRect(QPoint(x, y), size);
+ return result;
}
/*!
@@ -476,10 +485,12 @@ void MinOverlapPlacer::getCandidatePlacements(const QSize &size, const QList<QRe
Finds all rectangles in 'source' not completely inside 'domain'. The result is stored
in 'result' and also removed from 'source'.
*/
-void MinOverlapPlacer::findNonInsiders(const QRect &domain, QList<QRect> &source,
- QList<QRect> &result)
+QVector<QRect> MinOverlapPlacer::findNonInsiders(const QRect &domain, QVector<QRect> &source)
{
- QMutableListIterator<QRect> it(source);
+ QVector<QRect> result;
+ result.reserve(source.size());
+
+ QMutableVectorIterator<QRect> it(source);
while (it.hasNext()) {
const QRect srcRect = it.next();
if (!domain.contains(srcRect)) {
@@ -487,6 +498,8 @@ void MinOverlapPlacer::findNonInsiders(const QRect &domain, QList<QRect> &source
it.remove();
}
}
+
+ return result;
}
/*!
@@ -494,9 +507,11 @@ void MinOverlapPlacer::findNonInsiders(const QRect &domain, QList<QRect> &source
Finds all rectangles in 'source' that overlaps 'domain' by the maximum overlap area
between 'domain' and any rectangle in 'source'. The result is stored in 'result'.
*/
-void MinOverlapPlacer::findMaxOverlappers(const QRect &domain, const QList<QRect> &source,
- QList<QRect> &result)
+QVector<QRect> MinOverlapPlacer::findMaxOverlappers(const QRect &domain, const QVector<QRect> &source)
{
+ QVector<QRect> result;
+ result.reserve(source.size());
+
int maxOverlap = -1;
foreach (const QRect &srcRect, source) {
QRect intersection = domain.intersected(srcRect);
@@ -509,6 +524,8 @@ void MinOverlapPlacer::findMaxOverlappers(const QRect &domain, const QList<QRect
result << srcRect;
}
}
+
+ return result;
}
/*!
@@ -517,17 +534,15 @@ void MinOverlapPlacer::findMaxOverlappers(const QRect &domain, const QList<QRect
placement that overlaps the rectangles in 'rects' as little as possible while at the
same time being as much as possible inside 'domain'.
*/
-QPoint MinOverlapPlacer::findBestPlacement(const QRect &domain, const QList<QRect> &rects,
- QList<QRect> &source)
+QPoint MinOverlapPlacer::findBestPlacement(const QRect &domain, const QVector<QRect> &rects,
+ QVector<QRect> &source)
{
- QList<QRect> nonInsiders;
- findNonInsiders(domain, source, nonInsiders);
+ const QVector<QRect> nonInsiders = findNonInsiders(domain, source);
if (!source.empty())
return findMinOverlapRect(source, rects).topLeft();
- QList<QRect> maxOverlappers;
- findMaxOverlappers(domain, nonInsiders, maxOverlappers);
+ QVector<QRect> maxOverlappers = findMaxOverlappers(domain, nonInsiders);
return findMinOverlapRect(maxOverlappers, rects).topLeft();
}
@@ -538,7 +553,7 @@ QPoint MinOverlapPlacer::findBestPlacement(const QRect &domain, const QList<QRec
overlaps 'rects' as little as possible and 'domain' as much as possible.
Returns the position of the resulting rectangle.
*/
-QPoint MinOverlapPlacer::place(const QSize &size, const QList<QRect> &rects,
+QPoint MinOverlapPlacer::place(const QSize &size, const QVector<QRect> &rects,
const QRect &domain) const
{
if (size.isEmpty() || !domain.isValid())
@@ -548,8 +563,7 @@ QPoint MinOverlapPlacer::place(const QSize &size, const QList<QRect> &rects,
return QPoint();
}
- QList<QRect> candidates;
- getCandidatePlacements(size, rects, domain, candidates);
+ QVector<QRect> candidates = getCandidatePlacements(size, rects, domain);
return findBestPlacement(domain, rects, candidates);
}
@@ -882,7 +896,8 @@ void QMdiAreaPrivate::place(Placer *placer, QMdiSubWindow *child)
return;
}
- QList<QRect> rects;
+ QVector<QRect> rects;
+ rects.reserve(childWindows.size());
QRect parentRect = q->rect();
foreach (QMdiSubWindow *window, childWindows) {
if (!sanityCheck(window, "QMdiArea::place") || window == child || !window->isVisibleTo(q)
diff --git a/src/widgets/widgets/qmdiarea_p.h b/src/widgets/widgets/qmdiarea_p.h
index 90db55438a..360ed2508c 100644
--- a/src/widgets/widgets/qmdiarea_p.h
+++ b/src/widgets/widgets/qmdiarea_p.h
@@ -59,6 +59,7 @@
#ifndef QT_NO_MDIAREA
#include <QList>
+#include <QVector>
#include <QRect>
#include <QPoint>
#include <QtWidgets/qapplication.h>
@@ -116,24 +117,19 @@ public:
// Places the rectangle defined by 'size' relative to 'rects' and 'domain'.
// Returns the position of the resulting rectangle.
virtual QPoint place(
- const QSize &size, const QList<QRect> &rects, const QRect &domain) const = 0;
+ const QSize &size, const QVector<QRect> &rects, const QRect &domain) const = 0;
virtual ~Placer() {}
};
class MinOverlapPlacer : public Placer
{
- QPoint place(const QSize &size, const QList<QRect> &rects, const QRect &domain) const;
- static int accumulatedOverlap(const QRect &source, const QList<QRect> &rects);
- static QRect findMinOverlapRect(const QList<QRect> &source, const QList<QRect> &rects);
- static void getCandidatePlacements(
- const QSize &size, const QList<QRect> &rects, const QRect &domain,
- QList<QRect> &candidates);
- static QPoint findBestPlacement(
- const QRect &domain, const QList<QRect> &rects, QList<QRect> &source);
- static void findNonInsiders(
- const QRect &domain, QList<QRect> &source, QList<QRect> &result);
- static void findMaxOverlappers(
- const QRect &domain, const QList<QRect> &source, QList<QRect> &result);
+ QPoint place(const QSize &size, const QVector<QRect> &rects, const QRect &domain) const;
+ static int accumulatedOverlap(const QRect &source, const QVector<QRect> &rects);
+ static QRect findMinOverlapRect(const QVector<QRect> &source, const QVector<QRect> &rects);
+ static QVector<QRect> getCandidatePlacements(const QSize &size, const QVector<QRect> &rects, const QRect &domain);
+ static QPoint findBestPlacement(const QRect &domain, const QVector<QRect> &rects, QVector<QRect> &source);
+ static QVector<QRect> findNonInsiders(const QRect &domain, QVector<QRect> &source);
+ static QVector<QRect> findMaxOverlappers(const QRect &domain, const QVector<QRect> &source);
};
} // namespace QMdi
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index 7e48badea5..846199ebe2 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -187,8 +187,8 @@ void QMenuPrivate::syncPlatformMenu()
QPlatformMenuItem *menuItem = platformMenu->createMenuItem();
QAction *action = it.previous();
menuItem->setTag(reinterpret_cast<quintptr>(action));
- QObject::connect(menuItem, SIGNAL(activated()), action, SLOT(trigger()));
- QObject::connect(menuItem, SIGNAL(hovered()), action, SIGNAL(hovered()));
+ QObject::connect(menuItem, SIGNAL(activated()), action, SLOT(trigger()), Qt::QueuedConnection);
+ QObject::connect(menuItem, SIGNAL(hovered()), action, SIGNAL(hovered()), Qt::QueuedConnection);
copyActionToPlatformItem(action, menuItem);
platformMenu->insertMenuItem(menuItem, beforeItem);
beforeItem = menuItem;
diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp
index 23c1e99231..df13085dee 100644
--- a/src/widgets/widgets/qplaintextedit.cpp
+++ b/src/widgets/widgets/qplaintextedit.cpp
@@ -2537,6 +2537,8 @@ void QPlainTextEdit::setReadOnly(bool ro)
}
setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
d->control->setTextInteractionFlags(flags);
+ QEvent event(QEvent::ReadOnlyChange);
+ QApplication::sendEvent(this, &event);
}
/*!
diff --git a/src/widgets/widgets/qradiobutton.h b/src/widgets/widgets/qradiobutton.h
index 104d4a12e0..8888ccf86d 100644
--- a/src/widgets/widgets/qradiobutton.h
+++ b/src/widgets/widgets/qradiobutton.h
@@ -73,6 +73,7 @@ protected:
private:
Q_DECLARE_PRIVATE(QRadioButton)
Q_DISABLE_COPY(QRadioButton)
+ friend class QAccessibleButton;
};
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp
index 789ec2f6fd..e8fdc65711 100644
--- a/src/widgets/widgets/qtabbar.cpp
+++ b/src/widgets/widgets/qtabbar.cpp
@@ -632,6 +632,14 @@ void QTabBarPrivate::layoutWidgets(int start)
}
}
+void QTabBarPrivate::autoHideTabs()
+{
+ Q_Q(QTabBar);
+
+ if (autoHide)
+ q->setVisible(q->count() > 1);
+}
+
void QTabBarPrivate::_q_closeTab()
{
Q_Q(QTabBar);
@@ -861,6 +869,7 @@ int QTabBar::insertTab(int index, const QIcon& icon, const QString &text)
}
tabInserted(index);
+ d->autoHideTabs();
return index;
}
@@ -936,6 +945,7 @@ void QTabBar::removeTab(int index)
setCurrentIndex(d->currentIndex - 1);
}
d->refresh();
+ d->autoHideTabs();
tabRemoved(index);
}
}
@@ -2267,6 +2277,36 @@ void QTabBar::setDocumentMode(bool enabled)
}
/*!
+ \property QTabBar::autoHide
+ \brief If true, the tab bar is automatically hidden when it contains less
+ than 2 tabs.
+ \since 5.4
+
+ By default, this property is false.
+
+ \sa QWidget::visible
+*/
+
+bool QTabBar::autoHide() const
+{
+ Q_D(const QTabBar);
+ return d->autoHide;
+}
+
+void QTabBar::setAutoHide(bool hide)
+{
+ Q_D(QTabBar);
+ if (d->autoHide == hide)
+ return;
+
+ d->autoHide = hide;
+ if (hide)
+ d->autoHideTabs();
+ else
+ setVisible(true);
+}
+
+/*!
Sets \a widget on the tab \a index. The widget is placed
on the left or right hand side depending upon the \a position.
\since 4.5
diff --git a/src/widgets/widgets/qtabbar.h b/src/widgets/widgets/qtabbar.h
index a0e52c2f86..a1616b1524 100644
--- a/src/widgets/widgets/qtabbar.h
+++ b/src/widgets/widgets/qtabbar.h
@@ -70,6 +70,7 @@ class Q_WIDGETS_EXPORT QTabBar: public QWidget
Q_PROPERTY(bool expanding READ expanding WRITE setExpanding)
Q_PROPERTY(bool movable READ isMovable WRITE setMovable)
Q_PROPERTY(bool documentMode READ documentMode WRITE setDocumentMode)
+ Q_PROPERTY(bool autoHide READ autoHide WRITE setAutoHide)
public:
explicit QTabBar(QWidget* parent=0);
@@ -166,6 +167,9 @@ public:
bool documentMode() const;
void setDocumentMode(bool set);
+ bool autoHide() const;
+ void setAutoHide(bool hide);
+
public Q_SLOTS:
void setCurrentIndex(int index);
diff --git a/src/widgets/widgets/qtabbar_p.h b/src/widgets/widgets/qtabbar_p.h
index 3228308bc6..1238057e2a 100644
--- a/src/widgets/widgets/qtabbar_p.h
+++ b/src/widgets/widgets/qtabbar_p.h
@@ -77,7 +77,7 @@ public:
:currentIndex(-1), pressedIndex(-1), shape(QTabBar::RoundedNorth), layoutDirty(false),
drawBase(true), scrollOffset(0), elideModeSetByUser(false), useScrollButtonsSetByUser(false), expanding(true), closeButtonOnTabs(false),
selectionBehaviorOnRemove(QTabBar::SelectRightTab), paintWithOffsets(true), movable(false),
- dragInProgress(false), documentMode(false), movingTab(0)
+ dragInProgress(false), documentMode(false), autoHide(false), movingTab(0)
#ifdef Q_WS_MAC
, previousPressedIndex(-1)
#endif
@@ -184,6 +184,7 @@ public:
void updateMacBorderMetrics();
bool isTabInMacUnifiedToolbarArea() const;
void setupMovableTab();
+ void autoHideTabs();
void makeVisible(int index);
QSize iconSize;
@@ -201,6 +202,7 @@ public:
bool movable;
bool dragInProgress;
bool documentMode;
+ bool autoHide;
QWidget *movingTab;
#ifdef Q_WS_MAC
diff --git a/src/widgets/widgets/qtabwidget.cpp b/src/widgets/widgets/qtabwidget.cpp
index fced1c01ec..616b66b80b 100644
--- a/src/widgets/widgets/qtabwidget.cpp
+++ b/src/widgets/widgets/qtabwidget.cpp
@@ -1351,6 +1351,29 @@ void QTabWidget::setDocumentMode(bool enabled)
}
/*!
+ \property QTabWidget::tabBarAutoHide
+ \brief If true, the tab bar is automatically hidden when it contains less
+ than 2 tabs.
+ \since 5.4
+
+ By default, this property is false.
+
+ \sa QWidget::visible
+*/
+
+bool QTabWidget::tabBarAutoHide() const
+{
+ Q_D(const QTabWidget);
+ return d->tabs->autoHide();
+}
+
+void QTabWidget::setTabBarAutoHide(bool enabled)
+{
+ Q_D(QTabWidget);
+ return d->tabs->setAutoHide(enabled);
+}
+
+/*!
Removes all the pages, but does not delete them. Calling this function
is equivalent to calling removeTab() until the tab widget is empty.
*/
diff --git a/src/widgets/widgets/qtabwidget.h b/src/widgets/widgets/qtabwidget.h
index 83c2e31d28..046e544bf0 100644
--- a/src/widgets/widgets/qtabwidget.h
+++ b/src/widgets/widgets/qtabwidget.h
@@ -68,6 +68,7 @@ class Q_WIDGETS_EXPORT QTabWidget : public QWidget
Q_PROPERTY(bool documentMode READ documentMode WRITE setDocumentMode)
Q_PROPERTY(bool tabsClosable READ tabsClosable WRITE setTabsClosable)
Q_PROPERTY(bool movable READ isMovable WRITE setMovable)
+ Q_PROPERTY(bool tabBarAutoHide READ tabBarAutoHide WRITE setTabBarAutoHide)
public:
explicit QTabWidget(QWidget *parent = 0);
@@ -140,6 +141,9 @@ public:
bool documentMode() const;
void setDocumentMode(bool set);
+ bool tabBarAutoHide() const;
+ void setTabBarAutoHide(bool enabled);
+
void clear();
QTabBar* tabBar() const;
diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp
index a33ac0817f..f106b70c12 100644
--- a/src/widgets/widgets/qtextedit.cpp
+++ b/src/widgets/widgets/qtextedit.cpp
@@ -2122,6 +2122,8 @@ void QTextEdit::setReadOnly(bool ro)
}
d->control->setTextInteractionFlags(flags);
setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
+ QEvent event(QEvent::ReadOnlyChange);
+ QApplication::sendEvent(this, &event);
}
/*!
diff --git a/src/widgets/widgets/qtoolbar.cpp b/src/widgets/widgets/qtoolbar.cpp
index 1c05529cd6..834c2fe56b 100644
--- a/src/widgets/widgets/qtoolbar.cpp
+++ b/src/widgets/widgets/qtoolbar.cpp
@@ -720,6 +720,10 @@ void QToolBar::setIconSize(const QSize &iconSize)
as \l{QAction}s. Note that if you add a QToolButton with the
addWidget() method, it will not get this button style.
+ To have the style of toolbuttons follow the system settings, set this property to Qt::ToolButtonFollowStyle.
+ On Unix, the user settings from the desktop environment will be used.
+ On other platforms, Qt::ToolButtonFollowStyle means icon only.
+
The default is Qt::ToolButtonIconOnly.
*/
diff --git a/src/widgets/widgets/qtoolbutton.cpp b/src/widgets/widgets/qtoolbutton.cpp
index 497bc52109..1b5ba8cd58 100644
--- a/src/widgets/widgets/qtoolbutton.cpp
+++ b/src/widgets/widgets/qtoolbutton.cpp
@@ -384,8 +384,9 @@ QSize QToolButton::minimumSizeHint() const
The default is Qt::ToolButtonIconOnly.
- To have the style of toolbuttons follow the system settings (as available
- in GNOME and KDE desktop environments), set this property to Qt::ToolButtonFollowStyle.
+ To have the style of toolbuttons follow the system settings, set this property to Qt::ToolButtonFollowStyle.
+ On Unix, the user settings from the desktop environment will be used.
+ On other platforms, Qt::ToolButtonFollowStyle means icon only.
QToolButton automatically connects this slot to the relevant
signal in the QMainWindow in which is resides.
diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp
index 75f30599be..b927004773 100644
--- a/src/widgets/widgets/qwidgetlinecontrol.cpp
+++ b/src/widgets/widgets/qwidgetlinecontrol.cpp
@@ -355,8 +355,10 @@ void QWidgetLineControl::init(const QString &txt)
m_text = txt;
updateDisplayText();
m_cursor = m_text.length();
- if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
+ if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
m_keyboardScheme = theme->themeHint(QPlatformTheme::KeyboardScheme).toInt();
+ m_passwordMaskDelay = theme->themeHint(QPlatformTheme::PasswordMaskDelay).toInt();
+ }
// Generalize for X11
if (m_keyboardScheme == QPlatformTheme::KdeKeyboardScheme
|| m_keyboardScheme == QPlatformTheme::GnomeKeyboardScheme
@@ -787,7 +789,7 @@ void QWidgetLineControl::internalInsert(const QString &s)
if (m_echoMode == QLineEdit::Password) {
if (m_passwordEchoTimer != 0)
killTimer(m_passwordEchoTimer);
- int delay = qGuiApp->styleHints()->passwordMaskDelay();
+ int delay = m_passwordMaskDelay;
#ifdef QT_BUILD_INTERNAL
if (m_passwordMaskDelayOverride >= 0)
delay = m_passwordMaskDelayOverride;
diff --git a/src/widgets/widgets/qwidgetlinecontrol_p.h b/src/widgets/widgets/qwidgetlinecontrol_p.h
index 1cee67bfd2..ba73e9e25e 100644
--- a/src/widgets/widgets/qwidgetlinecontrol_p.h
+++ b/src/widgets/widgets/qwidgetlinecontrol_p.h
@@ -90,6 +90,7 @@ public:
m_tripleClickTimer(0), m_maskData(0), m_modifiedState(0), m_undoState(0),
m_selstart(0), m_selend(0), m_passwordEchoEditing(false)
, m_passwordEchoTimer(0)
+ , m_passwordMaskDelay(-1)
#if defined(Q_WS_MAC)
, m_threadChecks(false)
, m_textLayoutThread(0)
@@ -313,6 +314,9 @@ public:
QChar passwordCharacter() const { return m_passwordCharacter; }
void setPasswordCharacter(QChar character) { m_passwordCharacter = character; updateDisplayText(); }
+ int passwordMaskDelay() const { return m_passwordMaskDelay; }
+ void setPasswordMaskDelay(int delay) { m_passwordMaskDelay = delay; }
+
Qt::LayoutDirection layoutDirection() const {
if (m_layoutDirection == Qt::LayoutDirectionAuto) {
if (m_text.isEmpty())
@@ -481,6 +485,7 @@ private:
bool m_passwordEchoEditing;
QChar m_passwordCharacter;
int m_passwordEchoTimer;
+ int m_passwordMaskDelay;
void cancelPasswordEchoTimer()
{
if (m_passwordEchoTimer != 0) {
diff --git a/src/widgets/widgets/qwidgetresizehandler.cpp b/src/widgets/widgets/qwidgetresizehandler.cpp
index ba4e69126a..d4d44e60cd 100644
--- a/src/widgets/widgets/qwidgetresizehandler.cpp
+++ b/src/widgets/widgets/qwidgetresizehandler.cpp
@@ -58,6 +58,10 @@ QT_BEGIN_NAMESPACE
static bool resizeHorizontalDirectionFixed = false;
static bool resizeVerticalDirectionFixed = false;
+// ### fixme: Qt 6: No longer export QWidgetResizeHandler and remove "Move"
+// functionality. Currently, only the resize functionality is used by QDockWidget.
+// Historically, the class was used in Qt 3's QWorkspace (predecessor to QMdiArea).
+
QWidgetResizeHandler::QWidgetResizeHandler(QWidget *parent, QWidget *cw)
: QObject(parent), widget(parent), childWidget(cw ? cw : parent),
fw(0), extrahei(0), buttonDown(false), moveResizeMode(false), sizeprotect(true), movingEnabled(true)
diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp
index 96438a0bdf..5f60bf02d0 100644
--- a/src/widgets/widgets/qwidgettextcontrol.cpp
+++ b/src/widgets/widgets/qwidgettextcontrol.cpp
@@ -645,13 +645,15 @@ void QWidgetTextControlPrivate::_q_emitCursorPosChanged(const QTextCursor &someC
void QWidgetTextControlPrivate::_q_contentsChanged(int from, int charsRemoved, int charsAdded)
{
- Q_Q(QWidgetTextControl);
#ifndef QT_NO_ACCESSIBILITY
+ Q_Q(QWidgetTextControl);
if (QAccessible::isActive() && q->parent() && q->parent()->isWidgetType()) {
QTextCursor tmp(doc);
tmp.setPosition(from);
- tmp.setPosition(from + charsAdded, QTextCursor::KeepAnchor);
+ // when setting a new text document the length is off
+ // QTBUG-32583 - characterCount is off by 1 requires the -1
+ tmp.setPosition(qMin(doc->characterCount() - 1, from + charsAdded), QTextCursor::KeepAnchor);
QString newText = tmp.selectedText();
// always report the right number of removed chars, but in lack of the real string use spaces
@@ -668,6 +670,10 @@ void QWidgetTextControlPrivate::_q_contentsChanged(int from, int charsRemoved, i
QAccessible::updateAccessibility(ev);
delete ev;
}
+#else
+ Q_UNUSED(from)
+ Q_UNUSED(charsRemoved)
+ Q_UNUSED(charsAdded)
#endif
}
diff --git a/src/winmain/qtmain_win.cpp b/src/winmain/qtmain_win.cpp
index dc765ea56a..778ddee64b 100644
--- a/src/winmain/qtmain_win.cpp
+++ b/src/winmain/qtmain_win.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Windows main function of the Qt Toolkit.
@@ -43,6 +43,10 @@
#include "qstring.h"
#include "qvector.h"
+#ifndef Q_OS_WINCE
+# include <shlobj.h>
+#endif
+
/*
This file contains the code in the qtmain library for Windows.
qtmain contains the Windows startup code and is required for
@@ -83,26 +87,49 @@ extern "C" int main(int, char **);
application.
*/
-#ifdef Q_OS_WINCE
+#ifndef Q_OS_WINCE
+
+// Convert a wchar_t to char string, equivalent to QString::toLocal8Bit()
+// when passed CP_ACP.
+static inline char *wideToMulti(int codePage, const wchar_t *aw)
+{
+ const int required = WideCharToMultiByte(codePage, 0, aw, -1, NULL, 0, NULL, NULL);
+ char *result = new char[required];
+ WideCharToMultiByte(codePage, 0, aw, -1, result, required, NULL, NULL);
+ return result;
+}
+
+extern "C" int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR /*cmdParamarg*/, int /* cmdShow */)
+{
+ int argc;
+ wchar_t **argvW = CommandLineToArgvW(GetCommandLineW(), &argc);
+ if (!argvW)
+ return -1;
+ char **argv = new char *[argc];
+ for (int i = 0; i < argc; ++i)
+ argv[i] = wideToMulti(CP_ACP, argvW[i]);
+ LocalFree(argvW);
+ const int exitCode = main(argc, argv);
+ for (int i = 0; i < argc; ++i)
+ delete [] argv[i];
+ delete [] argv;
+ return exitCode;
+}
+
+#else // !Q_OS_WINCE
+
int WINAPI WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR /*wCmdParam*/, int cmdShow)
-#else
-extern "C"
-int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR /*cmdParamarg*/, int cmdShow)
-#endif
{
QByteArray cmdParam = QString::fromWCharArray(GetCommandLine()).toLocal8Bit();
-#if defined(Q_OS_WINCE)
wchar_t appName[MAX_PATH];
GetModuleFileName(0, appName, MAX_PATH);
cmdParam.prepend(QString(QLatin1String("\"%1\" ")).arg(QString::fromWCharArray(appName)).toLocal8Bit());
-#endif
int argc = 0;
QVector<char *> argv(8);
qWinMain(instance, prevInstance, cmdParam.data(), cmdShow, argc, argv);
-#if defined(Q_OS_WINCE)
wchar_t uniqueAppID[MAX_PATH];
GetModuleFileName(0, uniqueAppID, MAX_PATH);
QString uid = QString::fromWCharArray(uniqueAppID).toLower().replace(QLatin1String("\\"), QLatin1String("_"));
@@ -126,11 +153,10 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR /*cmdPara
SetForegroundWindow((HWND)(((ULONG)aHwnd) | 0x01));
return 0;
}
-#endif // Q_OS_WINCE
int result = main(argc, argv.data());
-#if defined(Q_OS_WINCE)
CloseHandle(mutex);
-#endif
return result;
}
+
+#endif // Q_OS_WINCE
diff --git a/src/winmain/qtmain_winrt.cpp b/src/winmain/qtmain_winrt.cpp
index bcb3445bcd..43bce0862a 100644
--- a/src/winmain/qtmain_winrt.cpp
+++ b/src/winmain/qtmain_winrt.cpp
@@ -67,6 +67,7 @@ extern "C" {
#include <qvector.h>
#include <qdir.h>
#include <qstandardpaths.h>
+#include <qthread.h>
#include <wrl.h>
#include <Windows.ApplicationModel.core.h>
@@ -237,6 +238,9 @@ int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
if (FAILED(RoInitialize(RO_INIT_MULTITHREADED)))
return 1;
+ // Mark the main thread
+ QThread::currentThread();
+
Core::ICoreApplication *appFactory;
if (FAILED(RoGetActivationFactory(qHString(CoreApplicationClass), IID_PPV_ARGS(&appFactory))))
return 2;
diff --git a/src/winmain/winmain.pro b/src/winmain/winmain.pro
index 998200cb1e..284f2a2201 100644
--- a/src/winmain/winmain.pro
+++ b/src/winmain/winmain.pro
@@ -20,6 +20,8 @@ winrt {
SOURCES = qtmain_winrt.cpp
} else {
SOURCES = qtmain_win.cpp
+
+ !wince: LIBS += -lshell32
}
load(qt_installs)
diff --git a/src/xml/doc/qtxml.qdocconf b/src/xml/doc/qtxml.qdocconf
index 1e3b534be5..8ca421ff4e 100644
--- a/src/xml/doc/qtxml.qdocconf
+++ b/src/xml/doc/qtxml.qdocconf
@@ -2,7 +2,6 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = QtXml
description = Qt XML Reference Documentation
-url = http://qt-project.org/doc/qt-$QT_VER
version = $QT_VERSION
examplesinstallpath = xml