aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--examples/quick/customitems/painteditem/textballoon.cpp15
-rw-r--r--examples/quick/quick.pro1
-rw-r--r--examples/quick/rendercontrol/window_singlethreaded.cpp46
-rw-r--r--examples/quick/rendercontrol/window_singlethreaded.h2
-rw-r--r--examples/quick/scenegraph/customgeometry/beziercurve.cpp6
-rw-r--r--examples/quick/scenegraph/graph/shaders/line.fsh2
-rw-r--r--examples/quick/scenegraph/graph/shaders/noisy.fsh2
-rw-r--r--examples/quick/scenegraph/rendernode/softwarerenderer.cpp7
-rw-r--r--examples/quick/scenegraph/shared/logorenderer.cpp4
-rw-r--r--examples/quick/scenegraph/textureinsgnode/main.qml2
-rw-r--r--examples/quick/scenegraph/textureinthread/main.qml2
-rw-r--r--examples/quick/scenegraph/twotextureproviders/main.qml2
-rw-r--r--examples/quick/shapes/content/item1.qml95
-rw-r--r--examples/quick/shapes/content/item10.qml157
-rw-r--r--examples/quick/shapes/content/item11.qml111
-rw-r--r--examples/quick/shapes/content/item12.qml113
-rw-r--r--examples/quick/shapes/content/item13.qml97
-rw-r--r--examples/quick/shapes/content/item14.qml91
-rw-r--r--examples/quick/shapes/content/item15.qml113
-rw-r--r--examples/quick/shapes/content/item17.qml77
-rw-r--r--examples/quick/shapes/content/item2.qml153
-rw-r--r--examples/quick/shapes/content/item4.qml86
-rw-r--r--examples/quick/shapes/content/item5.qml89
-rw-r--r--examples/quick/shapes/content/item6.qml89
-rw-r--r--examples/quick/shapes/content/item7.qml95
-rw-r--r--examples/quick/shapes/content/item8.qml93
-rw-r--r--examples/quick/shapes/content/item9.qml100
-rw-r--r--examples/quick/shapes/content/pathitem.qml65
-rw-r--r--examples/quick/shapes/content/pathitemgallery.qml192
-rw-r--r--examples/quick/shapes/content/pathiteminteract.qml285
-rw-r--r--examples/quick/shapes/content/pathitemsampling.qml186
-rw-r--r--examples/quick/shapes/content/pathitemtigers.qml137
-rw-r--r--examples/quick/shapes/content/tiger.qml3619
-rw-r--r--examples/quick/shapes/doc/images/qml-shapes-example.pngbin0 -> 49261 bytes
-rw-r--r--examples/quick/shapes/doc/src/shapes.qdoc39
-rw-r--r--examples/quick/shapes/main.cpp41
-rw-r--r--examples/quick/shapes/shapes.pro29
-rw-r--r--examples/quick/shapes/shapes.qrc31
-rw-r--r--examples/quick/shared/shared.h5
-rw-r--r--examples/quick/window/CurrentScreen.qml11
-rw-r--r--src/3rdparty/masm/assembler/MacroAssemblerX86_64.h51
-rw-r--r--src/3rdparty/masm/assembler/X86Assembler.h42
-rw-r--r--src/imports/imports.pro2
-rw-r--r--src/imports/qtquick2/plugins.qmltypes45
-rw-r--r--src/imports/shapes/plugin.cpp73
-rw-r--r--src/imports/shapes/plugins.qmltypes117
-rw-r--r--src/imports/shapes/qmldir4
-rw-r--r--src/imports/shapes/qquicknvprfunctions.cpp281
-rw-r--r--src/imports/shapes/qquicknvprfunctions_p.h400
-rw-r--r--src/imports/shapes/qquicknvprfunctions_p_p.h (renamed from src/quick/scenegraph/util/qsgdistancefieldutil_p.h)45
-rw-r--r--src/imports/shapes/qquickshape.cpp1347
-rw-r--r--src/imports/shapes/qquickshape_p.h287
-rw-r--r--src/imports/shapes/qquickshape_p_p.h280
-rw-r--r--src/imports/shapes/qquickshapegenericrenderer.cpp784
-rw-r--r--src/imports/shapes/qquickshapegenericrenderer_p.h308
-rw-r--r--src/imports/shapes/qquickshapenvprrenderer.cpp923
-rw-r--r--src/imports/shapes/qquickshapenvprrenderer_p.h237
-rw-r--r--src/imports/shapes/qquickshapesoftwarerenderer.cpp277
-rw-r--r--src/imports/shapes/qquickshapesoftwarerenderer_p.h136
-rw-r--r--src/imports/shapes/shapes.pro31
-rw-r--r--src/imports/testlib/TestCase.qml85
-rw-r--r--src/particles/qquickimageparticle.cpp58
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp26
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h4
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp7
-rw-r--r--src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp14
-rw-r--r--src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp17
-rw-r--r--src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp2
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp14
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12layer_p.h1
-rw-r--r--src/plugins/scenegraph/openvg/qsgopenvglayer.h1
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp145
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h26
-rw-r--r--src/qml/compiler/qqmlpropertycachecreator_p.h19
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp45
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h2
-rw-r--r--src/qml/compiler/qv4codegen.cpp149
-rw-r--r--src/qml/compiler/qv4codegen_p.h24
-rw-r--r--src/qml/compiler/qv4compileddata.cpp15
-rw-r--r--src/qml/compiler/qv4compileddata_p.h324
-rw-r--r--src/qml/compiler/qv4compiler.cpp24
-rw-r--r--src/qml/compiler/qv4compiler_p.h4
-rw-r--r--src/qml/compiler/qv4jsir_p.h26
-rw-r--r--src/qml/doc/src/cppintegration/data.qdoc18
-rw-r--r--src/qml/doc/src/javascript/functionlist.qdoc1
-rw-r--r--src/qml/doc/src/javascript/hostenvironment.qdoc13
-rw-r--r--src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc38
-rw-r--r--src/qml/doc/src/qmllanguageref/syntax/propertybinding.qdoc20
-rw-r--r--src/qml/jit/qv4assembler.cpp56
-rw-r--r--src/qml/jit/qv4assembler_p.h346
-rw-r--r--src/qml/jit/qv4binop.cpp2
-rw-r--r--src/qml/jit/qv4isel_masm.cpp94
-rw-r--r--src/qml/jit/qv4isel_masm_p.h18
-rw-r--r--src/qml/jsapi/qjsvalue.h6
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp60
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h28
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp193
-rw-r--r--src/qml/jsruntime/qv4arraydata_p.h161
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4context.cpp224
-rw-r--r--src/qml/jsruntime/qv4context_p.h161
-rw-r--r--src/qml/jsruntime/qv4dataview.cpp9
-rw-r--r--src/qml/jsruntime/qv4dataview_p.h13
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp51
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4engine.cpp78
-rw-r--r--src/qml/jsruntime/qv4engine_p.h47
-rw-r--r--src/qml/jsruntime/qv4enginebase_p.h6
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp44
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h14
-rw-r--r--src/qml/jsruntime/qv4function.cpp13
-rw-r--r--src/qml/jsruntime/qv4function_p.h6
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp66
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h28
-rw-r--r--src/qml/jsruntime/qv4global_p.h5
-rw-r--r--src/qml/jsruntime/qv4identifiertable_p.h4
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp58
-rw-r--r--src/qml/jsruntime/qv4internalclass_p.h3
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp76
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h18
-rw-r--r--src/qml/jsruntime/qv4managed.cpp1
-rw-r--r--src/qml/jsruntime/qv4managed_p.h7
-rw-r--r--src/qml/jsruntime/qv4memberdata.cpp15
-rw-r--r--src/qml/jsruntime/qv4memberdata_p.h35
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp56
-rw-r--r--src/qml/jsruntime/qv4numberobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4object.cpp228
-rw-r--r--src/qml/jsruntime/qv4object_p.h141
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp8
-rw-r--r--src/qml/jsruntime/qv4objectiterator_p.h2
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp128
-rw-r--r--src/qml/jsruntime/qv4objectproto_p.h1
-rw-r--r--src/qml/jsruntime/qv4persistent.cpp21
-rw-r--r--src/qml/jsruntime/qv4persistent_p.h4
-rw-r--r--src/qml/jsruntime/qv4property_p.h15
-rw-r--r--src/qml/jsruntime/qv4qmlcontext.cpp61
-rw-r--r--src/qml/jsruntime/qv4qmlcontext_p.h19
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp299
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h29
-rw-r--r--src/qml/jsruntime/qv4regexp.cpp6
-rw-r--r--src/qml/jsruntime/qv4regexp_p.h2
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp67
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h39
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp14
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp106
-rw-r--r--src/qml/jsruntime/qv4sequenceobject_p.h1
-rw-r--r--src/qml/jsruntime/qv4string.cpp6
-rw-r--r--src/qml/jsruntime/qv4string_p.h2
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp33
-rw-r--r--src/qml/jsruntime/qv4stringobject_p.h10
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp29
-rw-r--r--src/qml/jsruntime/qv4typedarray_p.h21
-rw-r--r--src/qml/jsruntime/qv4value_p.h3
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4variantobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp44
-rw-r--r--src/qml/memory/memory.pri3
-rw-r--r--src/qml/memory/qv4heap_p.h29
-rw-r--r--src/qml/memory/qv4mm.cpp384
-rw-r--r--src/qml/memory/qv4mm_p.h32
-rw-r--r--src/qml/memory/qv4mmdefs_p.h108
-rw-r--r--src/qml/memory/qv4writebarrier_p.h206
-rw-r--r--src/qml/parser/qqmljs.g62
-rw-r--r--src/qml/parser/qqmljsast.cpp17
-rw-r--r--src/qml/parser/qqmljsast_p.h90
-rw-r--r--src/qml/parser/qqmljsastfwd_p.h2
-rw-r--r--src/qml/parser/qqmljsastvisitor_p.h4
-rw-r--r--src/qml/parser/qqmljsgrammar.cpp2091
-rw-r--r--src/qml/parser/qqmljsgrammar_p.h294
-rw-r--r--src/qml/parser/qqmljskeywords_p.h11
-rw-r--r--src/qml/parser/qqmljslexer_p.h1
-rw-r--r--src/qml/parser/qqmljsparser.cpp404
-rw-r--r--src/qml/parser/qqmljsparser_p.h5
-rw-r--r--src/qml/qml/qqmlbinding.cpp46
-rw-r--r--src/qml/qml/qqmlbinding_p.h2
-rw-r--r--src/qml/qml/qqmlcomponent.cpp69
-rw-r--r--src/qml/qml/qqmlcomponent_p.h7
-rw-r--r--src/qml/qml/qqmlcustomparser.cpp22
-rw-r--r--src/qml/qml/qqmlengine.cpp36
-rw-r--r--src/qml/qml/qqmlengine.h4
-rw-r--r--src/qml/qml/qqmlglobal.cpp2
-rw-r--r--src/qml/qml/qqmlglobal_p.h1
-rw-r--r--src/qml/qml/qqmlimport.cpp36
-rw-r--r--src/qml/qml/qqmlimport_p.h13
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp13
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h2
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp3
-rw-r--r--src/qml/qml/qqmllistwrapper_p.h2
-rw-r--r--src/qml/qml/qqmlmetatype.cpp188
-rw-r--r--src/qml/qml/qqmlmetatype_p.h11
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp23
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h2
-rw-r--r--src/qml/qml/qqmlplatform.cpp6
-rw-r--r--src/qml/qml/qqmlplatform_p.h2
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp21
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h33
-rw-r--r--src/qml/qml/qqmltypeloader.cpp4
-rw-r--r--src/qml/qml/qqmltypenamecache.cpp4
-rw-r--r--src/qml/qml/qqmltypenamecache_p.h2
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp132
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h27
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp40
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h2
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp62
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h2
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp26
-rw-r--r--src/qml/types/qqmlconnections.cpp5
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp28
-rw-r--r--src/qml/types/qqmldelegatemodel_p_p.h5
-rw-r--r--src/qml/types/qqmllistmodel.cpp22
-rw-r--r--src/qml/types/qqmllistmodel_p_p.h4
-rw-r--r--src/qml/types/qquickpackage.cpp2
-rw-r--r--src/qml/util/qqmladaptormodel.cpp60
-rw-r--r--src/qml/util/qqmlpropertymap.cpp12
-rw-r--r--src/qml/util/qqmlpropertymap.h6
-rw-r--r--src/qmltest/quicktestresult.cpp40
-rw-r--r--src/quick/accessible/qaccessiblequickitem.cpp3
-rw-r--r--src/quick/designer/qquickdesignersupport.cpp5
-rw-r--r--src/quick/doc/images/declarative-arcrotation.pngbin0 -> 4315 bytes
-rw-r--r--src/quick/doc/images/pathitem-code-example.pngbin0 -> 5989 bytes
-rw-r--r--src/quick/doc/images/visualpath-code-example.pngbin0 -> 844 bytes
-rw-r--r--src/quick/doc/snippets/qml/layerblending.qml2
-rw-r--r--src/quick/doc/snippets/qml/opacitymask.qml2
-rw-r--r--src/quick/doc/snippets/qml/path/arcrotation.qml52
-rw-r--r--src/quick/doc/src/qmltypereference.qdoc1
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp30
-rw-r--r--src/quick/items/items.qrc4
-rw-r--r--src/quick/items/qquickanimatedimage_p.h1
-rw-r--r--src/quick/items/qquickflickable.cpp122
-rw-r--r--src/quick/items/qquickflickable_p.h11
-rw-r--r--src/quick/items/qquickflickable_p_p.h1
-rw-r--r--src/quick/items/qquickgenericshadereffect.cpp3
-rw-r--r--src/quick/items/qquickimage.cpp35
-rw-r--r--src/quick/items/qquickimage_p_p.h2
-rw-r--r--src/quick/items/qquickimagebase.cpp65
-rw-r--r--src/quick/items/qquickimagebase_p.h1
-rw-r--r--src/quick/items/qquickimagebase_p_p.h4
-rw-r--r--src/quick/items/qquickimplicitsizeitem.cpp26
-rw-r--r--src/quick/items/qquickimplicitsizeitem_p.h8
-rw-r--r--src/quick/items/qquickimplicitsizeitem_p_p.h3
-rw-r--r--src/quick/items/qquickitem.cpp117
-rw-r--r--src/quick/items/qquickitem.h4
-rw-r--r--src/quick/items/qquickitem_p.h17
-rw-r--r--src/quick/items/qquickitemanimation.cpp2
-rw-r--r--src/quick/items/qquickitemchangelistener_p.h1
-rw-r--r--src/quick/items/qquickitemsmodule.cpp12
-rw-r--r--src/quick/items/qquickopenglshadereffect.cpp28
-rw-r--r--src/quick/items/qquickopenglshadereffectnode.cpp15
-rw-r--r--src/quick/items/qquickopenglshadereffectnode_p.h2
-rw-r--r--src/quick/items/qquickpositioners.cpp9
-rw-r--r--src/quick/items/qquickpositioners_p.h1
-rw-r--r--src/quick/items/qquickpositioners_p_p.h3
-rw-r--r--src/quick/items/qquickrectangle.cpp9
-rw-r--r--src/quick/items/qquickrectangle_p_p.h15
-rw-r--r--src/quick/items/qquickscreen.cpp48
-rw-r--r--src/quick/items/qquickscreen_p.h9
-rw-r--r--src/quick/items/qquickshadereffectsource.cpp40
-rw-r--r--src/quick/items/qquickshadereffectsource_p.h6
-rw-r--r--src/quick/items/qquickstateoperations.cpp2
-rw-r--r--src/quick/items/qquicktext.cpp79
-rw-r--r--src/quick/items/qquicktext_p.h2
-rw-r--r--src/quick/items/qquicktext_p_p.h2
-rw-r--r--src/quick/items/qquicktextedit.cpp13
-rw-r--r--src/quick/items/qquicktextinput.cpp13
-rw-r--r--src/quick/items/qquickwindow.cpp9
-rw-r--r--src/quick/items/qquickwindow.h4
-rw-r--r--src/quick/items/qquickwindowmodule.cpp1
-rw-r--r--src/quick/items/shaders/lineargradient.frag9
-rw-r--r--src/quick/items/shaders/lineargradient.vert15
-rw-r--r--src/quick/items/shaders/lineargradient_core.frag12
-rw-r--r--src/quick/items/shaders/lineargradient_core.vert17
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarelayer_p.h1
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp2
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes.cpp8
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp21
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp2
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp4
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer.cpp22
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer_p.h2
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendernode.cpp9
-rw-r--r--src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp1
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp6
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer_p.h8
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp9
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h3
-rw-r--r--src/quick/scenegraph/qsgcontextplugin.cpp11
-rw-r--r--src/quick/scenegraph/qsgdefaultcontext.cpp5
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp20
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h2
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.cpp20
-rw-r--r--src/quick/scenegraph/qsgdefaultinternalimagenode.cpp6
-rw-r--r--src/quick/scenegraph/qsgdefaultinternalrectanglenode.cpp6
-rw-r--r--src/quick/scenegraph/qsgdefaultlayer.cpp20
-rw-r--r--src/quick/scenegraph/qsgdefaultlayer_p.h4
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext.cpp37
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext_p.h2
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode.cpp16
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp68
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p.h2
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp24
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp4
-rw-r--r--src/quick/scenegraph/scenegraph.pri2
-rw-r--r--src/quick/scenegraph/util/qsgdistancefieldutil.cpp115
-rw-r--r--src/quick/scenegraph/util/qsgflatcolormaterial.cpp6
-rw-r--r--src/quick/scenegraph/util/qsgtexture.cpp24
-rw-r--r--src/quick/scenegraph/util/qsgtexture.h3
-rw-r--r--src/quick/scenegraph/util/qsgtexture_p.h4
-rw-r--r--src/quick/scenegraph/util/qsgtexturematerial.cpp4
-rw-r--r--src/quick/scenegraph/util/qsgvertexcolormaterial.cpp6
-rw-r--r--src/quick/util/qquickanimatorjob.cpp25
-rw-r--r--src/quick/util/qquickanimatorjob_p.h1
-rw-r--r--src/quick/util/qquickglobal.cpp36
-rw-r--r--src/quick/util/qquickimageprovider.cpp14
-rw-r--r--src/quick/util/qquickpath.cpp184
-rw-r--r--src/quick/util/qquickpath_p.h19
-rw-r--r--src/quick/util/qquickpath_p_p.h2
-rw-r--r--src/quick/util/qquickpixmapcache.cpp4
-rw-r--r--src/quick/util/qquicksvgparser.cpp8
-rw-r--r--src/quick/util/qquicksvgparser_p.h7
-rw-r--r--src/quick/util/qquickvaluetypes.cpp10
-rw-r--r--src/quick/util/qquickvaluetypes_p.h4
-rw-r--r--tests/auto/qml/ecmascripttests/TestExpectations147
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp11
-rw-r--r--tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp36
-rw-r--r--tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp8
-rw-r--r--tests/auto/qml/qqmlbinding/data/bindingOverwriting.qml13
-rw-r--r--tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp16
-rw-r--r--tests/auto/qml/qqmlconnections/data/connection-no-signal-name.qml15
-rw-r--r--tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp10
-rw-r--r--tests/auto/qml/qqmlecmascript/data/dynamicString.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/sequenceSort.qml14
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.cpp24
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp110
-rw-r--r--tests/auto/qml/qqmlengine/tst_qqmlengine.cpp3
-rw-r--r--tests/auto/qml/qqmllanguage/data/TypeWithEnum.qml14
-rw-r--r--tests/auto/qml/qqmllanguage/data/cppnamespace.qml1
-rw-r--r--tests/auto/qml/qqmllanguage/data/instanceOf/CustomMouseArea.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/instanceOf/CustomRectangle.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/data/instanceOf/CustomRectangleWithProp.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/instanceOf/qmldir2
-rw-r--r--tests/auto/qml/qqmllanguage/data/instanceof_qtqml.qml13
-rw-r--r--tests/auto/qml/qqmllanguage/data/instanceof_qtqml_qualified.qml13
-rw-r--r--tests/auto/qml/qqmllanguage/data/instanceof_qtquick.qml14
-rw-r--r--tests/auto/qml/qqmllanguage/data/instanceof_qtquick_composite.qml26
-rw-r--r--tests/auto/qml/qqmllanguage/data/instanceof_qtquick_composite_qualified.qml27
-rw-r--r--tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/NonSingletonType.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/SingletonType.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/qmldir4
-rw-r--r--tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/test.js1
-rw-r--r--tests/auto/qml/qqmllanguage/data/lowercaseQmlEnum.1.errors.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/lowercaseQmlEnum.1.qml9
-rw-r--r--tests/auto/qml/qqmllanguage/data/lowercaseQmlEnum.2.errors.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/lowercaseQmlEnum.2.qml9
-rw-r--r--tests/auto/qml/qqmllanguage/data/mixedModuleWithSelfImport.qml3
-rw-r--r--tests/auto/qml/qqmllanguage/data/registeredCompositeTypeWithEnum.qml1
-rw-r--r--tests/auto/qml/qqmllanguage/data/scopedEnum.qml21
-rw-r--r--tests/auto/qml/qqmllanguage/data/scopedEnumList.errors.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/scopedEnumList.qml10
-rw-r--r--tests/auto/qml/qqmllanguage/data/usingTypeWithEnum.qml8
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h18
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp260
-rw-r--r--tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp4
-rw-r--r--tests/auto/qml/qqmltranslation/data/TranslationChangeBase.qml5
-rw-r--r--tests/auto/qml/qqmltranslation/data/translationChange.qml10
-rw-r--r--tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp46
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.expectbin0 -> 223 bytes
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.qml23
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp1
-rw-r--r--tests/auto/qmltest/BLACKLIST16
-rw-r--r--tests/auto/qmltest/animatedimage/animatedimage.pro1
-rw-r--r--tests/auto/qmltest/animations/animations.pro1
-rw-r--r--tests/auto/qmltest/borderimage/borderimage.pro1
-rw-r--r--tests/auto/qmltest/buttonclick/buttonclick.pro1
-rw-r--r--tests/auto/qmltest/createbenchmark/createbenchmark.pro1
-rw-r--r--tests/auto/qmltest/events/events.pro1
-rw-r--r--tests/auto/qmltest/fontloader/fontloader.pro1
-rw-r--r--tests/auto/qmltest/gradient/gradient.pro1
-rw-r--r--tests/auto/qmltest/image/image.pro1
-rw-r--r--tests/auto/qmltest/itemgrabber/itemgrabber.pro1
-rw-r--r--tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml4
-rw-r--r--tests/auto/qmltest/layout/layout.pro1
-rw-r--r--tests/auto/qmltest/listmodel/listmodel.pro1
-rw-r--r--tests/auto/qmltest/listview/BLACKLIST4
-rw-r--r--tests/auto/qmltest/listview/listview.pro1
-rw-r--r--tests/auto/qmltest/objectmodel/objectmodel.pro1
-rw-r--r--tests/auto/qmltest/pathview/pathview.pro1
-rw-r--r--tests/auto/qmltest/pixel/pixel.pro1
-rw-r--r--tests/auto/qmltest/positioners/positioners.pro1
-rw-r--r--tests/auto/qmltest/qmltest.pro44
-rw-r--r--tests/auto/qmltest/qqmlbinding/qqmlbinding.pro1
-rw-r--r--tests/auto/qmltest/qtbug46798/qtbug46798.pro1
-rw-r--r--tests/auto/qmltest/rectangle/rectangle.pro1
-rw-r--r--tests/auto/qmltest/selftests/BLACKLIST13
-rw-r--r--tests/auto/qmltest/selftests/selftests.pro1
-rw-r--r--tests/auto/qmltest/selftests/tst_grabImage.qml62
-rw-r--r--tests/auto/qmltest/selftests/tst_selftests.qml10
-rw-r--r--tests/auto/qmltest/shadersource/BLACKLIST3
-rw-r--r--tests/auto/qmltest/shadersource/shadersource.pro1
-rw-r--r--tests/auto/qmltest/stability/stability.pro1
-rw-r--r--tests/auto/qmltest/statemachine/statemachine.pro1
-rw-r--r--tests/auto/qmltest/text/text.pro1
-rw-r--r--tests/auto/qmltest/textedit/BLACKLIST6
-rw-r--r--tests/auto/qmltest/textedit/textedit.pro1
-rw-r--r--tests/auto/qmltest/textinput/textinput.pro1
-rw-r--r--tests/auto/qmltest/tst_qmltest.cpp30
-rw-r--r--tests/auto/qmltest/window/window.pro1
-rw-r--r--tests/auto/quick/examples/tst_examples.cpp2
-rw-r--r--tests/auto/quick/nokeywords/tst_nokeywords.cpp1
-rw-r--r--tests/auto/quick/qquickapplication/data/tst_platformname.qml6
-rw-r--r--tests/auto/quick/qquickapplication/qquickapplication.pro3
-rw-r--r--tests/auto/quick/qquickapplication/tst_qquickapplication.cpp19
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp143
-rw-r--r--tests/auto/quick/qquickimage/tst_qquickimage.cpp61
-rw-r--r--tests/auto/quick/qquickrectangle/data/gradient-multiple.qml30
-rw-r--r--tests/auto/quick/qquickrectangle/data/gradient-separate.qml20
-rw-r--r--tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp59
-rw-r--r--tests/auto/quick/qquickscreen/tst_qquickscreen.cpp3
-rw-r--r--tests/auto/quick/qquickshape/data/pathitem1.qml5
-rw-r--r--tests/auto/quick/qquickshape/data/pathitem2.qml7
-rw-r--r--tests/auto/quick/qquickshape/data/pathitem3.pngbin0 -> 5214 bytes
-rw-r--r--tests/auto/quick/qquickshape/data/pathitem3.qml33
-rw-r--r--tests/auto/quick/qquickshape/data/pathitem4.pngbin0 -> 5713 bytes
-rw-r--r--tests/auto/quick/qquickshape/data/pathitem4.qml56
-rw-r--r--tests/auto/quick/qquickshape/qquickshape.pro35
-rw-r--r--tests/auto/quick/qquickshape/tst_qquickshape.cpp250
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp55
-rw-r--r--tests/auto/quick/qquickwindow/BLACKLIST4
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp6
-rw-r--r--tests/auto/quick/quick.pro1
-rw-r--r--tests/benchmarks/qml/creation/tst_creation.cpp4
-rw-r--r--tests/manual/scenegraph_lancelot/data/shape/shape_arc.qml112
-rw-r--r--tests/manual/scenegraph_lancelot/data/shape/shape_arc_fill.qml112
-rw-r--r--tests/manual/scenegraph_lancelot/data/shape/shape_cubic.qml35
-rw-r--r--tests/manual/scenegraph_lancelot/data/shape/shape_linear_gradient.qml33
-rw-r--r--tests/manual/scenegraph_lancelot/data/shape/shape_lines.qml92
-rw-r--r--tests/manual/scenegraph_lancelot/data/shape/shape_quad.qml34
-rw-r--r--tests/manual/scenegraph_lancelot/data/shape/shape_spread.qml35
-rw-r--r--tests/manual/scenegraph_lancelot/data/text/text_advance_bidi_ltr.qml56
-rw-r--r--tests/manual/scenegraph_lancelot/data/text/text_advance_hebrew.qml54
-rw-r--r--tests/manual/scenegraph_lancelot/data/text/text_advance_latin.qml55
-rw-r--r--tests/manual/scenegraph_lancelot/data/text/text_advance_multiline.qml55
-rw-r--r--tests/manual/scenegraph_lancelot/data/text/text_advance_multiparagraph.qml39
-rw-r--r--tests/manual/scenegraph_lancelot/data/text/text_advance_multiparagraph_multifontsizes.qml39
-rw-r--r--tests/manual/scenegraph_lancelot/data/text/text_nokerning_latin.qml16
-rw-r--r--tests/manual/shapestest/main.cpp69
-rw-r--r--tests/manual/shapestest/shapestest.pro6
-rw-r--r--tests/manual/shapestest/shapestest.qml396
-rw-r--r--tests/manual/shapestest/shapestest.qrc5
-rw-r--r--tests/manual/v4/typedarrays.js4
-rw-r--r--tools/qml/main.cpp4
-rw-r--r--tools/qml/qml.pro9
-rw-r--r--tools/qmlcachegen/qmlcachegen.pro2
-rw-r--r--tools/qmleasing/qmleasing.pro9
-rw-r--r--tools/qmlimportscanner/main.cpp4
-rw-r--r--tools/qmlimportscanner/qmlimportscanner.pro9
-rw-r--r--tools/qmljs/qmljs.cpp4
-rw-r--r--tools/qmljs/qmljs.pro9
-rw-r--r--tools/qmllint/qmllint.pro9
-rw-r--r--tools/qmlmin/main.cpp10
-rw-r--r--tools/qmlmin/qmlmin.pro9
-rw-r--r--tools/qmlplugindump/qmlplugindump.pro9
-rw-r--r--tools/qmlprofiler/qmlprofiler.pro9
-rw-r--r--tools/qmlprofiler/qmlprofilerdata.cpp10
-rw-r--r--tools/qmlscene/main.cpp96
-rw-r--r--tools/qmlscene/qmlscene.pro9
-rw-r--r--tools/qmltestrunner/qmltestrunner.pro9
-rw-r--r--tools/qmltime/qmltime.pro10
469 files changed, 21951 insertions, 4465 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 8881d4bba8..4e4a28b8f9 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -1,4 +1,4 @@
load(qt_build_config)
CONFIG += warning_clean
-MODULE_VERSION = 5.9.2
+MODULE_VERSION = 5.10.0
diff --git a/examples/quick/customitems/painteditem/textballoon.cpp b/examples/quick/customitems/painteditem/textballoon.cpp
index 1713cc762f..bd8248e65e 100644
--- a/examples/quick/customitems/painteditem/textballoon.cpp
+++ b/examples/quick/customitems/painteditem/textballoon.cpp
@@ -67,23 +67,24 @@ void TextBalloon::paint(QPainter *painter)
painter->setPen(Qt::NoPen);
painter->setRenderHint(QPainter::Antialiasing);
- painter->drawRoundedRect(0, 0, boundingRect().width(), boundingRect().height() - 10, 10, 10);
+ QSizeF itemSize = size();
+ painter->drawRoundedRect(0, 0, itemSize.width(), itemSize.height() - 10, 10, 10);
if (rightAligned)
{
const QPointF points[3] = {
- QPointF(boundingRect().width() - 10.0, boundingRect().height() - 10.0),
- QPointF(boundingRect().width() - 20.0, boundingRect().height()),
- QPointF(boundingRect().width() - 30.0, boundingRect().height() - 10.0),
+ QPointF(itemSize.width() - 10.0, itemSize.height() - 10.0),
+ QPointF(itemSize.width() - 20.0, itemSize.height()),
+ QPointF(itemSize.width() - 30.0, itemSize.height() - 10.0),
};
painter->drawConvexPolygon(points, 3);
}
else
{
const QPointF points[3] = {
- QPointF(10.0, boundingRect().height() - 10.0),
- QPointF(20.0, boundingRect().height()),
- QPointF(30.0, boundingRect().height() - 10.0),
+ QPointF(10.0, itemSize.height() - 10.0),
+ QPointF(20.0, itemSize.height()),
+ QPointF(30.0, itemSize.height() - 10.0),
};
painter->drawConvexPolygon(points, 3);
}
diff --git a/examples/quick/quick.pro b/examples/quick/quick.pro
index 445dfb0fab..22dfff703e 100644
--- a/examples/quick/quick.pro
+++ b/examples/quick/quick.pro
@@ -24,6 +24,7 @@ SUBDIRS = quick-accessibility \
imageresponseprovider \
window \
particles \
+ shapes \
demos
#OpenGL Support Required
diff --git a/examples/quick/rendercontrol/window_singlethreaded.cpp b/examples/quick/rendercontrol/window_singlethreaded.cpp
index ef8f2fed43..bd4de9a7cb 100644
--- a/examples/quick/rendercontrol/window_singlethreaded.cpp
+++ b/examples/quick/rendercontrol/window_singlethreaded.cpp
@@ -82,6 +82,10 @@ WindowSingleThreaded::WindowSingleThreaded()
{
setSurfaceType(QSurface::OpenGLSurface);
+ // The rendercontrol does not necessarily need an FBO. Demonstrate this
+ // when requested.
+ m_onscreen = QCoreApplication::arguments().contains(QStringLiteral("--onscreen"));
+
QSurfaceFormat format;
// Qt Quick may need a depth and stencil buffer. Always make sure these are available.
format.setDepthBufferSize(16);
@@ -164,8 +168,14 @@ void WindowSingleThreaded::createFbo()
// The scene graph has been initialized. It is now time to create an FBO and associate
// it with the QQuickWindow.
m_dpr = devicePixelRatio();
- m_fbo = new QOpenGLFramebufferObject(size() * m_dpr, QOpenGLFramebufferObject::CombinedDepthStencil);
- m_quickWindow->setRenderTarget(m_fbo);
+ if (!m_onscreen) {
+ m_fbo = new QOpenGLFramebufferObject(size() * m_dpr, QOpenGLFramebufferObject::CombinedDepthStencil);
+ m_quickWindow->setRenderTarget(m_fbo);
+ } else {
+ // Special case: No FBO. Render directly to the window's default framebuffer.
+ m_onscreenSize = size() * m_dpr;
+ m_quickWindow->setRenderTarget(0, m_onscreenSize);
+ }
}
void WindowSingleThreaded::destroyFbo()
@@ -176,7 +186,10 @@ void WindowSingleThreaded::destroyFbo()
void WindowSingleThreaded::render()
{
- if (!m_context->makeCurrent(m_offscreenSurface))
+ QSurface *surface = m_offscreenSurface;
+ if (m_onscreen)
+ surface = this;
+ if (!m_context->makeCurrent(surface))
return;
// Polish, synchronize and render the next frame (into our fbo). In this example
@@ -195,7 +208,10 @@ void WindowSingleThreaded::render()
m_quickReady = true;
// Get something onto the screen.
- m_cubeRenderer->render(this, m_context, m_quickReady ? m_fbo->texture() : 0);
+ if (!m_onscreen)
+ m_cubeRenderer->render(this, m_context, m_quickReady ? m_fbo->texture() : 0);
+ else
+ m_context->swapBuffers(this);
}
void WindowSingleThreaded::requestUpdate()
@@ -237,7 +253,10 @@ void WindowSingleThreaded::run()
updateSizes();
// Initialize the render control and our OpenGL resources.
- m_context->makeCurrent(m_offscreenSurface);
+ QSurface *surface = m_offscreenSurface;
+ if (m_onscreen)
+ surface = this;
+ m_context->makeCurrent(surface);
m_renderControl->initialize(m_context);
m_quickInitialized = true;
}
@@ -266,7 +285,8 @@ void WindowSingleThreaded::exposeEvent(QExposeEvent *)
{
if (isExposed()) {
if (!m_quickInitialized) {
- m_cubeRenderer->render(this, m_context, m_quickReady ? m_fbo->texture() : 0);
+ if (!m_onscreen)
+ m_cubeRenderer->render(this, m_context, m_quickReady ? m_fbo->texture() : 0);
startQuick(QStringLiteral("qrc:/rendercontrol/demo.qml"));
}
}
@@ -274,7 +294,10 @@ void WindowSingleThreaded::exposeEvent(QExposeEvent *)
void WindowSingleThreaded::resizeFbo()
{
- if (m_rootItem && m_context->makeCurrent(m_offscreenSurface)) {
+ QSurface *surface = m_offscreenSurface;
+ if (m_onscreen)
+ surface = this;
+ if (m_rootItem && m_context->makeCurrent(surface)) {
delete m_fbo;
createFbo();
m_context->doneCurrent();
@@ -287,8 +310,13 @@ void WindowSingleThreaded::resizeEvent(QResizeEvent *)
{
// If this is a resize after the scene is up and running, recreate the fbo and the
// Quick item and scene.
- if (m_fbo && m_fbo->size() != size() * devicePixelRatio())
- resizeFbo();
+ if (!m_onscreen) {
+ if (m_fbo && m_fbo->size() != size() * devicePixelRatio())
+ resizeFbo();
+ } else {
+ if (m_onscreenSize != size() * devicePixelRatio())
+ resizeFbo();
+ }
}
void WindowSingleThreaded::handleScreenChange()
diff --git a/examples/quick/rendercontrol/window_singlethreaded.h b/examples/quick/rendercontrol/window_singlethreaded.h
index 534d6b9bc3..4736f036ad 100644
--- a/examples/quick/rendercontrol/window_singlethreaded.h
+++ b/examples/quick/rendercontrol/window_singlethreaded.h
@@ -97,6 +97,8 @@ private:
QTimer m_updateTimer;
CubeRenderer *m_cubeRenderer;
qreal m_dpr;
+ bool m_onscreen;
+ QSize m_onscreenSize;
};
#endif
diff --git a/examples/quick/scenegraph/customgeometry/beziercurve.cpp b/examples/quick/scenegraph/customgeometry/beziercurve.cpp
index ca3c6f524b..750ff6aa3b 100644
--- a/examples/quick/scenegraph/customgeometry/beziercurve.cpp
+++ b/examples/quick/scenegraph/customgeometry/beziercurve.cpp
@@ -152,7 +152,7 @@ QSGNode *BezierCurve::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
//! [7]
//! [8]
- QRectF bounds = boundingRect();
+ QSizeF itemSize = size();
QSGGeometry::Point2D *vertices = geometry->vertexDataAsPoint2D();
for (int i = 0; i < m_segmentCount; ++i) {
qreal t = i / qreal(m_segmentCount - 1);
@@ -163,8 +163,8 @@ QSGNode *BezierCurve::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+ 3 * invt * t * t * m_p3
+ t * t * t * m_p4;
- float x = bounds.x() + pos.x() * bounds.width();
- float y = bounds.y() + pos.y() * bounds.height();
+ float x = pos.x() * itemSize.width();
+ float y = pos.y() * itemSize.height();
vertices[i].set(x, y);
}
diff --git a/examples/quick/scenegraph/graph/shaders/line.fsh b/examples/quick/scenegraph/graph/shaders/line.fsh
index 5d38c46d4d..41c0ee3c00 100644
--- a/examples/quick/scenegraph/graph/shaders/line.fsh
+++ b/examples/quick/scenegraph/graph/shaders/line.fsh
@@ -44,7 +44,7 @@ uniform lowp float spread;
varying lowp float vT;
-#define PI 3.14159265359
+#define PI 3.14159265358979323846
void main(void)
{
diff --git a/examples/quick/scenegraph/graph/shaders/noisy.fsh b/examples/quick/scenegraph/graph/shaders/noisy.fsh
index 30b0def932..c217e635ef 100644
--- a/examples/quick/scenegraph/graph/shaders/noisy.fsh
+++ b/examples/quick/scenegraph/graph/shaders/noisy.fsh
@@ -45,7 +45,7 @@ uniform lowp vec4 color;
varying highp vec2 vTexCoord;
varying lowp vec2 vShadeCoord;
-#define PI 3.14159265359
+#define PI 3.14159265358979323846
void main()
{
diff --git a/examples/quick/scenegraph/rendernode/softwarerenderer.cpp b/examples/quick/scenegraph/rendernode/softwarerenderer.cpp
index d303b9ef13..f4ee976705 100644
--- a/examples/quick/scenegraph/rendernode/softwarerenderer.cpp
+++ b/examples/quick/scenegraph/rendernode/softwarerenderer.cpp
@@ -64,11 +64,12 @@ void SoftwareRenderNode::render(const RenderState *renderState)
QPainter *p = static_cast<QPainter *>(rif->getResource(m_item->window(), QSGRendererInterface::PainterResource));
Q_ASSERT(p);
- p->setTransform(matrix()->toTransform());
- p->setOpacity(inheritedOpacity());
const QRegion *clipRegion = renderState->clipRegion();
if (clipRegion && !clipRegion->isEmpty())
- p->setClipRegion(*clipRegion, Qt::IntersectClip);
+ p->setClipRegion(*clipRegion, Qt::ReplaceClip); // must be done before setTransform
+
+ p->setTransform(matrix()->toTransform());
+ p->setOpacity(inheritedOpacity());
const QPointF p0(m_item->width() - 1, m_item->height() - 1);
const QPointF p1(0, 0);
diff --git a/examples/quick/scenegraph/shared/logorenderer.cpp b/examples/quick/scenegraph/shared/logorenderer.cpp
index 8eb2d44c1e..5c3a770f54 100644
--- a/examples/quick/scenegraph/shared/logorenderer.cpp
+++ b/examples/quick/scenegraph/shared/logorenderer.cpp
@@ -41,7 +41,7 @@
#include "logorenderer.h"
#include <QPainter>
#include <QPaintEngine>
-#include <math.h>
+#include <qmath.h>
LogoRenderer::LogoRenderer()
{
@@ -166,7 +166,7 @@ void LogoRenderer::createGeometry()
extrude(x4, y4, y4, x4);
extrude(y4, x4, y3, x3);
- const qreal Pi = 3.14159f;
+ const qreal Pi = M_PI;
const int NumSectors = 100;
for (int i = 0; i < NumSectors; ++i) {
diff --git a/examples/quick/scenegraph/textureinsgnode/main.qml b/examples/quick/scenegraph/textureinsgnode/main.qml
index fe145b0f05..ba110a278d 100644
--- a/examples/quick/scenegraph/textureinsgnode/main.qml
+++ b/examples/quick/scenegraph/textureinsgnode/main.qml
@@ -64,7 +64,7 @@ Item {
uniform highp vec2 pixelSize;
varying highp vec2 qt_TexCoord0;
void main() {
- highp vec2 tc = sign(sin(3.14152 * qt_TexCoord0 * pixelSize));
+ highp vec2 tc = sign(sin(3.14159265358979323846 * qt_TexCoord0 * pixelSize));
if (tc.x != tc.y)
gl_FragColor = color1;
else
diff --git a/examples/quick/scenegraph/textureinthread/main.qml b/examples/quick/scenegraph/textureinthread/main.qml
index 9108f0281d..2d61488e85 100644
--- a/examples/quick/scenegraph/textureinthread/main.qml
+++ b/examples/quick/scenegraph/textureinthread/main.qml
@@ -64,7 +64,7 @@ Item {
uniform highp vec2 pixelSize;
varying highp vec2 qt_TexCoord0;
void main() {
- highp vec2 tc = sign(sin(3.14152 * qt_TexCoord0 * pixelSize));
+ highp vec2 tc = sign(sin(3.14159265358979323846 * qt_TexCoord0 * pixelSize));
if (tc.x != tc.y)
gl_FragColor = color1;
else
diff --git a/examples/quick/scenegraph/twotextureproviders/main.qml b/examples/quick/scenegraph/twotextureproviders/main.qml
index af07f9badd..a6202b5a09 100644
--- a/examples/quick/scenegraph/twotextureproviders/main.qml
+++ b/examples/quick/scenegraph/twotextureproviders/main.qml
@@ -61,7 +61,7 @@ Item {
uniform highp vec2 pixelSize;
varying highp vec2 qt_TexCoord0;
void main() {
- highp vec2 tc = sign(sin(3.14152 * qt_TexCoord0 * pixelSize));
+ highp vec2 tc = sign(sin(3.14159265358979323846 * qt_TexCoord0 * pixelSize));
if (tc.x != tc.y)
gl_FragColor = color1;
else
diff --git a/examples/quick/shapes/content/item1.qml b/examples/quick/shapes/content/item1.qml
new file mode 100644
index 0000000000..9328979324
--- /dev/null
+++ b/examples/quick/shapes/content/item1.qml
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ color: "lightGray"
+
+ Shape {
+ id: ctr
+ anchors.fill: parent
+
+ ShapePath {
+ strokeColor: "red"
+ fillColor: "blue"
+
+ SequentialAnimation on strokeWidth {
+ loops: Animation.Infinite
+ NumberAnimation { from: 1; to: 30; duration: 5000 }
+ NumberAnimation { from: 30; to: 1; duration: 5000 }
+ PauseAnimation { duration: 2000 }
+ }
+
+ startX: 30; startY: 30
+ PathLine { x: ctr.width - 30; y: ctr.height - 30 }
+ PathLine { x: 30; y: ctr.height - 30 }
+ PathLine { x: 30; y: 30 }
+ }
+
+ // Besides ShapePath, Shape supports visual and non-visual objects too, allowing
+ // free mixing without going through extra hoops:
+ Rectangle {
+ id: testRect
+ color: "green"
+ opacity: 0.3
+ width: 20
+ height: 20
+ anchors.right: parent.right
+ }
+ Timer {
+ interval: 100
+ repeat: true
+ onTriggered: testRect.width = testRect.width > 1 ? testRect.width - 1 : 20
+ running: true
+ }
+ }
+}
diff --git a/examples/quick/shapes/content/item10.qml b/examples/quick/shapes/content/item10.qml
new file mode 100644
index 0000000000..cb2444fe4b
--- /dev/null
+++ b/examples/quick/shapes/content/item10.qml
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ color: "lightGray"
+
+ Item {
+ width: 200
+ height: 200
+ anchors.centerIn: parent
+
+ Shape {
+ id: shape
+ anchors.fill: parent
+
+ ShapePath {
+ strokeWidth: 4
+ strokeColor: "black"
+ fillColor: "lightBlue"
+
+ startX: 50; startY: 100
+ PathCubic {
+ x: 150; y: 100
+ control1X: cp1.x; control1Y: cp1.y
+ control2X: cp2.x; control2Y: cp2.y
+ }
+ }
+ }
+
+ Rectangle {
+ id: cp1
+ color: "red"
+ width: 10; height: 10
+ SequentialAnimation {
+ loops: Animation.Infinite
+ running: true
+ NumberAnimation {
+ target: cp1
+ property: "x"
+ from: 0
+ to: shape.width - cp1.width
+ duration: 5000
+ }
+ NumberAnimation {
+ target: cp1
+ property: "x"
+ from: shape.width - cp1.width
+ to: 0
+ duration: 5000
+ }
+ NumberAnimation {
+ target: cp1
+ property: "y"
+ from: 0
+ to: shape.height - cp1.height
+ duration: 5000
+ }
+ NumberAnimation {
+ target: cp1
+ property: "y"
+ from: shape.height - cp1.height
+ to: 0
+ duration: 5000
+ }
+ }
+ }
+
+ Rectangle {
+ id: cp2
+ color: "blue"
+ width: 10; height: 10
+ x: shape.width - width
+ SequentialAnimation {
+ loops: Animation.Infinite
+ running: true
+ NumberAnimation {
+ target: cp2
+ property: "y"
+ from: 0
+ to: shape.height - cp2.height
+ duration: 5000
+ }
+ NumberAnimation {
+ target: cp2
+ property: "y"
+ from: shape.height - cp2.height
+ to: 0
+ duration: 5000
+ }
+ NumberAnimation {
+ target: cp2
+ property: "x"
+ from: shape.width - cp2.width
+ to: 0
+ duration: 5000
+ }
+ NumberAnimation {
+ target: cp2
+ property: "x"
+ from: 0
+ to: shape.width - cp2.width
+ duration: 5000
+ }
+ }
+ }
+ }
+}
diff --git a/examples/quick/shapes/content/item11.qml b/examples/quick/shapes/content/item11.qml
new file mode 100644
index 0000000000..0cfe73d5c9
--- /dev/null
+++ b/examples/quick/shapes/content/item11.qml
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ color: "lightGray"
+ Shape {
+ id: shape
+ width: 220
+ height: 200
+ anchors.centerIn: parent
+
+ ShapePath {
+ fillGradient: LinearGradient {
+ y2: shape.height
+ GradientStop { position: 0; color: "yellow" }
+ GradientStop { position: 1; color: "green" }
+ }
+
+ startX: 10; startY: 100
+ PathArc {
+ relativeX: 50; y: 100
+ radiusX: 25; radiusY: 25
+ }
+ PathArc {
+ relativeX: 50; y: 100
+ radiusX: 25; radiusY: 35
+ }
+ PathArc {
+ relativeX: 50; y: 100
+ radiusX: 25; radiusY: 60
+ }
+ PathArc {
+ relativeX: 50; y: 100
+ radiusX: 50; radiusY: 120
+ }
+ }
+ }
+
+ Shape {
+ width: 120
+ height: 130
+ anchors.bottom: parent.bottom
+ anchors.right: parent.right
+
+ scale: 0.5
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: "darkBlue"
+ strokeWidth: 20
+ capStyle: ShapePath.RoundCap
+
+ startX: 20; startY: 50
+ PathArc {
+ x: 20; y: 90
+ radiusX: 45; radiusY: 45
+ useLargeArc: true
+ }
+ }
+ }
+}
diff --git a/examples/quick/shapes/content/item12.qml b/examples/quick/shapes/content/item12.qml
new file mode 100644
index 0000000000..8bdd1bfe50
--- /dev/null
+++ b/examples/quick/shapes/content/item12.qml
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ color: "lightGray"
+ Rectangle {
+ border.color: "black"
+ width: 200
+ height: 200
+ anchors.centerIn: parent
+
+ Shape {
+ anchors.fill: parent
+
+ ShapePath {
+ strokeColor: "transparent"
+
+ fillGradient: LinearGradient {
+ id: grad
+ y1: 50; y2: 150
+ GradientStop { position: 0; color: "black" }
+ GradientStop { position: 1; color: "red" }
+ }
+
+ startX: 10; startY: 10
+ PathLine { relativeX: 180; relativeY: 0 }
+ PathLine { relativeX: 0; relativeY: 180 }
+ PathLine { relativeX: -180; relativeY: 0 }
+ PathLine { relativeX: 0; relativeY: -180 }
+ }
+ }
+
+ Timer {
+ id: spreadTimer
+ interval: 3000
+ running: true
+ repeat: true
+ property variant spreads: [ ShapeGradient.PadSpread, ShapeGradient.RepeatSpread, ShapeGradient.ReflectSpread ]
+ property variant spreadTexts: [ "PadSpread", "RepeatSpread", "ReflectSpread" ]
+ property int spreadIdx: 0
+ onTriggered: { spreadIdx = (spreadIdx + 1) % spreads.length; grad.spread = spreads[spreadIdx] }
+ }
+
+
+ Shape {
+ anchors.fill: parent
+ ShapePath {
+ strokeColor: "gray"
+ strokeWidth: 2
+ fillColor: "transparent"
+ PathMove { x: 0; y: 50 }
+ PathLine { relativeX: 200; relativeY: 0 }
+ PathMove { x: 0; y: 150 }
+ PathLine { relativeX: 200; relativeY: 0 }
+ }
+ }
+ }
+
+ Text {
+ anchors.right: parent.right
+ text: spreadTimer.spreadTexts[spreadTimer.spreadIdx]
+ }
+}
diff --git a/examples/quick/shapes/content/item13.qml b/examples/quick/shapes/content/item13.qml
new file mode 100644
index 0000000000..93160af7d8
--- /dev/null
+++ b/examples/quick/shapes/content/item13.qml
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ color: "lightGray"
+
+ Rectangle {
+ width: 100
+ height: 100
+ anchors.centerIn: parent
+ border.color: "gray"
+
+ Repeater {
+ model: 2
+ Shape {
+ anchors.fill: parent
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: model.index === 0 ? "red" : "blue"
+ strokeStyle: ShapePath.DashLine
+ strokeWidth: 4
+
+ startX: 4; startY: 4
+ PathArc {
+ id: arc
+ x: 96; y: 96
+ radiusX: 100; radiusY: 100
+ direction: model.index === 0 ? PathArc.Clockwise : PathArc.Counterclockwise
+ }
+ }
+ }
+ }
+ }
+
+ Column {
+ anchors.right: parent.right
+ Text {
+ text: "Clockwise (sweep 1)"
+ color: "red"
+ }
+ Text {
+ text: "Counter clockwise (sweep 0)"
+ color: "blue"
+ }
+ }
+}
diff --git a/examples/quick/shapes/content/item14.qml b/examples/quick/shapes/content/item14.qml
new file mode 100644
index 0000000000..fd5b7d1048
--- /dev/null
+++ b/examples/quick/shapes/content/item14.qml
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ color: "lightGray"
+
+ Repeater {
+ model: 2
+ Shape {
+ width: 200
+ height: 200
+ anchors.centerIn: parent
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: model.index === 0 ? "red" : "blue"
+ strokeStyle: ShapePath.DashLine
+ strokeWidth: 4
+
+ startX: 50; startY: 100
+ PathArc {
+ x: 100; y: 150
+ radiusX: 50; radiusY: 50
+ useLargeArc: model.index === 1
+ }
+ }
+ }
+ }
+
+ Column {
+ anchors.right: parent.right
+ Text {
+ text: "Small"
+ color: "red"
+ }
+ Text {
+ text: "Large"
+ color: "blue"
+ }
+ }
+}
diff --git a/examples/quick/shapes/content/item15.qml b/examples/quick/shapes/content/item15.qml
new file mode 100644
index 0000000000..eb23b8b3c5
--- /dev/null
+++ b/examples/quick/shapes/content/item15.qml
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ color: "lightGray"
+
+ Repeater {
+ model: 2
+ Shape {
+ width: 200
+ height: 200
+ anchors.centerIn: parent
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: model.index === 0 ? "red" : "blue"
+ strokeStyle: ShapePath.DashLine
+ strokeWidth: 4
+
+ startX: 50; startY: 100
+ PathArc {
+ x: 150; y: 100
+ radiusX: 50; radiusY: 20
+ xAxisRotation: model.index === 0 ? 0 : 45
+ }
+ }
+ }
+ }
+
+ Repeater {
+ model: 2
+ Shape {
+ width: 200
+ height: 200
+ anchors.centerIn: parent
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: model.index === 0 ? "red" : "blue"
+
+ startX: 50; startY: 100
+ PathArc {
+ x: 150; y: 100
+ radiusX: 50; radiusY: 20
+ xAxisRotation: model.index === 0 ? 0 : 45
+ direction: PathArc.Counterclockwise
+ }
+ }
+ }
+ }
+
+ Column {
+ anchors.right: parent.right
+ Text {
+ text: "0 degrees"
+ color: "red"
+ }
+ Text {
+ text: "45 degrees"
+ color: "blue"
+ }
+ }
+}
diff --git a/examples/quick/shapes/content/item17.qml b/examples/quick/shapes/content/item17.qml
new file mode 100644
index 0000000000..6ee03ddd04
--- /dev/null
+++ b/examples/quick/shapes/content/item17.qml
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ color: "lightGray"
+
+ Item {
+ anchors.fill: parent
+
+ Text {
+ anchors.centerIn: parent
+ text: "Loading"
+ // Phase #1: Loader loads tiger.qml. After this we have our item.
+ // Phase #2: With some backends (generic) the item will start async processing. Wait for this too.
+ visible: shapeLoader.status != Loader.Ready || shapeLoader.item.status === Shape.Processing
+ }
+
+ Loader {
+ id: shapeLoader
+ anchors.fill: parent
+ source: "tiger.qml"
+ asynchronous: true
+ visible: status == Loader.Ready
+ scale: 0.4
+ }
+ }
+}
diff --git a/examples/quick/shapes/content/item2.qml b/examples/quick/shapes/content/item2.qml
new file mode 100644
index 0000000000..a033ba88c7
--- /dev/null
+++ b/examples/quick/shapes/content/item2.qml
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ color: "lightGray"
+
+ Shape {
+ id: circ1
+ anchors.fill: parent
+
+ ShapePath {
+ id: p1
+ fillColor: "transparent" // stroke only
+ strokeWidth: 4
+
+ SequentialAnimation on strokeColor {
+ loops: Animation.Infinite
+ ColorAnimation {
+ from: "black"
+ to: "yellow"
+ duration: 5000
+ }
+ ColorAnimation {
+ from: "yellow"
+ to: "green"
+ duration: 5000
+ }
+ ColorAnimation {
+ from: "green"
+ to: "black"
+ duration: 5000
+ }
+ }
+
+ property real r: 60
+ startX: circ1.width / 2 - r
+ startY: circ1.height / 2 - r
+ PathArc {
+ x: circ1.width / 2 + p1.r
+ y: circ1.height / 2 + p1.r
+ radiusX: p1.r; radiusY: p1.r
+ useLargeArc: true
+ }
+ PathArc {
+ x: circ1.width / 2 - p1.r
+ y: circ1.height / 2 - p1.r
+ radiusX: p1.r; radiusY: p1.r
+ useLargeArc: true
+ }
+ }
+ }
+
+ Shape {
+ id: circ2
+ anchors.fill: parent
+
+ SequentialAnimation on opacity {
+ loops: Animation.Infinite
+ NumberAnimation { from: 1.0; to: 0.0; duration: 5000 }
+ NumberAnimation { from: 0.0; to: 1.0; duration: 5000 }
+ }
+
+ ShapePath {
+ id: p2
+ strokeWidth: -1 // or strokeColor: "transparent"
+
+ SequentialAnimation on fillColor {
+ loops: Animation.Infinite
+ ColorAnimation {
+ from: "gray"
+ to: "purple"
+ duration: 3000
+ }
+ ColorAnimation {
+ from: "purple"
+ to: "red"
+ duration: 3000
+ }
+ ColorAnimation {
+ from: "red"
+ to: "gray"
+ duration: 3000
+ }
+ }
+
+ property real r: 40
+ startX: circ2.width / 2 - r
+ startY: circ2.height / 2 - r
+ PathArc {
+ x: circ2.width / 2 + p2.r
+ y: circ2.height / 2 + p2.r
+ radiusX: p2.r; radiusY: p2.r
+ useLargeArc: true
+ }
+ PathArc {
+ x: circ2.width / 2 - p2.r
+ y: circ2.height / 2 - p2.r
+ radiusX: p2.r; radiusY: p2.r
+ useLargeArc: true
+ }
+ }
+ }
+}
diff --git a/examples/quick/shapes/content/item4.qml b/examples/quick/shapes/content/item4.qml
new file mode 100644
index 0000000000..2b20c0a263
--- /dev/null
+++ b/examples/quick/shapes/content/item4.qml
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ color: "lightGray"
+ Shape {
+ id: shape
+ anchors.fill: parent
+
+ ShapePath {
+ id: p
+ strokeWidth: 5
+ strokeColor: "blue"
+ strokeStyle: ShapePath.DashLine
+ dashPattern: [ 1, 4, 4, 4 ]
+ fillColor: "lightBlue"
+
+ property real xr: 70
+ property real yr: 30
+ startX: shape.width / 2 - xr
+ startY: shape.height / 2 - yr
+ PathArc {
+ x: shape.width / 2 + p.xr
+ y: shape.height / 2 + p.yr
+ radiusX: p.xr; radiusY: p.yr
+ useLargeArc: true
+ }
+ PathArc {
+ x: shape.width / 2 - p.xr
+ y: shape.height / 2 - p.yr
+ radiusX: p.xr; radiusY: p.yr
+ useLargeArc: true
+ }
+ }
+ }
+}
diff --git a/examples/quick/shapes/content/item5.qml b/examples/quick/shapes/content/item5.qml
new file mode 100644
index 0000000000..5fd25093ae
--- /dev/null
+++ b/examples/quick/shapes/content/item5.qml
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ color: "lightGray"
+ Shape {
+ width: 200
+ height: 150
+ anchors.centerIn: parent
+ ShapePath {
+ strokeWidth: 4
+ strokeColor: "red"
+ fillGradient: LinearGradient {
+ x1: 20; y1: 20
+ x2: 180; y2: 130
+ GradientStop { position: 0; color: "blue" }
+ GradientStop { position: 0.2; color: "green" }
+ GradientStop { position: 0.4; color: "red" }
+ GradientStop { position: 0.6; color: "yellow" }
+ GradientStop { position: 1; color: "cyan" }
+ }
+ fillColor: "blue" // ignored with the gradient set
+ strokeStyle: ShapePath.DashLine
+ dashPattern: [ 1, 4 ]
+ startX: 20; startY: 20
+ PathLine { x: 180; y: 130 }
+ PathLine { x: 20; y: 130 }
+ PathLine { x: 20; y: 20 }
+ }
+ transform: Rotation { origin.x: 100; origin.y: 50; axis { x: 0; y: 1; z: 0 }
+ SequentialAnimation on angle {
+ NumberAnimation { from: 0; to: 75; duration: 2000 }
+ NumberAnimation { from: 75; to: -75; duration: 4000 }
+ NumberAnimation { from: -75; to: 0; duration: 2000 }
+ loops: Animation.Infinite
+ }
+ }
+ }
+}
diff --git a/examples/quick/shapes/content/item6.qml b/examples/quick/shapes/content/item6.qml
new file mode 100644
index 0000000000..f0791c30d2
--- /dev/null
+++ b/examples/quick/shapes/content/item6.qml
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ color: "lightGray"
+ Shape {
+ width: 100
+ height: 100
+ anchors.centerIn: parent
+ ShapePath {
+ id: star
+ strokeColor: "blue"
+ fillColor: "magenta"
+ strokeWidth: 2
+ PathMove { x: 90; y: 50 }
+ PathLine { x: 50 + 40 * Math.cos(0.8 * 1 * Math.PI); y: 50 + 40 * Math.sin(0.8 * 1 * Math.PI) }
+ PathLine { x: 50 + 40 * Math.cos(0.8 * 2 * Math.PI); y: 50 + 40 * Math.sin(0.8 * 2 * Math.PI) }
+ PathLine { x: 50 + 40 * Math.cos(0.8 * 3 * Math.PI); y: 50 + 40 * Math.sin(0.8 * 3 * Math.PI) }
+ PathLine { x: 50 + 40 * Math.cos(0.8 * 4 * Math.PI); y: 50 + 40 * Math.sin(0.8 * 4 * Math.PI) }
+ PathLine { x: 90; y: 50 }
+ }
+ NumberAnimation on rotation {
+ from: 0
+ to: 360
+ duration: 5000
+ loops: Animation.Infinite
+ }
+ }
+ Timer {
+ interval: 2000
+ onTriggered: star.fillRule = (star.fillRule === ShapePath.OddEvenFill ? ShapePath.WindingFill : ShapePath.OddEvenFill)
+ repeat: true
+ running: true
+ }
+ Text {
+ anchors.right: parent.right
+ text: star.fillRule === ShapePath.OddEvenFill ? "OddEvenFill" : "WindingFill"
+ }
+}
diff --git a/examples/quick/shapes/content/item7.qml b/examples/quick/shapes/content/item7.qml
new file mode 100644
index 0000000000..ff5c5702da
--- /dev/null
+++ b/examples/quick/shapes/content/item7.qml
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ color: "lightGray"
+
+ Shape {
+ width: 120
+ height: 120
+ anchors.centerIn: parent
+
+ ShapePath {
+ id: joinTest
+
+ strokeColor: "black"
+ strokeWidth: 16
+ fillColor: "transparent"
+ capStyle: ShapePath.RoundCap
+
+ property int joinStyleIdx: 0
+ property variant styles: [ ShapePath.BevelJoin, ShapePath.MiterJoin, ShapePath.RoundJoin ]
+ property variant styleTexts: [ "BevelJoin", "MiterJoin", "RoundJoin" ]
+
+ joinStyle: styles[joinStyleIdx]
+
+ startX: 30
+ startY: 30
+ PathLine { x: 100; y: 100 }
+ PathLine { x: 30; y: 100 }
+ }
+ }
+
+ Timer {
+ interval: 1000
+ repeat: true
+ running: true
+ onTriggered: joinTest.joinStyleIdx = (joinTest.joinStyleIdx + 1) % joinTest.styles.length
+ }
+
+ Text {
+ id: txt
+ anchors.right: parent.right
+ text: joinTest.styleTexts[joinTest.joinStyleIdx]
+ }
+}
diff --git a/examples/quick/shapes/content/item8.qml b/examples/quick/shapes/content/item8.qml
new file mode 100644
index 0000000000..07f633fa56
--- /dev/null
+++ b/examples/quick/shapes/content/item8.qml
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ color: "lightGray"
+
+ Shape {
+ anchors.centerIn: parent
+ width: 200
+ height: 100
+
+ ShapePath {
+ id: capTest
+ strokeColor: "green"
+ strokeWidth: 20
+ fillColor: "transparent"
+
+ property int capStyleIdx: 0
+ property variant styles: [ ShapePath.FlatCap, ShapePath.SquareCap, ShapePath.RoundCap ]
+ property variant styleTexts: [ "FlatCap", "SquareCap", "RoundCap" ]
+
+ capStyle: styles[capStyleIdx]
+
+ startX: 40; startY: 30
+ PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 }
+ PathLine { x: 150; y: 80 }
+ PathQuad { x: 160; y: 30; controlX: 200; controlY: 80 }
+ }
+ }
+
+ Timer {
+ interval: 1000
+ repeat: true
+ running: true
+ onTriggered: capTest.capStyleIdx = (capTest.capStyleIdx + 1) % capTest.styles.length
+ }
+
+ Text {
+ id: txt
+ anchors.right: parent.right
+ text: capTest.styleTexts[capTest.capStyleIdx]
+ }
+}
diff --git a/examples/quick/shapes/content/item9.qml b/examples/quick/shapes/content/item9.qml
new file mode 100644
index 0000000000..4e5b4022b6
--- /dev/null
+++ b/examples/quick/shapes/content/item9.qml
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ color: "lightGray"
+
+ Item {
+ width: 200
+ height: 100
+ anchors.centerIn: parent
+
+ Shape {
+ id: shape
+ anchors.fill: parent
+
+ ShapePath {
+ strokeWidth: 4
+ strokeColor: "black"
+ fillColor: "transparent"
+
+ startX: 50
+ startY: 50
+ PathQuad {
+ x: 150; y: 50
+ controlX: cp.x; controlY: cp.y
+ }
+ }
+ }
+
+ Rectangle {
+ id: cp
+ color: "red"
+ width: 10
+ height: 10
+ SequentialAnimation on x {
+ loops: Animation.Infinite
+ NumberAnimation {
+ from: 0
+ to: shape.width - cp.width
+ duration: 5000
+ }
+ NumberAnimation {
+ from: shape.width - cp.width
+ to: 0
+ duration: 5000
+ }
+ }
+ }
+ }
+}
diff --git a/examples/quick/shapes/content/pathitem.qml b/examples/quick/shapes/content/pathitem.qml
new file mode 100644
index 0000000000..0933aa79b2
--- /dev/null
+++ b/examples/quick/shapes/content/pathitem.qml
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Item {
+ width: 1024
+ height: 768
+ LauncherList {
+ anchors.fill: parent
+ Component.onCompleted: {
+ addExample("Shape Gallery", "Simple path rendering examples", Qt.resolvedUrl("pathitemgallery.qml"))
+ addExample("Interactive Shape", "Dynamic, interactive path rendering examples", Qt.resolvedUrl("pathiteminteract.qml"))
+ addExample("Super- and multisampling", "Improving quality", Qt.resolvedUrl("pathitemsampling.qml"))
+ addExample("Clip My Tiger!", "Clip examples, a.k.a. What Not To Do", Qt.resolvedUrl("pathitemtigers.qml"))
+ }
+ }
+}
diff --git a/examples/quick/shapes/content/pathitemgallery.qml b/examples/quick/shapes/content/pathitemgallery.qml
new file mode 100644
index 0000000000..e871de4c52
--- /dev/null
+++ b/examples/quick/shapes/content/pathitemgallery.qml
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ id: root
+ width: 1024
+ height: 768
+
+ property color col: "lightsteelblue"
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: Qt.tint(root.col, "#20FFFFFF") }
+ GradientStop { position: 0.1; color: Qt.tint(root.col, "#20AAAAAA") }
+ GradientStop { position: 0.9; color: Qt.tint(root.col, "#20666666") }
+ GradientStop { position: 1.0; color: Qt.tint(root.col, "#20000000") }
+ }
+
+ ListModel {
+ id: pathGalleryModel
+ ListElement {
+ name: "Stroke and fill"
+ shapeUrl: "item1.qml"
+ }
+ ListElement {
+ name: "Stroke or fill only"
+ shapeUrl: "item2.qml"
+ }
+ ListElement {
+ name: "Dash pattern"
+ shapeUrl: "item4.qml"
+ }
+ ListElement {
+ name: "Linear gradient"
+ shapeUrl: "item5.qml"
+ }
+ ListElement {
+ name: "Fill rules"
+ shapeUrl: "item6.qml"
+ }
+ ListElement {
+ name: "Join styles"
+ shapeUrl: "item7.qml"
+ }
+ ListElement {
+ name: "Cap styles"
+ shapeUrl: "item8.qml"
+ }
+ ListElement {
+ name: "Quadratic curve"
+ shapeUrl: "item9.qml"
+ }
+ ListElement {
+ name: "Cubic curve"
+ shapeUrl: "item10.qml"
+ }
+ ListElement {
+ name: "Elliptical arc"
+ shapeUrl: "item11.qml"
+ }
+ ListElement {
+ name: "Gradient spread modes"
+ shapeUrl: "item12.qml"
+ }
+ ListElement {
+ name: "Arc direction"
+ shapeUrl: "item13.qml"
+ }
+ ListElement {
+ name: "Large/small arc"
+ shapeUrl: "item14.qml"
+ }
+ ListElement {
+ name: "Arc rotation"
+ shapeUrl: "item15.qml"
+ }
+ ListElement {
+ name: "Tiger"
+ shapeUrl: "item17.qml"
+ }
+ }
+
+ property int gridSpacing: 10
+
+ Component {
+ id: pathGalleryDelegate
+ Rectangle {
+ border.color: "purple"
+ width: grid.cellWidth - root.gridSpacing
+ height: grid.cellHeight - root.gridSpacing
+ Column {
+ anchors.fill: parent
+ anchors.margins: 4
+ Item {
+ width: parent.width
+ height: parent.height - delegText.height
+ Loader {
+ source: Qt.resolvedUrl(shapeUrl)
+ anchors.fill: parent
+ }
+ }
+ Text {
+ id: delegText
+ text: model.name
+ font.pointSize: 16
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ anchors.fill: parent
+ anchors.margins: 10
+ color: "lightBlue"
+ clip: true
+
+ GridView {
+ id: grid
+ anchors.fill: parent
+ anchors.margins: root.gridSpacing
+ cellWidth: 300
+ cellHeight: 300
+ delegate: pathGalleryDelegate
+ model: pathGalleryModel
+ }
+ }
+
+ Text {
+ anchors.right: parent.right
+ Shape { id: dummyShape; ShapePath { } } // used only to get the renderer type
+ color: "darkBlue"
+ font.pointSize: 12
+ property variant rendererStrings: [ "Unknown", "Generic (QtGui triangulator)", "GL_NV_path_rendering", "Software (QPainter)" ]
+ text: "Active Shape backend: " + rendererStrings[dummyShape.rendererType]
+ SequentialAnimation on opacity {
+ NumberAnimation { from: 1; to: 0; duration: 5000 }
+ PauseAnimation { duration: 5000 }
+ NumberAnimation { from: 0; to: 1; duration: 1000 }
+ PauseAnimation { duration: 5000 }
+ loops: Animation.Infinite
+ }
+ }
+}
diff --git a/examples/quick/shapes/content/pathiteminteract.qml b/examples/quick/shapes/content/pathiteminteract.qml
new file mode 100644
index 0000000000..55a1d16299
--- /dev/null
+++ b/examples/quick/shapes/content/pathiteminteract.qml
@@ -0,0 +1,285 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ id: root
+ width: 1024
+ height: 768
+
+ property color col: "lightsteelblue"
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: Qt.tint(root.col, "#20FFFFFF") }
+ GradientStop { position: 0.1; color: Qt.tint(root.col, "#20AAAAAA") }
+ GradientStop { position: 0.9; color: Qt.tint(root.col, "#20666666") }
+ GradientStop { position: 1.0; color: Qt.tint(root.col, "#20000000") }
+ }
+
+ property int mode: 0
+ property bool showResizers: true
+ property bool fill: false
+
+ Row {
+ x: 20
+ y: 10
+ spacing: 20
+ Rectangle {
+ border.color: "black"
+ color: root.mode === 0 ? "red" : "transparent"
+ width: 100
+ height: 40
+ Text {
+ anchors.centerIn: parent
+ text: "Line"
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: root.mode = 0
+ }
+ }
+ Rectangle {
+ border.color: "black"
+ color: root.mode === 1 ? "red" : "transparent"
+ width: 100
+ height: 40
+ Text {
+ anchors.centerIn: parent
+ text: "Cubic"
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: root.mode = 1
+ }
+ }
+ Rectangle {
+ border.color: "black"
+ color: root.mode === 2 ? "red" : "transparent"
+ width: 100
+ height: 40
+ Text {
+ anchors.centerIn: parent
+ text: "Quadratic"
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: root.mode = 2
+ }
+ }
+
+ Slider {
+ id: widthSlider
+ name: "Width"
+ min: 1
+ max: 60
+ init: 4
+ }
+
+ Rectangle {
+ border.color: "black"
+ color: root.showResizers ? "yellow" : "transparent"
+ width: 50
+ height: 40
+ Text {
+ anchors.centerIn: parent
+ text: "Manip"
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ root.showResizers = !root.showResizers;
+ for (var i = 0; i < canvas.resizers.length; ++i)
+ canvas.resizers[i].visible = root.showResizers;
+ }
+ }
+ }
+
+ Rectangle {
+ border.color: "black"
+ color: root.fill ? "yellow" : "transparent"
+ width: 50
+ height: 40
+ Text {
+ anchors.centerIn: parent
+ text: "Fill"
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: root.fill = !root.fill
+ }
+ }
+ }
+
+ Rectangle {
+ id: canvas
+ width: root.width - 40
+ height: root.height - 120
+ x: 20
+ y: 100
+
+ property variant activePath: null
+
+ property variant resizers: []
+ property variant funcs
+
+ function genResizer(obj, x, y, xprop, yprop, color) {
+ var ma = Qt.createQmlObject('import QtQuick 2.9; import QtQuick.Shapes 1.0; Rectangle { id: rr; property variant obj; color: "' + color + '"; width: 20; height: 20;'+
+ 'MouseArea { anchors.fill: parent; hoverEnabled: true;' +
+ 'onEntered: color = "yellow"; onExited: color = "' + color + '";' +
+ 'property bool a: false; onPressed: a = true; onReleased: a = false; ' +
+ 'onPositionChanged: if (a) { var pt = mapToItem(rr.parent, mouse.x, mouse.y);' +
+ 'obj.' + xprop + ' = pt.x; obj.' + yprop + ' = pt.y; rr.x = pt.x - 10; rr.y = pt.y - 10; } } }',
+ canvas, "resizer_item");
+ ma.visible = root.showResizers;
+ ma.obj = obj;
+ ma.x = x - 10;
+ ma.y = y - 10;
+ resizers.push(ma);
+ return ma;
+ }
+
+ Component.onCompleted: {
+ funcs = [
+ { "start": function(x, y) {
+ var p = Qt.createQmlObject('import QtQuick 2.9; import QtQuick.Shapes 1.0; ShapePath {' +
+ 'strokeColor: "black"; fillColor: "transparent";'+
+ 'strokeWidth: ' + widthSlider.value + ';' +
+ 'startX: ' + x + '; startY: ' + y + ';' +
+ 'PathLine { x: ' + x + ' + 1; y: ' + y + ' + 1 } }',
+ root, "dynamic_visual_path");
+ shape.data.push(p);
+ activePath = p;
+ }, "move": function(x, y) {
+ if (!activePath)
+ return;
+ var pathObj = activePath.pathElements[0];
+ pathObj.x = x;
+ pathObj.y = y;
+ }, "end": function() {
+ canvas.genResizer(activePath, activePath.startX, activePath.startY, "startX", "startY", "red");
+ var pathObj = activePath.pathElements[0];
+ canvas.genResizer(pathObj, pathObj.x, pathObj.y, "x", "y", "red");
+ activePath = null;
+ }
+ },
+ { "start": function(x, y) {
+ var p = Qt.createQmlObject('import QtQuick 2.9; import QtQuick.Shapes 1.0; ShapePath {' +
+ 'strokeColor: "black"; fillColor: "' + (root.fill ? 'green' : 'transparent') + '";'+
+ 'strokeWidth: ' + widthSlider.value + ';' +
+ 'startX: ' + x + '; startY: ' + y + ';' +
+ 'PathCubic { x: ' + x + ' + 1; y: ' + y + ' + 1;' +
+ 'control1X: ' + x + ' + 50; control1Y: ' + y + ' + 50; control2X: ' + x + ' + 150; control2Y: ' + y + ' + 50; } }',
+ root, "dynamic_visual_path");
+ shape.data.push(p);
+ activePath = p;
+ }, "move": function(x, y) {
+ if (!activePath)
+ return;
+ var pathObj = activePath.pathElements[0];
+ pathObj.x = x;
+ pathObj.y = y;
+ }, "end": function() {
+ canvas.genResizer(activePath, activePath.startX, activePath.startY, "startX", "startY", "red");
+ var pathObj = activePath.pathElements[0];
+ canvas.genResizer(pathObj, pathObj.x, pathObj.y, "x", "y", "red");
+ canvas.genResizer(pathObj, pathObj.control1X, pathObj.control1Y, "control1X", "control1Y", "blue");
+ canvas.genResizer(pathObj, pathObj.control2X, pathObj.control2Y, "control2X", "control2Y", "lightBlue");
+ activePath = null;
+ }
+ },
+ { "start": function(x, y) {
+ var p = Qt.createQmlObject('import QtQuick 2.9; import QtQuick.Shapes 1.0; ShapePath {' +
+ 'strokeColor: "black"; fillColor: "' + (root.fill ? 'green' : 'transparent') + '";'+
+ 'strokeWidth: ' + widthSlider.value + ';' +
+ 'startX: ' + x + '; startY: ' + y + ';' +
+ 'PathQuad { x: ' + x + ' + 1; y: ' + y + ' + 1;' +
+ 'controlX: ' + x + ' + 50; controlY: ' + y + ' + 50 } }',
+ root, "dynamic_visual_path");
+ shape.data.push(p);
+ activePath = p;
+ }, "move": function(x, y) {
+ if (!activePath)
+ return;
+ var pathObj = activePath.pathElements[0];
+ pathObj.x = x;
+ pathObj.y = y;
+ }, "end": function() {
+ canvas.genResizer(activePath, activePath.startX, activePath.startY, "startX", "startY", "red");
+ var pathObj = activePath.pathElements[0];
+ canvas.genResizer(pathObj, pathObj.x, pathObj.y, "x", "y", "red");
+ canvas.genResizer(pathObj, pathObj.controlX, pathObj.controlY, "controlX", "controlY", "blue");
+ activePath = null;
+ }
+ }
+ ];
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onPressed: {
+ canvas.funcs[root.mode].start(mouse.x, mouse.y);
+ }
+ onPositionChanged: {
+ canvas.funcs[root.mode].move(mouse.x, mouse.y);
+ }
+ onReleased: {
+ canvas.funcs[root.mode].end();
+ }
+ }
+
+ Shape {
+ id: shape
+ anchors.fill: parent
+
+ data: []
+ }
+ }
+}
diff --git a/examples/quick/shapes/content/pathitemsampling.qml b/examples/quick/shapes/content/pathitemsampling.qml
new file mode 100644
index 0000000000..6b651f8a1d
--- /dev/null
+++ b/examples/quick/shapes/content/pathitemsampling.qml
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ id: root
+ width: 1024
+ height: 768
+
+ property color col: "lightsteelblue"
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: Qt.tint(root.col, "#20FFFFFF") }
+ GradientStop { position: 0.1; color: Qt.tint(root.col, "#20AAAAAA") }
+ GradientStop { position: 0.9; color: Qt.tint(root.col, "#20666666") }
+ GradientStop { position: 1.0; color: Qt.tint(root.col, "#20000000") }
+ }
+
+ Row {
+ anchors.fill: parent
+ anchors.margins: 20
+ spacing: 40
+
+ Column {
+ spacing: 40
+
+ Text {
+ text: "Original"
+ }
+
+ // A simple Shape without anything special.
+ Rectangle {
+ color: "lightGray"
+ width: 400
+ height: 200
+
+ Shape {
+ x: 30
+ y: 20
+ width: 50
+ height: 50
+ scale: 2
+
+ ShapePath {
+ strokeColor: "green"
+ NumberAnimation on strokeWidth { from: 1; to: 20; duration: 5000 }
+ fillColor: "transparent"
+ capStyle: ShapePath.RoundCap
+
+ startX: 40; startY: 30
+ PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 }
+ PathLine { x: 150; y: 80 }
+ PathQuad { x: 160; y: 30; controlX: 200; controlY: 80 }
+ }
+ }
+ }
+
+ Text {
+ text: "Supersampling (2x)"
+ }
+
+ // Now let's use 2x supersampling via layers. This way the entire subtree
+ // is rendered into an FBO twice the size and then drawn with linear
+ // filtering. This allows having some level of AA even when there is no
+ // support for multisample framebuffers.
+ Rectangle {
+ id: supersampledItem
+ color: "lightGray"
+ width: 400
+ height: 200
+
+ layer.enabled: true
+ layer.smooth: true
+ layer.textureSize: Qt.size(supersampledItem.width * 2, supersampledItem.height * 2)
+
+ Shape {
+ x: 30
+ y: 20
+ width: 50
+ height: 50
+ scale: 2
+
+ ShapePath {
+ strokeColor: "green"
+ NumberAnimation on strokeWidth { from: 1; to: 20; duration: 5000 }
+ fillColor: "transparent"
+ capStyle: ShapePath.RoundCap
+
+ startX: 40; startY: 30
+ PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 }
+ PathLine { x: 150; y: 80 }
+ PathQuad { x: 160; y: 30; controlX: 200; controlY: 80 }
+ }
+ }
+ }
+ }
+
+ Column {
+ spacing: 40
+
+ Text {
+ text: "Multisampling (4x)"
+ }
+
+ // Now let's use 4x MSAA, again via layers. This needs support for
+ // multisample renderbuffers and framebuffer blits.
+ Rectangle {
+ color: "lightGray"
+ width: 400
+ height: 200
+
+ layer.enabled: true
+ layer.smooth: true
+ layer.samples: 4
+
+ Shape {
+ x: 30
+ y: 20
+ width: 50
+ height: 50
+ scale: 2
+
+ ShapePath {
+ strokeColor: "green"
+ NumberAnimation on strokeWidth { from: 1; to: 20; duration: 5000 }
+ fillColor: "transparent"
+ capStyle: ShapePath.RoundCap
+
+ startX: 40; startY: 30
+ PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 }
+ PathLine { x: 150; y: 80 }
+ PathQuad { x: 160; y: 30; controlX: 200; controlY: 80 }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/examples/quick/shapes/content/pathitemtigers.qml b/examples/quick/shapes/content/pathitemtigers.qml
new file mode 100644
index 0000000000..c55efdc403
--- /dev/null
+++ b/examples/quick/shapes/content/pathitemtigers.qml
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ id: root
+ width: 1024
+ height: 768
+
+ property color col: "lightsteelblue"
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: Qt.tint(root.col, "#20FFFFFF") }
+ GradientStop { position: 0.1; color: Qt.tint(root.col, "#20AAAAAA") }
+ GradientStop { position: 0.9; color: Qt.tint(root.col, "#20666666") }
+ GradientStop { position: 1.0; color: Qt.tint(root.col, "#20000000") }
+ }
+
+ Rectangle {
+ id: scissorRect
+ width: 200
+ height: 200
+ x: 150
+ property real centerY: parent.height / 2 - height / 2
+ property real dy: 0
+ y: centerY + dy
+ clip: true
+
+ Loader {
+ id: loader1
+ width: parent.width
+ height: parent.height
+ y: 25 - scissorRect.dy
+ source: "tiger.qml"
+ asynchronous: true
+ visible: status === Loader.Ready
+ }
+
+ SequentialAnimation on dy {
+ loops: Animation.Infinite
+ running: loader1.status === Loader.Ready && loader1.item.status === Shape.Ready
+ NumberAnimation {
+ from: 0
+ to: -scissorRect.centerY
+ duration: 2000
+ }
+ NumberAnimation {
+ from: -scissorRect.centerY
+ to: scissorRect.centerY
+ duration: 4000
+ }
+ NumberAnimation {
+ from: scissorRect.centerY
+ to: 0
+ duration: 2000
+ }
+ }
+ }
+
+ // With a more complex transformation (like rotation), stenciling is used
+ // instead of scissoring, this is more expensive. It may also trigger a
+ // slower code path for Shapes, depending on the path rendering backend
+ // in use, and may affect rendering quality as well.
+ Rectangle {
+ id: stencilRect
+ width: 300
+ height: 200
+ anchors.right: parent.right
+ anchors.rightMargin: 100
+ anchors.verticalCenter: parent.verticalCenter
+ clip: true // NB! still clips to bounding rect (not shape)
+
+ Loader {
+ id: loader2
+ width: parent.width
+ height: parent.height
+ source: "tiger.qml"
+ asynchronous: true
+ visible: status === Loader.Ready
+ }
+
+ NumberAnimation on rotation {
+ from: 0
+ to: 360
+ duration: 5000
+ loops: Animation.Infinite
+ }
+ }
+}
diff --git a/examples/quick/shapes/content/tiger.qml b/examples/quick/shapes/content/tiger.qml
new file mode 100644
index 0000000000..50cb103d50
--- /dev/null
+++ b/examples/quick/shapes/content/tiger.qml
@@ -0,0 +1,3619 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Shape {
+ asynchronous: true
+
+ anchors.fill: parent
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.172
+ PathMove { x: -122.304; y: 84.285 }
+ PathCubic { control1X: -122.304; control1Y: 84.285; control2X: -122.203; control2Y: 86.179; x: -123.027; y: 86.16 }
+ PathCubic { control1X: -123.851; control1Y: 86.141; control2X: -140.305; control2Y: 38.066; x: -160.833; y: 40.309 }
+ PathCubic { control1X: -160.833; control1Y: 40.309; control2X: -143.05; control2Y: 32.956; x: -122.304; y: 84.285 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.172
+ PathMove { x: -118.774; y: 81.262 }
+ PathCubic { control1X: -118.774; control1Y: 81.262; control2X: -119.323; control2Y: 83.078; x: -120.092; y: 82.779 }
+ PathCubic { control1X: -120.86; control1Y: 82.481; control2X: -119.977; control2Y: 31.675; x: -140.043; y: 26.801 }
+ PathCubic { control1X: -140.043; control1Y: 26.801; control2X: -120.82; control2Y: 25.937; x: -118.774; y: 81.262 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.172
+ PathMove { x: -91.284; y: 123.59 }
+ PathCubic { control1X: -91.284; control1Y: 123.59; control2X: -89.648; control2Y: 124.55; x: -90.118; y: 125.227 }
+ PathCubic { control1X: -90.589; control1Y: 125.904; control2X: -139.763; control2Y: 113.102; x: -149.218; y: 131.459 }
+ PathCubic { control1X: -149.218; control1Y: 131.459; control2X: -145.539; control2Y: 112.572; x: -91.284; y: 123.59 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.172
+ PathMove { x: -94.093; y: 133.801 }
+ PathCubic { control1X: -94.093; control1Y: 133.801; control2X: -92.237; control2Y: 134.197; x: -92.471; y: 134.988 }
+ PathCubic { control1X: -92.704; control1Y: 135.779; control2X: -143.407; control2Y: 139.121; x: -146.597; y: 159.522 }
+ PathCubic { control1X: -146.597; control1Y: 159.522; control2X: -149.055; control2Y: 140.437; x: -94.093; y: 133.801 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.172
+ PathMove { x: -98.304; y: 128.276 }
+ PathCubic { control1X: -98.304; control1Y: 128.276; control2X: -96.526; control2Y: 128.939; x: -96.872; y: 129.687 }
+ PathCubic { control1X: -97.218; control1Y: 130.435; control2X: -147.866; control2Y: 126.346; x: -153.998; y: 146.064 }
+ PathCubic { control1X: -153.998; control1Y: 146.064; control2X: -153.646; control2Y: 126.825; x: -98.304; y: 128.276 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.172
+ PathMove { x: -109.009; y: 110.072 }
+ PathCubic { control1X: -109.009; control1Y: 110.072; control2X: -107.701; control2Y: 111.446; x: -108.34; y: 111.967 }
+ PathCubic { control1X: -108.979; control1Y: 112.488; control2X: -152.722; control2Y: 86.634; x: -166.869; y: 101.676 }
+ PathCubic { control1X: -166.869; control1Y: 101.676; control2X: -158.128; control2Y: 84.533; x: -109.009; y: 110.072 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.172
+ PathMove { x: -116.554; y: 114.263 }
+ PathCubic { control1X: -116.554; control1Y: 114.263; control2X: -115.098; control2Y: 115.48; x: -115.674; y: 116.071 }
+ PathCubic { control1X: -116.25; control1Y: 116.661; control2X: -162.638; control2Y: 95.922; x: -174.992; y: 112.469 }
+ PathCubic { control1X: -174.992; control1Y: 112.469; control2X: -168.247; control2Y: 94.447; x: -116.554; y: 114.263 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.172
+ PathMove { x: -119.154; y: 118.335 }
+ PathCubic { control1X: -119.154; control1Y: 118.335; control2X: -117.546; control2Y: 119.343; x: -118.036; y: 120.006 }
+ PathCubic { control1X: -118.526; control1Y: 120.669; control2X: -167.308; control2Y: 106.446; x: -177.291; y: 124.522 }
+ PathCubic { control1X: -177.291; control1Y: 124.522; control2X: -173.066; control2Y: 105.749; x: -119.154; y: 118.335 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.172
+ PathMove { x: -108.42; y: 118.949 }
+ PathCubic { control1X: -108.42; control1Y: 118.949; control2X: -107.298; control2Y: 120.48; x: -107.999; y: 120.915 }
+ PathCubic { control1X: -108.7; control1Y: 121.35; control2X: -148.769; control2Y: 90.102; x: -164.727; y: 103.207 }
+ PathCubic { control1X: -164.727; control1Y: 103.207; control2X: -153.862; control2Y: 87.326; x: -108.42; y: 118.949 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.172
+ PathMove { x: -128.2; y: 90 }
+ PathCubic { control1X: -128.2; control1Y: 90; control2X: -127.6; control2Y: 91.8; x: -128.4; y: 92 }
+ PathCubic { control1X: -129.2; control1Y: 92.2; control2X: -157.8; control2Y: 50.2; x: -177.001; y: 57.8 }
+ PathCubic { control1X: -177.001; control1Y: 57.8; control2X: -161.8; control2Y: 46; x: -128.2; y: 90 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.172
+ PathMove { x: -127.505; y: 96.979 }
+ PathCubic { control1X: -127.505; control1Y: 96.979; control2X: -126.53; control2Y: 98.608; x: -127.269; y: 98.975 }
+ PathCubic { control1X: -128.007; control1Y: 99.343; control2X: -164.992; control2Y: 64.499; x: -182.101; y: 76.061 }
+ PathCubic { control1X: -182.101; control1Y: 76.061; control2X: -169.804; control2Y: 61.261; x: -127.505; y: 96.979 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.172
+ PathMove { x: -127.62; y: 101.349 }
+ PathCubic { control1X: -127.62; control1Y: 101.349; control2X: -126.498; control2Y: 102.88; x: -127.199; y: 103.315 }
+ PathCubic { control1X: -127.9; control1Y: 103.749; control2X: -167.969; control2Y: 72.502; x: -183.927; y: 85.607 }
+ PathCubic { control1X: -183.927; control1Y: 85.607; control2X: -173.062; control2Y: 69.726; x: -127.62; y: 101.349 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 1
+ PathMove { x: -129.83; y: 103.065 }
+ PathCubic { control1X: -129.327; control1Y: 109.113; control2X: -128.339; control2Y: 115.682; x: -126.6; y: 118.801 }
+ PathCubic { control1X: -126.6; control1Y: 118.801; control2X: -130.2; control2Y: 131.201; x: -121.4; y: 144.401 }
+ PathCubic { control1X: -121.4; control1Y: 144.401; control2X: -121.8; control2Y: 151.601; x: -120.2; y: 154.801 }
+ PathCubic { control1X: -120.2; control1Y: 154.801; control2X: -116.2; control2Y: 163.201; x: -111.4; y: 164.001 }
+ PathCubic { control1X: -107.516; control1Y: 164.648; control2X: -98.793; control2Y: 167.717; x: -88.932; y: 169.121 }
+ PathCubic { control1X: -88.932; control1Y: 169.121; control2X: -71.8; control2Y: 183.201; x: -75; y: 196.001 }
+ PathCubic { control1X: -75; control1Y: 196.001; control2X: -75.4; control2Y: 212.401; x: -79; y: 214.001 }
+ PathCubic { control1X: -79; control1Y: 214.001; control2X: -67.4; control2Y: 202.801; x: -77; y: 219.601 }
+ PathLine { x: -81.4; y: 238.401 }
+ PathCubic { control1X: -81.4; control1Y: 238.401; control2X: -55.8; control2Y: 216.801; x: -71.4; y: 235.201 }
+ PathLine { x: -81.4; y: 261.201 }
+ PathCubic { control1X: -81.4; control1Y: 261.201; control2X: -61.8; control2Y: 242.801; x: -69; y: 251.201 }
+ PathLine { x: -72.2; y: 260.001 }
+ PathCubic { control1X: -72.2; control1Y: 260.001; control2X: -29; control2Y: 232.801; x: -59.8; y: 262.401 }
+ PathCubic { control1X: -59.8; control1Y: 262.401; control2X: -51.8; control2Y: 258.801; x: -47.4; y: 261.601 }
+ PathCubic { control1X: -47.4; control1Y: 261.601; control2X: -40.6; control2Y: 260.401; x: -41.4; y: 262.001 }
+ PathCubic { control1X: -41.4; control1Y: 262.001; control2X: -62.2; control2Y: 272.401; x: -65.8; y: 290.801 }
+ PathCubic { control1X: -65.8; control1Y: 290.801; control2X: -57.4; control2Y: 280.801; x: -60.6; y: 291.601 }
+ PathLine { x: -60.2; y: 303.201 }
+ PathCubic { control1X: -60.2; control1Y: 303.201; control2X: -56.2; control2Y: 281.601; x: -56.6; y: 319.201 }
+ PathCubic { control1X: -56.6; control1Y: 319.201; control2X: -37.4; control2Y: 301.201; x: -49; y: 322.001 }
+ PathLine { x: -49; y: 338.801 }
+ PathCubic { control1X: -49; control1Y: 338.801; control2X: -33.8; control2Y: 322.401; x: -40.2; y: 335.201 }
+ PathCubic { control1X: -40.2; control1Y: 335.201; control2X: -30.2; control2Y: 326.401; x: -34.2; y: 341.601 }
+ PathCubic { control1X: -34.2; control1Y: 341.601; control2X: -35; control2Y: 352.001; x: -30.6; y: 340.801 }
+ PathCubic { control1X: -30.6; control1Y: 340.801; control2X: -14.6; control2Y: 310.201; x: -20.6; y: 336.401 }
+ PathCubic { control1X: -20.6; control1Y: 336.401; control2X: -21.4; control2Y: 355.601; x: -16.6; y: 340.801 }
+ PathCubic { control1X: -16.6; control1Y: 340.801; control2X: -16.2; control2Y: 351.201; x: -7; y: 358.401 }
+ PathCubic { control1X: -7; control1Y: 358.401; control2X: -8.2; control2Y: 307.601; x: 4.6; y: 343.601 }
+ PathLine { x: 8.6; y: 360.001 }
+ PathCubic { control1X: 8.6; control1Y: 360.001; control2X: 11.4; control2Y: 350.801; x: 11; y: 345.601 }
+ PathCubic { control1X: 11; control1Y: 345.601; control2X: 25.8; control2Y: 329.201; x: 19; y: 353.601 }
+ PathCubic { control1X: 19; control1Y: 353.601; control2X: 34.2; control2Y: 330.801; x: 31; y: 344.001 }
+ PathCubic { control1X: 31; control1Y: 344.001; control2X: 23.4; control2Y: 360.001; x: 25; y: 364.801 }
+ PathCubic { control1X: 25; control1Y: 364.801; control2X: 41.8; control2Y: 330.001; x: 43; y: 328.401 }
+ PathCubic { control1X: 43; control1Y: 328.401; control2X: 41; control2Y: 370.802; x: 51.8; y: 334.801 }
+ PathCubic { control1X: 51.8; control1Y: 334.801; control2X: 57.4; control2Y: 346.801; x: 54.6; y: 351.201 }
+ PathCubic { control1X: 54.6; control1Y: 351.201; control2X: 62.6; control2Y: 343.201; x: 61.8; y: 340.001 }
+ PathCubic { control1X: 61.8; control1Y: 340.001; control2X: 66.4; control2Y: 331.801; x: 69.2; y: 345.401 }
+ PathCubic { control1X: 69.2; control1Y: 345.401; control2X: 71; control2Y: 354.801; x: 72.6; y: 351.601 }
+ PathCubic { control1X: 72.6; control1Y: 351.601; control2X: 76.6; control2Y: 375.602; x: 77.8; y: 352.801 }
+ PathCubic { control1X: 77.8; control1Y: 352.801; control2X: 79.4; control2Y: 339.201; x: 72.2; y: 327.601 }
+ PathCubic { control1X: 72.2; control1Y: 327.601; control2X: 73; control2Y: 324.401; x: 70.2; y: 320.401 }
+ PathCubic { control1X: 70.2; control1Y: 320.401; control2X: 83.8; control2Y: 342.001; x: 76.6; y: 313.201 }
+ PathCubic { control1X: 76.6; control1Y: 313.201; control2X: 87.801; control2Y: 321.201; x: 89.001; y: 321.201 }
+ PathCubic { control1X: 89.001; control1Y: 321.201; control2X: 75.4; control2Y: 298.001; x: 84.2; y: 302.801 }
+ PathCubic { control1X: 84.2; control1Y: 302.801; control2X: 79; control2Y: 292.401; x: 97.001; y: 304.401 }
+ PathCubic { control1X: 97.001; control1Y: 304.401; control2X: 81; control2Y: 288.401; x: 98.601; y: 298.001 }
+ PathCubic { control1X: 98.601; control1Y: 298.001; control2X: 106.601; control2Y: 304.401; x: 99.001; y: 294.401 }
+ PathCubic { control1X: 99.001; control1Y: 294.401; control2X: 84.6; control2Y: 278.401; x: 106.601; y: 296.401 }
+ PathCubic { control1X: 106.601; control1Y: 296.401; control2X: 118.201; control2Y: 312.801; x: 119.001; y: 315.601 }
+ PathCubic { control1X: 119.001; control1Y: 315.601; control2X: 109.001; control2Y: 286.401; x: 104.601; y: 283.601 }
+ PathCubic { control1X: 104.601; control1Y: 283.601; control2X: 113.001; control2Y: 247.201; x: 154.201; y: 262.801 }
+ PathCubic { control1X: 154.201; control1Y: 262.801; control2X: 161.001; control2Y: 280.001; x: 165.401; y: 261.601 }
+ PathCubic { control1X: 165.401; control1Y: 261.601; control2X: 178.201; control2Y: 255.201; x: 189.401; y: 282.801 }
+ PathCubic { control1X: 189.401; control1Y: 282.801; control2X: 193.401; control2Y: 269.201; x: 192.601; y: 266.401 }
+ PathCubic { control1X: 192.601; control1Y: 266.401; control2X: 199.401; control2Y: 267.601; x: 198.601; y: 266.401 }
+ PathCubic { control1X: 198.601; control1Y: 266.401; control2X: 211.801; control2Y: 270.801; x: 213.001; y: 270.001 }
+ PathCubic { control1X: 213.001; control1Y: 270.001; control2X: 219.801; control2Y: 276.801; x: 220.201; y: 273.201 }
+ PathCubic { control1X: 220.201; control1Y: 273.201; control2X: 229.401; control2Y: 276.001; x: 227.401; y: 272.401 }
+ PathCubic { control1X: 227.401; control1Y: 272.401; control2X: 236.201; control2Y: 288.001; x: 236.601; y: 291.601 }
+ PathLine { x: 239.001; y: 277.601 }
+ PathLine { x: 241.001; y: 280.401 }
+ PathCubic { control1X: 241.001; control1Y: 280.401; control2X: 242.601; control2Y: 272.801; x: 241.801; y: 271.601 }
+ PathCubic { control1X: 241.001; control1Y: 270.401; control2X: 261.801; control2Y: 278.401; x: 266.601; y: 299.201 }
+ PathLine { x: 268.601; y: 307.601 }
+ PathCubic { control1X: 268.601; control1Y: 307.601; control2X: 274.601; control2Y: 292.801; x: 273.001; y: 288.801 }
+ PathCubic { control1X: 273.001; control1Y: 288.801; control2X: 278.201; control2Y: 289.601; x: 278.601; y: 294.001 }
+ PathCubic { control1X: 278.601; control1Y: 294.001; control2X: 282.601; control2Y: 270.801; x: 277.801; y: 264.801 }
+ PathCubic { control1X: 277.801; control1Y: 264.801; control2X: 282.201; control2Y: 264.001; x: 283.401; y: 267.601 }
+ PathLine { x: 283.401; y: 260.401 }
+ PathCubic { control1X: 283.401; control1Y: 260.401; control2X: 290.601; control2Y: 261.201; x: 290.601; y: 258.801 }
+ PathCubic { control1X: 290.601; control1Y: 258.801; control2X: 295.001; control2Y: 254.801; x: 297.001; y: 259.601 }
+ PathCubic { control1X: 297.001; control1Y: 259.601; control2X: 284.601; control2Y: 224.401; x: 303.001; y: 243.601 }
+ PathCubic { control1X: 303.001; control1Y: 243.601; control2X: 310.201; control2Y: 254.401; x: 306.601; y: 235.601 }
+ PathCubic { control1X: 303.001; control1Y: 216.801; control2X: 299.001; control2Y: 215.201; x: 303.801; y: 214.801 }
+ PathCubic { control1X: 303.801; control1Y: 214.801; control2X: 304.601; control2Y: 211.201; x: 302.601; y: 209.601 }
+ PathCubic { control1X: 300.601; control1Y: 208.001; control2X: 303.801; control2Y: 209.601; x: 303.801; y: 209.601 }
+ PathCubic { control1X: 303.801; control1Y: 209.601; control2X: 308.601; control2Y: 213.601; x: 303.401; y: 191.601 }
+ PathCubic { control1X: 303.401; control1Y: 191.601; control2X: 309.801; control2Y: 193.201; x: 297.801; y: 164.001 }
+ PathCubic { control1X: 297.801; control1Y: 164.001; control2X: 300.601; control2Y: 161.601; x: 296.601; y: 153.201 }
+ PathCubic { control1X: 296.601; control1Y: 153.201; control2X: 304.601; control2Y: 157.601; x: 307.401; y: 156.001 }
+ PathCubic { control1X: 307.401; control1Y: 156.001; control2X: 307.001; control2Y: 154.401; x: 303.801; y: 150.401 }
+ PathCubic { control1X: 303.801; control1Y: 150.401; control2X: 282.201; control2Y: 95.6; x: 302.601; y: 117.601 }
+ PathCubic { control1X: 302.601; control1Y: 117.601; control2X: 314.451; control2Y: 131.151; x: 308.051; y: 108.351 }
+ PathCubic { control1X: 308.051; control1Y: 108.351; control2X: 298.94; control2Y: 84.341; x: 299.717; y: 80.045 }
+ PathLine { x: -129.83; y: 103.065 }
+ }
+
+ ShapePath {
+ fillColor: "#cc7226"
+ strokeColor: "#000000"
+ strokeWidth: 1
+ PathMove { x: 299.717; y: 80.245 }
+ PathCubic { control1X: 300.345; control1Y: 80.426; control2X: 302.551; control2Y: 81.55; x: 303.801; y: 83.2 }
+ PathCubic { control1X: 303.801; control1Y: 83.2; control2X: 310.601; control2Y: 94; x: 305.401; y: 75.6 }
+ PathCubic { control1X: 305.401; control1Y: 75.6; control2X: 296.201; control2Y: 46.8; x: 305.001; y: 58 }
+ PathCubic { control1X: 305.001; control1Y: 58; control2X: 311.001; control2Y: 65.2; x: 307.801; y: 51.6 }
+ PathCubic { control1X: 303.936; control1Y: 35.173; control2X: 301.401; control2Y: 28.8; x: 301.401; y: 28.8 }
+ PathCubic { control1X: 301.401; control1Y: 28.8; control2X: 313.001; control2Y: 33.6; x: 286.201; y: -6 }
+ PathLine { x: 295.001; y: -2.4 }
+ PathCubic { control1X: 295.001; control1Y: -2.4; control2X: 275.401; control2Y: -42; x: 253.801; y: -47.2 }
+ PathLine { x: 245.801; y: -53.2 }
+ PathCubic { control1X: 245.801; control1Y: -53.2; control2X: 284.201; control2Y: -91.2; x: 271.401; y: -128 }
+ PathCubic { control1X: 271.401; control1Y: -128; control2X: 264.601; control2Y: -133.2; x: 255.001; y: -124 }
+ PathCubic { control1X: 255.001; control1Y: -124; control2X: 248.601; control2Y: -119.2; x: 242.601; y: -120.8 }
+ PathCubic { control1X: 242.601; control1Y: -120.8; control2X: 211.801; control2Y: -119.6; x: 209.801; y: -119.6 }
+ PathCubic { control1X: 207.801; control1Y: -119.6; control2X: 173.001; control2Y: -156.8; x: 107.401; y: -139.2 }
+ PathCubic { control1X: 107.401; control1Y: -139.2; control2X: 102.201; control2Y: -137.2; x: 97.801; y: -138.4 }
+ PathCubic { control1X: 97.801; control1Y: -138.4; control2X: 79.4; control2Y: -154.4; x: 30.6; y: -131.6 }
+ PathCubic { control1X: 30.6; control1Y: -131.6; control2X: 20.6; control2Y: -129.6; x: 19; y: -129.6 }
+ PathCubic { control1X: 17.4; control1Y: -129.6; control2X: 14.6; control2Y: -129.6; x: 6.6; y: -123.2 }
+ PathCubic { control1X: -1.4; control1Y: -116.8; control2X: -1.8; control2Y: -116; x: -3.8; y: -114.4 }
+ PathCubic { control1X: -3.8; control1Y: -114.4; control2X: -20.2; control2Y: -103.2; x: -25; y: -102.4 }
+ PathCubic { control1X: -25; control1Y: -102.4; control2X: -36.6; control2Y: -96; x: -41; y: -86 }
+ PathLine { x: -44.6; y: -84.8 }
+ PathCubic { control1X: -44.6; control1Y: -84.8; control2X: -46.2; control2Y: -77.6; x: -46.6; y: -76.4 }
+ PathCubic { control1X: -46.6; control1Y: -76.4; control2X: -51.4; control2Y: -72.8; x: -52.2; y: -67.2 }
+ PathCubic { control1X: -52.2; control1Y: -67.2; control2X: -61; control2Y: -61.2; x: -60.6; y: -56.8 }
+ PathCubic { control1X: -60.6; control1Y: -56.8; control2X: -62.2; control2Y: -51.6; x: -63; y: -46.8 }
+ PathCubic { control1X: -63; control1Y: -46.8; control2X: -70.2; control2Y: -42; x: -69.4; y: -39.2 }
+ PathCubic { control1X: -69.4; control1Y: -39.2; control2X: -77; control2Y: -25.2; x: -75.8; y: -18.4 }
+ PathCubic { control1X: -75.8; control1Y: -18.4; control2X: -82.2; control2Y: -18.8; x: -85; y: -16.4 }
+ PathCubic { control1X: -85; control1Y: -16.4; control2X: -85.8; control2Y: -11.6; x: -87.4; y: -11.2 }
+ PathCubic { control1X: -87.4; control1Y: -11.2; control2X: -90.2; control2Y: -10; x: -87.8; y: -6 }
+ PathCubic { control1X: -87.8; control1Y: -6; control2X: -89.4; control2Y: -3.2; x: -89.8; y: -1.6 }
+ PathCubic { control1X: -89.8; control1Y: -1.6; control2X: -89; control2Y: 1.2; x: -93.4; y: 6.8 }
+ PathCubic { control1X: -93.4; control1Y: 6.8; control2X: -99.8; control2Y: 25.6; x: -97.8; y: 30.8 }
+ PathCubic { control1X: -97.8; control1Y: 30.8; control2X: -97.4; control2Y: 35.6; x: -100.2; y: 37.2 }
+ PathCubic { control1X: -100.2; control1Y: 37.2; control2X: -103.8; control2Y: 36.8; x: -95.4; y: 48.8 }
+ PathCubic { control1X: -95.4; control1Y: 48.8; control2X: -94.6; control2Y: 50; x: -97.8; y: 52.4 }
+ PathCubic { control1X: -97.8; control1Y: 52.4; control2X: -115; control2Y: 56; x: -117.4; y: 72.4 }
+ PathCubic { control1X: -117.4; control1Y: 72.4; control2X: -131; control2Y: 87.2; x: -131; y: 92.4 }
+ PathCubic { control1X: -131; control1Y: 94.705; control2X: -130.729; control2Y: 97.852; x: -130.03; y: 102.465 }
+ PathCubic { control1X: -130.03; control1Y: 102.465; control2X: -130.6; control2Y: 110.801; x: -103; y: 111.601 }
+ PathCubic { control1X: -75.4; control1Y: 112.401; control2X: 299.717; control2Y: 80.245; x: 299.717; y: 80.245 }
+ }
+
+ ShapePath {
+ fillColor: "#cc7226"
+ strokeWidth: -1
+ PathMove { x: -115.6; y: 102.6 }
+ PathCubic { control1X: -140.6; control1Y: 63.2; control2X: -126.2; control2Y: 119.601; x: -126.2; y: 119.601 }
+ PathCubic { control1X: -117.4; control1Y: 154.001; control2X: 12.2; control2Y: 116.401; x: 12.2; y: 116.401 }
+ PathCubic { control1X: 12.2; control1Y: 116.401; control2X: 181.001; control2Y: 86; x: 192.201; y: 82 }
+ PathCubic { control1X: 203.401; control1Y: 78; control2X: 298.601; control2Y: 84.4; x: 298.601; y: 84.4 }
+ PathLine { x: 293.001; y: 67.6 }
+ PathCubic { control1X: 228.201; control1Y: 21.2; control2X: 209.001; control2Y: 44.4; x: 195.401; y: 40.4 }
+ PathCubic { control1X: 181.801; control1Y: 36.4; control2X: 184.201; control2Y: 46; x: 181.001; y: 46.8 }
+ PathCubic { control1X: 177.801; control1Y: 47.6; control2X: 138.601; control2Y: 22.8; x: 132.201; y: 23.6 }
+ PathCubic { control1X: 125.801; control1Y: 24.4; control2X: 100.459; control2Y: 0.649; x: 115.401; y: 32.4 }
+ PathCubic { control1X: 131.401; control1Y: 66.4; control2X: 57; control2Y: 71.6; x: 40.2; y: 60.4 }
+ PathCubic { control1X: 23.4; control1Y: 49.2; control2X: 47.4; control2Y: 78.8; x: 47.4; y: 78.8 }
+ PathCubic { control1X: 65.8; control1Y: 98.8; control2X: 31.4; control2Y: 82; x: 31.4; y: 82 }
+ PathCubic { control1X: -3; control1Y: 69.2; control2X: -27; control2Y: 94.8; x: -30.2; y: 95.6 }
+ PathCubic { control1X: -33.4; control1Y: 96.4; control2X: -38.2; control2Y: 99.6; x: -39; y: 93.2 }
+ PathCubic { control1X: -39.8; control1Y: 86.8; control2X: -47.31; control2Y: 70.099; x: -79; y: 96.4 }
+ PathCubic { control1X: -99; control1Y: 113.001; control2X: -112.8; control2Y: 91; x: -112.8; y: 91 }
+ PathLine { x: -115.6; y: 102.6 }
+ }
+
+ ShapePath {
+ fillColor: "#e87f3a"
+ strokeWidth: -1
+ PathMove { x: 133.51; y: 25.346 }
+ PathCubic { control1X: 127.11; control1Y: 26.146; control2X: 101.743; control2Y: 2.407; x: 116.71; y: 34.146 }
+ PathCubic { control1X: 133.31; control1Y: 69.346; control2X: 58.31; control2Y: 73.346; x: 41.51; y: 62.146 }
+ PathCubic { control1X: 24.709; control1Y: 50.946; control2X: 48.71; control2Y: 80.546; x: 48.71; y: 80.546 }
+ PathCubic { control1X: 67.11; control1Y: 100.546; control2X: 32.709; control2Y: 83.746; x: 32.709; y: 83.746 }
+ PathCubic { control1X: -1.691; control1Y: 70.946; control2X: -25.691; control2Y: 96.546; x: -28.891; y: 97.346 }
+ PathCubic { control1X: -32.091; control1Y: 98.146; control2X: -36.891; control2Y: 101.346; x: -37.691; y: 94.946 }
+ PathCubic { control1X: -38.491; control1Y: 88.546; control2X: -45.87; control2Y: 72.012; x: -77.691; y: 98.146 }
+ PathCubic { control1X: -98.927; control1Y: 115.492; control2X: -112.418; control2Y: 94.037; x: -112.418; y: 94.037 }
+ PathLine { x: -115.618; y: 104.146 }
+ PathCubic { control1X: -140.618; control1Y: 64.346; control2X: -125.546; control2Y: 122.655; x: -125.546; y: 122.655 }
+ PathCubic { control1X: -116.745; control1Y: 157.056; control2X: 13.509; control2Y: 118.146; x: 13.509; y: 118.146 }
+ PathCubic { control1X: 13.509; control1Y: 118.146; control2X: 182.31; control2Y: 87.746; x: 193.51; y: 83.746 }
+ PathCubic { control1X: 204.71; control1Y: 79.746; control2X: 299.038; control2Y: 86.073; x: 299.038; y: 86.073 }
+ PathLine { x: 293.51; y: 68.764 }
+ PathCubic { control1X: 228.71; control1Y: 22.364; control2X: 210.31; control2Y: 46.146; x: 196.71; y: 42.146 }
+ PathCubic { control1X: 183.11; control1Y: 38.146; control2X: 185.51; control2Y: 47.746; x: 182.31; y: 48.546 }
+ PathCubic { control1X: 179.11; control1Y: 49.346; control2X: 139.91; control2Y: 24.546; x: 133.51; y: 25.346 }
+ }
+
+ ShapePath {
+ fillColor: "#ea8c4d"
+ strokeWidth: -1
+ PathMove { x: 134.819; y: 27.091 }
+ PathCubic { control1X: 128.419; control1Y: 27.891; control2X: 103.685; control2Y: 3.862; x: 118.019; y: 35.891 }
+ PathCubic { control1X: 134.219; control1Y: 72.092; control2X: 59.619; control2Y: 75.092; x: 42.819; y: 63.892 }
+ PathCubic { control1X: 26.019; control1Y: 52.692; control2X: 50.019; control2Y: 82.292; x: 50.019; y: 82.292 }
+ PathCubic { control1X: 68.419; control1Y: 102.292; control2X: 34.019; control2Y: 85.492; x: 34.019; y: 85.492 }
+ PathCubic { control1X: -0.381; control1Y: 72.692; control2X: -24.382; control2Y: 98.292; x: -27.582; y: 99.092 }
+ PathCubic { control1X: -30.782; control1Y: 99.892; control2X: -35.582; control2Y: 103.092; x: -36.382; y: 96.692 }
+ PathCubic { control1X: -37.182; control1Y: 90.292; control2X: -44.43; control2Y: 73.925; x: -76.382; y: 99.892 }
+ PathCubic { control1X: -98.855; control1Y: 117.983; control2X: -112.036; control2Y: 97.074; x: -112.036; y: 97.074 }
+ PathLine { x: -115.636; y: 105.692 }
+ PathCubic { control1X: -139.436; control1Y: 66.692; control2X: -124.891; control2Y: 125.71; x: -124.891; y: 125.71 }
+ PathCubic { control1X: -116.091; control1Y: 160.11; control2X: 14.819; control2Y: 119.892; x: 14.819; y: 119.892 }
+ PathCubic { control1X: 14.819; control1Y: 119.892; control2X: 183.619; control2Y: 89.492; x: 194.819; y: 85.492 }
+ PathCubic { control1X: 206.019; control1Y: 81.492; control2X: 299.474; control2Y: 87.746; x: 299.474; y: 87.746 }
+ PathLine { x: 294.02; y: 69.928 }
+ PathCubic { control1X: 229.219; control1Y: 23.528; control2X: 211.619; control2Y: 47.891; x: 198.019; y: 43.891 }
+ PathCubic { control1X: 184.419; control1Y: 39.891; control2X: 186.819; control2Y: 49.491; x: 183.619; y: 50.292 }
+ PathCubic { control1X: 180.419; control1Y: 51.092; control2X: 141.219; control2Y: 26.291; x: 134.819; y: 27.091 }
+ }
+
+ ShapePath {
+ fillColor: "#ec9961"
+ strokeWidth: -1
+ PathMove { x: 136.128; y: 28.837 }
+ PathCubic { control1X: 129.728; control1Y: 29.637; control2X: 104.999; control2Y: 5.605; x: 119.328; y: 37.637 }
+ PathCubic { control1X: 136.128; control1Y: 75.193; control2X: 60.394; control2Y: 76.482; x: 44.128; y: 65.637 }
+ PathCubic { control1X: 27.328; control1Y: 54.437; control2X: 51.328; control2Y: 84.037; x: 51.328; y: 84.037 }
+ PathCubic { control1X: 69.728; control1Y: 104.037; control2X: 35.328; control2Y: 87.237; x: 35.328; y: 87.237 }
+ PathCubic { control1X: 0.928; control1Y: 74.437; control2X: -23.072; control2Y: 100.037; x: -26.272; y: 100.837 }
+ PathCubic { control1X: -29.472; control1Y: 101.637; control2X: -34.272; control2Y: 104.837; x: -35.072; y: 98.437 }
+ PathCubic { control1X: -35.872; control1Y: 92.037; control2X: -42.989; control2Y: 75.839; x: -75.073; y: 101.637 }
+ PathCubic { control1X: -98.782; control1Y: 120.474; control2X: -111.655; control2Y: 100.11; x: -111.655; y: 100.11 }
+ PathLine { x: -115.655; y: 107.237 }
+ PathCubic { control1X: -137.455; control1Y: 70.437; control2X: -124.236; control2Y: 128.765; x: -124.236; y: 128.765 }
+ PathCubic { control1X: -115.436; control1Y: 163.165; control2X: 16.128; control2Y: 121.637; x: 16.128; y: 121.637 }
+ PathCubic { control1X: 16.128; control1Y: 121.637; control2X: 184.928; control2Y: 91.237; x: 196.129; y: 87.237 }
+ PathCubic { control1X: 207.329; control1Y: 83.237; control2X: 299.911; control2Y: 89.419; x: 299.911; y: 89.419 }
+ PathLine { x: 294.529; y: 71.092 }
+ PathCubic { control1X: 229.729; control1Y: 24.691; control2X: 212.929; control2Y: 49.637; x: 199.329; y: 45.637 }
+ PathCubic { control1X: 185.728; control1Y: 41.637; control2X: 188.128; control2Y: 51.237; x: 184.928; y: 52.037 }
+ PathCubic { control1X: 181.728; control1Y: 52.837; control2X: 142.528; control2Y: 28.037; x: 136.128; y: 28.837 }
+ }
+
+ ShapePath {
+ fillColor: "#eea575"
+ strokeWidth: -1
+ PathMove { x: 137.438; y: 30.583 }
+ PathCubic { control1X: 131.037; control1Y: 31.383; control2X: 106.814; control2Y: 7.129; x: 120.637; y: 39.383 }
+ PathCubic { control1X: 137.438; control1Y: 78.583; control2X: 62.237; control2Y: 78.583; x: 45.437; y: 67.383 }
+ PathCubic { control1X: 28.637; control1Y: 56.183; control2X: 52.637; control2Y: 85.783; x: 52.637; y: 85.783 }
+ PathCubic { control1X: 71.037; control1Y: 105.783; control2X: 36.637; control2Y: 88.983; x: 36.637; y: 88.983 }
+ PathCubic { control1X: 2.237; control1Y: 76.183; control2X: -21.763; control2Y: 101.783; x: -24.963; y: 102.583 }
+ PathCubic { control1X: -28.163; control1Y: 103.383; control2X: -32.963; control2Y: 106.583; x: -33.763; y: 100.183 }
+ PathCubic { control1X: -34.563; control1Y: 93.783; control2X: -41.548; control2Y: 77.752; x: -73.763; y: 103.383 }
+ PathCubic { control1X: -98.709; control1Y: 122.965; control2X: -111.273; control2Y: 103.146; x: -111.273; y: 103.146 }
+ PathLine { x: -115.673; y: 108.783 }
+ PathCubic { control1X: -135.473; control1Y: 73.982; control2X: -123.582; control2Y: 131.819; x: -123.582; y: 131.819 }
+ PathCubic { control1X: -114.782; control1Y: 166.22; control2X: 17.437; control2Y: 123.383; x: 17.437; y: 123.383 }
+ PathCubic { control1X: 17.437; control1Y: 123.383; control2X: 186.238; control2Y: 92.983; x: 197.438; y: 88.983 }
+ PathCubic { control1X: 208.638; control1Y: 84.983; control2X: 300.347; control2Y: 91.092; x: 300.347; y: 91.092 }
+ PathLine { x: 295.038; y: 72.255 }
+ PathCubic { control1X: 230.238; control1Y: 25.855; control2X: 214.238; control2Y: 51.383; x: 200.638; y: 47.383 }
+ PathCubic { control1X: 187.038; control1Y: 43.383; control2X: 189.438; control2Y: 52.983; x: 186.238; y: 53.783 }
+ PathCubic { control1X: 183.038; control1Y: 54.583; control2X: 143.838; control2Y: 29.783; x: 137.438; y: 30.583 }
+ }
+
+ ShapePath {
+ fillColor: "#f1b288"
+ strokeWidth: -1
+ PathMove { x: 138.747; y: 32.328 }
+ PathCubic { control1X: 132.347; control1Y: 33.128; control2X: 106.383; control2Y: 9.677; x: 121.947; y: 41.128 }
+ PathCubic { control1X: 141.147; control1Y: 79.928; control2X: 63.546; control2Y: 80.328; x: 46.746; y: 69.128 }
+ PathCubic { control1X: 29.946; control1Y: 57.928; control2X: 53.946; control2Y: 87.528; x: 53.946; y: 87.528 }
+ PathCubic { control1X: 72.346; control1Y: 107.528; control2X: 37.946; control2Y: 90.728; x: 37.946; y: 90.728 }
+ PathCubic { control1X: 3.546; control1Y: 77.928; control2X: -20.454; control2Y: 103.528; x: -23.654; y: 104.328 }
+ PathCubic { control1X: -26.854; control1Y: 105.128; control2X: -31.654; control2Y: 108.328; x: -32.454; y: 101.928 }
+ PathCubic { control1X: -33.254; control1Y: 95.528; control2X: -40.108; control2Y: 79.665; x: -72.454; y: 105.128 }
+ PathCubic { control1X: -98.636; control1Y: 125.456; control2X: -110.891; control2Y: 106.183; x: -110.891; y: 106.183 }
+ PathLine { x: -115.691; y: 110.328 }
+ PathCubic { control1X: -133.691; control1Y: 77.128; control2X: -122.927; control2Y: 134.874; x: -122.927; y: 134.874 }
+ PathCubic { control1X: -114.127; control1Y: 169.274; control2X: 18.746; control2Y: 125.128; x: 18.746; y: 125.128 }
+ PathCubic { control1X: 18.746; control1Y: 125.128; control2X: 187.547; control2Y: 94.728; x: 198.747; y: 90.728 }
+ PathCubic { control1X: 209.947; control1Y: 86.728; control2X: 300.783; control2Y: 92.764; x: 300.783; y: 92.764 }
+ PathLine { x: 295.547; y: 73.419 }
+ PathCubic { control1X: 230.747; control1Y: 27.019; control2X: 215.547; control2Y: 53.128; x: 201.947; y: 49.128 }
+ PathCubic { control1X: 188.347; control1Y: 45.128; control2X: 190.747; control2Y: 54.728; x: 187.547; y: 55.528 }
+ PathCubic { control1X: 184.347; control1Y: 56.328; control2X: 145.147; control2Y: 31.528; x: 138.747; y: 32.328 }
+ }
+
+ ShapePath {
+ fillColor: "#f3bf9c"
+ strokeWidth: -1
+ PathMove { x: 140.056; y: 34.073 }
+ PathCubic { control1X: 133.655; control1Y: 34.873; control2X: 107.313; control2Y: 11.613; x: 123.255; y: 42.873 }
+ PathCubic { control1X: 143.656; control1Y: 82.874; control2X: 64.855; control2Y: 82.074; x: 48.055; y: 70.874 }
+ PathCubic { control1X: 31.255; control1Y: 59.674; control2X: 55.255; control2Y: 89.274; x: 55.255; y: 89.274 }
+ PathCubic { control1X: 73.655; control1Y: 109.274; control2X: 39.255; control2Y: 92.474; x: 39.255; y: 92.474 }
+ PathCubic { control1X: 4.855; control1Y: 79.674; control2X: -19.145; control2Y: 105.274; x: -22.345; y: 106.074 }
+ PathCubic { control1X: -25.545; control1Y: 106.874; control2X: -30.345; control2Y: 110.074; x: -31.145; y: 103.674 }
+ PathCubic { control1X: -31.945; control1Y: 97.274; control2X: -38.668; control2Y: 81.578; x: -71.145; y: 106.874 }
+ PathCubic { control1X: -98.564; control1Y: 127.947; control2X: -110.509; control2Y: 109.219; x: -110.509; y: 109.219 }
+ PathLine { x: -115.709; y: 111.874 }
+ PathCubic { control1X: -131.709; control1Y: 81.674; control2X: -122.273; control2Y: 137.929; x: -122.273; y: 137.929 }
+ PathCubic { control1X: -113.473; control1Y: 172.329; control2X: 20.055; control2Y: 126.874; x: 20.055; y: 126.874 }
+ PathCubic { control1X: 20.055; control1Y: 126.874; control2X: 188.856; control2Y: 96.474; x: 200.056; y: 92.474 }
+ PathCubic { control1X: 211.256; control1Y: 88.474; control2X: 301.22; control2Y: 94.437; x: 301.22; y: 94.437 }
+ PathLine { x: 296.056; y: 74.583 }
+ PathCubic { control1X: 231.256; control1Y: 28.183; control2X: 216.856; control2Y: 54.874; x: 203.256; y: 50.874 }
+ PathCubic { control1X: 189.656; control1Y: 46.873; control2X: 192.056; control2Y: 56.474; x: 188.856; y: 57.274 }
+ PathCubic { control1X: 185.656; control1Y: 58.074; control2X: 146.456; control2Y: 33.273; x: 140.056; y: 34.073 }
+ }
+
+ ShapePath {
+ fillColor: "#f5ccb0"
+ strokeWidth: -1
+ PathMove { x: 141.365; y: 35.819 }
+ PathCubic { control1X: 134.965; control1Y: 36.619; control2X: 107.523; control2Y: 13.944; x: 124.565; y: 44.619 }
+ PathCubic { control1X: 146.565; control1Y: 84.219; control2X: 66.164; control2Y: 83.819; x: 49.364; y: 72.619 }
+ PathCubic { control1X: 32.564; control1Y: 61.419; control2X: 56.564; control2Y: 91.019; x: 56.564; y: 91.019 }
+ PathCubic { control1X: 74.964; control1Y: 111.019; control2X: 40.564; control2Y: 94.219; x: 40.564; y: 94.219 }
+ PathCubic { control1X: 6.164; control1Y: 81.419; control2X: -17.836; control2Y: 107.019; x: -21.036; y: 107.819 }
+ PathCubic { control1X: -24.236; control1Y: 108.619; control2X: -29.036; control2Y: 111.819; x: -29.836; y: 105.419 }
+ PathCubic { control1X: -30.636; control1Y: 99.019; control2X: -37.227; control2Y: 83.492; x: -69.836; y: 108.619 }
+ PathCubic { control1X: -98.491; control1Y: 130.438; control2X: -110.127; control2Y: 112.256; x: -110.127; y: 112.256 }
+ PathLine { x: -115.727; y: 113.419 }
+ PathCubic { control1X: -130.128; control1Y: 85.019; control2X: -121.618; control2Y: 140.983; x: -121.618; y: 140.983 }
+ PathCubic { control1X: -112.818; control1Y: 175.384; control2X: 21.364; control2Y: 128.619; x: 21.364; y: 128.619 }
+ PathCubic { control1X: 21.364; control1Y: 128.619; control2X: 190.165; control2Y: 98.219; x: 201.365; y: 94.219 }
+ PathCubic { control1X: 212.565; control1Y: 90.219; control2X: 301.656; control2Y: 96.11; x: 301.656; y: 96.11 }
+ PathLine { x: 296.565; y: 75.746 }
+ PathCubic { control1X: 231.765; control1Y: 29.346; control2X: 218.165; control2Y: 56.619; x: 204.565; y: 52.619 }
+ PathCubic { control1X: 190.965; control1Y: 48.619; control2X: 193.365; control2Y: 58.219; x: 190.165; y: 59.019 }
+ PathCubic { control1X: 186.965; control1Y: 59.819; control2X: 147.765; control2Y: 35.019; x: 141.365; y: 35.819 }
+ }
+
+ ShapePath {
+ fillColor: "#f8d8c4"
+ strokeWidth: -1
+ PathMove { x: 142.674; y: 37.565 }
+ PathCubic { control1X: 136.274; control1Y: 38.365; control2X: 108.832; control2Y: 15.689; x: 125.874; y: 46.365 }
+ PathCubic { control1X: 147.874; control1Y: 85.965; control2X: 67.474; control2Y: 85.565; x: 50.674; y: 74.365 }
+ PathCubic { control1X: 33.874; control1Y: 63.165; control2X: 57.874; control2Y: 92.765; x: 57.874; y: 92.765 }
+ PathCubic { control1X: 76.274; control1Y: 112.765; control2X: 41.874; control2Y: 95.965; x: 41.874; y: 95.965 }
+ PathCubic { control1X: 7.473; control1Y: 83.165; control2X: -16.527; control2Y: 108.765; x: -19.727; y: 109.565 }
+ PathCubic { control1X: -22.927; control1Y: 110.365; control2X: -27.727; control2Y: 113.565; x: -28.527; y: 107.165 }
+ PathCubic { control1X: -29.327; control1Y: 100.765; control2X: -35.786; control2Y: 85.405; x: -68.527; y: 110.365 }
+ PathCubic { control1X: -98.418; control1Y: 132.929; control2X: -109.745; control2Y: 115.293; x: -109.745; y: 115.293 }
+ PathLine { x: -115.745; y: 114.965 }
+ PathCubic { control1X: -129.346; control1Y: 88.564; control2X: -120.963; control2Y: 144.038; x: -120.963; y: 144.038 }
+ PathCubic { control1X: -112.163; control1Y: 178.438; control2X: 22.673; control2Y: 130.365; x: 22.673; y: 130.365 }
+ PathCubic { control1X: 22.673; control1Y: 130.365; control2X: 191.474; control2Y: 99.965; x: 202.674; y: 95.965 }
+ PathCubic { control1X: 213.874; control1Y: 91.965; control2X: 302.093; control2Y: 97.783; x: 302.093; y: 97.783 }
+ PathLine { x: 297.075; y: 76.91 }
+ PathCubic { control1X: 232.274; control1Y: 30.51; control2X: 219.474; control2Y: 58.365; x: 205.874; y: 54.365 }
+ PathCubic { control1X: 192.274; control1Y: 50.365; control2X: 194.674; control2Y: 59.965; x: 191.474; y: 60.765 }
+ PathCubic { control1X: 188.274; control1Y: 61.565; control2X: 149.074; control2Y: 36.765; x: 142.674; y: 37.565 }
+ }
+
+ ShapePath {
+ fillColor: "#fae5d7"
+ strokeWidth: -1
+ PathMove { x: 143.983; y: 39.31 }
+ PathCubic { control1X: 137.583; control1Y: 40.11; control2X: 110.529; control2Y: 17.223; x: 127.183; y: 48.11 }
+ PathCubic { control1X: 149.183; control1Y: 88.91; control2X: 68.783; control2Y: 87.31; x: 51.983; y: 76.11 }
+ PathCubic { control1X: 35.183; control1Y: 64.91; control2X: 59.183; control2Y: 94.51; x: 59.183; y: 94.51 }
+ PathCubic { control1X: 77.583; control1Y: 114.51; control2X: 43.183; control2Y: 97.71; x: 43.183; y: 97.71 }
+ PathCubic { control1X: 8.783; control1Y: 84.91; control2X: -15.217; control2Y: 110.51; x: -18.417; y: 111.31 }
+ PathCubic { control1X: -21.618; control1Y: 112.11; control2X: -26.418; control2Y: 115.31; x: -27.218; y: 108.91 }
+ PathCubic { control1X: -28.018; control1Y: 102.51; control2X: -34.346; control2Y: 87.318; x: -67.218; y: 112.11 }
+ PathCubic { control1X: -98.345; control1Y: 135.42; control2X: -109.363; control2Y: 118.329; x: -109.363; y: 118.329 }
+ PathLine { x: -115.764; y: 116.51 }
+ PathCubic { control1X: -128.764; control1Y: 92.51; control2X: -120.309; control2Y: 147.093; x: -120.309; y: 147.093 }
+ PathCubic { control1X: -111.509; control1Y: 181.493; control2X: 23.983; control2Y: 132.11; x: 23.983; y: 132.11 }
+ PathCubic { control1X: 23.983; control1Y: 132.11; control2X: 192.783; control2Y: 101.71; x: 203.983; y: 97.71 }
+ PathCubic { control1X: 215.183; control1Y: 93.71; control2X: 302.529; control2Y: 99.456; x: 302.529; y: 99.456 }
+ PathLine { x: 297.583; y: 78.074 }
+ PathCubic { control1X: 232.783; control1Y: 31.673; control2X: 220.783; control2Y: 60.11; x: 207.183; y: 56.11 }
+ PathCubic { control1X: 193.583; control1Y: 52.11; control2X: 195.983; control2Y: 61.71; x: 192.783; y: 62.51 }
+ PathCubic { control1X: 189.583; control1Y: 63.31; control2X: 150.383; control2Y: 38.51; x: 143.983; y: 39.31 }
+ }
+
+ ShapePath {
+ fillColor: "#fcf2eb"
+ strokeWidth: -1
+ PathMove { x: 145.292; y: 41.055 }
+ PathCubic { control1X: 138.892; control1Y: 41.855; control2X: 112.917; control2Y: 18.411; x: 128.492; y: 49.855 }
+ PathCubic { control1X: 149.692; control1Y: 92.656; control2X: 70.092; control2Y: 89.056; x: 53.292; y: 77.856 }
+ PathCubic { control1X: 36.492; control1Y: 66.656; control2X: 60.492; control2Y: 96.256; x: 60.492; y: 96.256 }
+ PathCubic { control1X: 78.892; control1Y: 116.256; control2X: 44.492; control2Y: 99.456; x: 44.492; y: 99.456 }
+ PathCubic { control1X: 10.092; control1Y: 86.656; control2X: -13.908; control2Y: 112.256; x: -17.108; y: 113.056 }
+ PathCubic { control1X: -20.308; control1Y: 113.856; control2X: -25.108; control2Y: 117.056; x: -25.908; y: 110.656 }
+ PathCubic { control1X: -26.708; control1Y: 104.256; control2X: -32.905; control2Y: 89.232; x: -65.908; y: 113.856 }
+ PathCubic { control1X: -98.273; control1Y: 137.911; control2X: -108.982; control2Y: 121.365; x: -108.982; y: 121.365 }
+ PathLine { x: -115.782; y: 118.056 }
+ PathCubic { control1X: -128.582; control1Y: 94.856; control2X: -119.654; control2Y: 150.147; x: -119.654; y: 150.147 }
+ PathCubic { control1X: -110.854; control1Y: 184.547; control2X: 25.292; control2Y: 133.856; x: 25.292; y: 133.856 }
+ PathCubic { control1X: 25.292; control1Y: 133.856; control2X: 194.093; control2Y: 103.456; x: 205.293; y: 99.456 }
+ PathCubic { control1X: 216.493; control1Y: 95.456; control2X: 302.965; control2Y: 101.128; x: 302.965; y: 101.128 }
+ PathLine { x: 298.093; y: 79.237 }
+ PathCubic { control1X: 233.292; control1Y: 32.837; control2X: 222.093; control2Y: 61.856; x: 208.493; y: 57.856 }
+ PathCubic { control1X: 194.893; control1Y: 53.855; control2X: 197.293; control2Y: 63.456; x: 194.093; y: 64.256 }
+ PathCubic { control1X: 190.892; control1Y: 65.056; control2X: 151.692; control2Y: 40.255; x: 145.292; y: 41.055 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeWidth: -1
+ PathMove { x: -115.8; y: 119.601 }
+ PathCubic { control1X: -128.6; control1Y: 97.6; control2X: -119; control2Y: 153.201; x: -119; y: 153.201 }
+ PathCubic { control1X: -110.2; control1Y: 187.601; control2X: 26.6; control2Y: 135.601; x: 26.6; y: 135.601 }
+ PathCubic { control1X: 26.6; control1Y: 135.601; control2X: 195.401; control2Y: 105.2; x: 206.601; y: 101.2 }
+ PathCubic { control1X: 217.801; control1Y: 97.2; control2X: 303.401; control2Y: 102.8; x: 303.401; y: 102.8 }
+ PathLine { x: 298.601; y: 80.4 }
+ PathCubic { control1X: 233.801; control1Y: 34; control2X: 223.401; control2Y: 63.6; x: 209.801; y: 59.6 }
+ PathCubic { control1X: 196.201; control1Y: 55.6; control2X: 198.601; control2Y: 65.2; x: 195.401; y: 66 }
+ PathCubic { control1X: 192.201; control1Y: 66.8; control2X: 153.001; control2Y: 42; x: 146.601; y: 42.8 }
+ PathCubic { control1X: 140.201; control1Y: 43.6; control2X: 114.981; control2Y: 19.793; x: 129.801; y: 51.6 }
+ PathCubic { control1X: 152.028; control1Y: 99.307; control2X: 69.041; control2Y: 89.227; x: 54.6; y: 79.6 }
+ PathCubic { control1X: 37.8; control1Y: 68.4; control2X: 61.8; control2Y: 98; x: 61.8; y: 98 }
+ PathCubic { control1X: 80.2; control1Y: 118.001; control2X: 45.8; control2Y: 101.2; x: 45.8; y: 101.2 }
+ PathCubic { control1X: 11.4; control1Y: 88.4; control2X: -12.6; control2Y: 114.001; x: -15.8; y: 114.801 }
+ PathCubic { control1X: -19; control1Y: 115.601; control2X: -23.8; control2Y: 118.801; x: -24.6; y: 112.401 }
+ PathCubic { control1X: -25.4; control1Y: 106; control2X: -31.465; control2Y: 91.144; x: -64.6; y: 115.601 }
+ PathCubic { control1X: -98.2; control1Y: 140.401; control2X: -108.6; control2Y: 124.401; x: -108.6; y: 124.401 }
+ PathLine { x: -115.8; y: 119.601 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -74.2; y: 149.601 }
+ PathCubic { control1X: -74.2; control1Y: 149.601; control2X: -81.4; control2Y: 161.201; x: -60.6; y: 174.401 }
+ PathCubic { control1X: -60.6; control1Y: 174.401; control2X: -59.2; control2Y: 175.801; x: -77.2; y: 171.601 }
+ PathCubic { control1X: -77.2; control1Y: 171.601; control2X: -83.4; control2Y: 169.601; x: -85; y: 159.201 }
+ PathCubic { control1X: -85; control1Y: 159.201; control2X: -89.8; control2Y: 154.801; x: -94.6; y: 149.201 }
+ PathCubic { control1X: -99.4; control1Y: 143.601; control2X: -74.2; control2Y: 149.601; x: -74.2; y: 149.601 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: 65.8; y: 102 }
+ PathCubic { control1X: 65.8; control1Y: 102; control2X: 83.498; control2Y: 128.821; x: 82.9; y: 133.601 }
+ PathCubic { control1X: 81.6; control1Y: 144.001; control2X: 81.4; control2Y: 153.601; x: 84.6; y: 157.601 }
+ PathCubic { control1X: 87.801; control1Y: 161.601; control2X: 96.601; control2Y: 194.801; x: 96.601; y: 194.801 }
+ PathCubic { control1X: 96.601; control1Y: 194.801; control2X: 96.201; control2Y: 196.001; x: 108.601; y: 158.001 }
+ PathCubic { control1X: 108.601; control1Y: 158.001; control2X: 120.201; control2Y: 142.001; x: 100.201; y: 123.601 }
+ PathCubic { control1X: 100.201; control1Y: 123.601; control2X: 65; control2Y: 94.8; x: 65.8; y: 102 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -54.2; y: 176.401 }
+ PathCubic { control1X: -54.2; control1Y: 176.401; control2X: -43; control2Y: 183.601; x: -57.4; y: 214.801 }
+ PathLine { x: -51; y: 212.401 }
+ PathCubic { control1X: -51; control1Y: 212.401; control2X: -51.8; control2Y: 223.601; x: -55; y: 226.001 }
+ PathLine { x: -47.8; y: 222.801 }
+ PathCubic { control1X: -47.8; control1Y: 222.801; control2X: -43; control2Y: 230.801; x: -47; y: 235.601 }
+ PathCubic { control1X: -47; control1Y: 235.601; control2X: -30.2; control2Y: 243.601; x: -31; y: 250.001 }
+ PathCubic { control1X: -31; control1Y: 250.001; control2X: -24.6; control2Y: 242.001; x: -28.6; y: 235.601 }
+ PathCubic { control1X: -32.6; control1Y: 229.201; control2X: -39.8; control2Y: 233.201; x: -39; y: 214.801 }
+ PathLine { x: -47.8; y: 218.001 }
+ PathCubic { control1X: -47.8; control1Y: 218.001; control2X: -42.2; control2Y: 209.201; x: -42.2; y: 202.801 }
+ PathLine { x: -50.2; y: 205.201 }
+ PathCubic { control1X: -50.2; control1Y: 205.201; control2X: -34.731; control2Y: 178.623; x: -45.4; y: 177.201 }
+ PathCubic { control1X: -51.4; control1Y: 176.401; control2X: -54.2; control2Y: 176.401; x: -54.2; y: 176.401 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -21.8; y: 193.201 }
+ PathCubic { control1X: -21.8; control1Y: 193.201; control2X: -19; control2Y: 188.801; x: -21.8; y: 189.601 }
+ PathCubic { control1X: -24.6; control1Y: 190.401; control2X: -55.8; control2Y: 205.201; x: -61.8; y: 214.801 }
+ PathCubic { control1X: -61.8; control1Y: 214.801; control2X: -27.4; control2Y: 190.401; x: -21.8; y: 193.201 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -11.4; y: 201.201 }
+ PathCubic { control1X: -11.4; control1Y: 201.201; control2X: -8.6; control2Y: 196.801; x: -11.4; y: 197.601 }
+ PathCubic { control1X: -14.2; control1Y: 198.401; control2X: -45.4; control2Y: 213.201; x: -51.4; y: 222.801 }
+ PathCubic { control1X: -51.4; control1Y: 222.801; control2X: -17; control2Y: 198.401; x: -11.4; y: 201.201 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: 1.8; y: 186.001 }
+ PathCubic { control1X: 1.8; control1Y: 186.001; control2X: 4.6; control2Y: 181.601; x: 1.8; y: 182.401 }
+ PathCubic { control1X: -1; control1Y: 183.201; control2X: -32.2; control2Y: 198.001; x: -38.2; y: 207.601 }
+ PathCubic { control1X: -38.2; control1Y: 207.601; control2X: -3.8; control2Y: 183.201; x: 1.8; y: 186.001 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -21.4; y: 229.601 }
+ PathCubic { control1X: -21.4; control1Y: 229.601; control2X: -21.4; control2Y: 223.601; x: -24.2; y: 224.401 }
+ PathCubic { control1X: -27; control1Y: 225.201; control2X: -63; control2Y: 242.801; x: -69; y: 252.401 }
+ PathCubic { control1X: -69; control1Y: 252.401; control2X: -27; control2Y: 226.801; x: -21.4; y: 229.601 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -20.2; y: 218.801 }
+ PathCubic { control1X: -20.2; control1Y: 218.801; control2X: -19; control2Y: 214.001; x: -21.8; y: 214.801 }
+ PathCubic { control1X: -23.8; control1Y: 214.801; control2X: -50.2; control2Y: 226.401; x: -56.2; y: 236.001 }
+ PathCubic { control1X: -56.2; control1Y: 236.001; control2X: -26.6; control2Y: 214.401; x: -20.2; y: 218.801 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -34.6; y: 266.401 }
+ PathLine { x: -44.6; y: 274.001 }
+ PathCubic { control1X: -44.6; control1Y: 274.001; control2X: -34.2; control2Y: 266.401; x: -30.6; y: 267.601 }
+ PathCubic { control1X: -30.6; control1Y: 267.601; control2X: -37.4; control2Y: 278.801; x: -38.2; y: 284.001 }
+ PathCubic { control1X: -38.2; control1Y: 284.001; control2X: -27.8; control2Y: 271.201; x: -22.2; y: 271.601 }
+ PathCubic { control1X: -22.2; control1Y: 271.601; control2X: -14.6; control2Y: 272.001; x: -14.6; y: 282.801 }
+ PathCubic { control1X: -14.6; control1Y: 282.801; control2X: -9; control2Y: 272.401; x: -5.8; y: 272.801 }
+ PathCubic { control1X: -5.8; control1Y: 272.801; control2X: -4.6; control2Y: 279.201; x: -5.8; y: 286.001 }
+ PathCubic { control1X: -5.8; control1Y: 286.001; control2X: -1.8; control2Y: 278.401; x: 2.2; y: 280.001 }
+ PathCubic { control1X: 2.2; control1Y: 280.001; control2X: 8.6; control2Y: 278.001; x: 7.8; y: 289.601 }
+ PathCubic { control1X: 7.8; control1Y: 289.601; control2X: 7.8; control2Y: 300.001; x: 7; y: 302.801 }
+ PathCubic { control1X: 7; control1Y: 302.801; control2X: 12.6; control2Y: 276.401; x: 15; y: 276.001 }
+ PathCubic { control1X: 15; control1Y: 276.001; control2X: 23; control2Y: 274.801; x: 27.8; y: 283.601 }
+ PathCubic { control1X: 27.8; control1Y: 283.601; control2X: 23.8; control2Y: 276.001; x: 28.6; y: 278.001 }
+ PathCubic { control1X: 28.6; control1Y: 278.001; control2X: 39.4; control2Y: 279.601; x: 42.6; y: 286.401 }
+ PathCubic { control1X: 42.6; control1Y: 286.401; control2X: 35.8; control2Y: 274.401; x: 41.4; y: 277.601 }
+ PathCubic { control1X: 41.4; control1Y: 277.601; control2X: 48.2; control2Y: 277.601; x: 49.4; y: 284.001 }
+ PathCubic { control1X: 49.4; control1Y: 284.001; control2X: 57.8; control2Y: 305.201; x: 59.8; y: 306.801 }
+ PathCubic { control1X: 59.8; control1Y: 306.801; control2X: 52.2; control2Y: 285.201; x: 53.8; y: 285.201 }
+ PathCubic { control1X: 53.8; control1Y: 285.201; control2X: 51.8; control2Y: 273.201; x: 57; y: 288.001 }
+ PathCubic { control1X: 57; control1Y: 288.001; control2X: 53.8; control2Y: 274.001; x: 59.4; y: 274.801 }
+ PathCubic { control1X: 65; control1Y: 275.601; control2X: 69.4; control2Y: 285.601; x: 77.8; y: 283.201 }
+ PathCubic { control1X: 77.8; control1Y: 283.201; control2X: 87.401; control2Y: 288.801; x: 89.401; y: 219.601 }
+ PathLine { x: -34.6; y: 266.401 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -29.8; y: 173.601 }
+ PathCubic { control1X: -29.8; control1Y: 173.601; control2X: -15; control2Y: 167.601; x: 25; y: 173.601 }
+ PathCubic { control1X: 25; control1Y: 173.601; control2X: 32.2; control2Y: 174.001; x: 39; y: 165.201 }
+ PathCubic { control1X: 45.8; control1Y: 156.401; control2X: 72.6; control2Y: 149.201; x: 79; y: 151.201 }
+ PathLine { x: 88.601; y: 157.601 }
+ PathLine { x: 89.401; y: 158.801 }
+ PathCubic { control1X: 89.401; control1Y: 158.801; control2X: 101.801; control2Y: 169.201; x: 102.201; y: 176.801 }
+ PathCubic { control1X: 102.601; control1Y: 184.401; control2X: 87.801; control2Y: 232.401; x: 78.2; y: 248.401 }
+ PathCubic { control1X: 68.6; control1Y: 264.401; control2X: 59; control2Y: 276.801; x: 39.8; y: 274.401 }
+ PathCubic { control1X: 39.8; control1Y: 274.401; control2X: 19; control2Y: 270.401; x: -6.6; y: 274.401 }
+ PathCubic { control1X: -6.6; control1Y: 274.401; control2X: -35.8; control2Y: 272.801; x: -38.6; y: 264.801 }
+ PathCubic { control1X: -41.4; control1Y: 256.801; control2X: -27.4; control2Y: 241.601; x: -27.4; y: 241.601 }
+ PathCubic { control1X: -27.4; control1Y: 241.601; control2X: -23; control2Y: 233.201; x: -24.2; y: 218.801 }
+ PathCubic { control1X: -25.4; control1Y: 204.401; control2X: -25; control2Y: 176.401; x: -29.8; y: 173.601 }
+ }
+
+ ShapePath {
+ fillColor: "#e5668c"
+ strokeWidth: -1
+ PathMove { x: -7.8; y: 175.601 }
+ PathCubic { control1X: 0.6; control1Y: 194.001; control2X: -29; control2Y: 259.201; x: -29; y: 259.201 }
+ PathCubic { control1X: -31; control1Y: 260.801; control2X: -16.34; control2Y: 266.846; x: -6.2; y: 264.401 }
+ PathCubic { control1X: 4.746; control1Y: 261.763; control2X: 45; control2Y: 266.001; x: 45; y: 266.001 }
+ PathCubic { control1X: 68.6; control1Y: 250.401; control2X: 81.4; control2Y: 206.001; x: 81.4; y: 206.001 }
+ PathCubic { control1X: 81.4; control1Y: 206.001; control2X: 91.801; control2Y: 182.001; x: 74.2; y: 178.801 }
+ PathCubic { control1X: 56.6; control1Y: 175.601; control2X: -7.8; control2Y: 175.601; x: -7.8; y: 175.601 }
+ }
+
+ ShapePath {
+ fillColor: "#b23259"
+ strokeWidth: -1
+ PathMove { x: -9.831; y: 206.497 }
+ PathCubic { control1X: -6.505; control1Y: 193.707; control2X: -4.921; control2Y: 181.906; x: -7.8; y: 175.601 }
+ PathCubic { control1X: -7.8; control1Y: 175.601; control2X: 54.6; control2Y: 182.001; x: 65.8; y: 161.201 }
+ PathCubic { control1X: 70.041; control1Y: 153.326; control2X: 84.801; control2Y: 184.001; x: 84.4; y: 193.601 }
+ PathCubic { control1X: 84.4; control1Y: 193.601; control2X: 21.4; control2Y: 208.001; x: 6.6; y: 196.801 }
+ PathLine { x: -9.831; y: 206.497 }
+ }
+
+ ShapePath {
+ fillColor: "#a5264c"
+ strokeWidth: -1
+ PathMove { x: -5.4; y: 222.801 }
+ PathCubic { control1X: -5.4; control1Y: 222.801; control2X: -3.4; control2Y: 230.001; x: -5.8; y: 234.001 }
+ PathCubic { control1X: -5.8; control1Y: 234.001; control2X: -7.4; control2Y: 234.801; x: -8.6; y: 235.201 }
+ PathCubic { control1X: -8.6; control1Y: 235.201; control2X: -7.4; control2Y: 238.801; x: -1.4; y: 240.401 }
+ PathCubic { control1X: -1.4; control1Y: 240.401; control2X: 0.6; control2Y: 244.801; x: 3; y: 245.201 }
+ PathCubic { control1X: 5.4; control1Y: 245.601; control2X: 10.2; control2Y: 251.201; x: 14.2; y: 250.001 }
+ PathCubic { control1X: 18.2; control1Y: 248.801; control2X: 29.4; control2Y: 244.801; x: 29.4; y: 244.801 }
+ PathCubic { control1X: 29.4; control1Y: 244.801; control2X: 35; control2Y: 241.601; x: 43.8; y: 245.201 }
+ PathCubic { control1X: 43.8; control1Y: 245.201; control2X: 46.175; control2Y: 244.399; x: 46.6; y: 240.401 }
+ PathCubic { control1X: 47.1; control1Y: 235.701; control2X: 50.2; control2Y: 232.001; x: 52.2; y: 230.001 }
+ PathCubic { control1X: 54.2; control1Y: 228.001; control2X: 63.8; control2Y: 215.201; x: 62.6; y: 214.801 }
+ PathCubic { control1X: 61.4; control1Y: 214.401; control2X: -5.4; control2Y: 222.801; x: -5.4; y: 222.801 }
+ }
+
+ ShapePath {
+ fillColor: "#ff727f"
+ strokeColor: "#000000"
+ strokeWidth: 1
+ PathMove { x: -9.8; y: 174.401 }
+ PathCubic { control1X: -9.8; control1Y: 174.401; control2X: -12.6; control2Y: 196.801; x: -9.4; y: 205.201 }
+ PathCubic { control1X: -6.2; control1Y: 213.601; control2X: -7; control2Y: 215.601; x: -7.8; y: 219.601 }
+ PathCubic { control1X: -8.6; control1Y: 223.601; control2X: -4.2; control2Y: 233.601; x: 1.4; y: 239.601 }
+ PathLine { x: 13.4; y: 241.201 }
+ PathCubic { control1X: 13.4; control1Y: 241.201; control2X: 28.6; control2Y: 237.601; x: 37.8; y: 240.401 }
+ PathCubic { control1X: 37.8; control1Y: 240.401; control2X: 46.794; control2Y: 241.744; x: 50.2; y: 226.801 }
+ PathCubic { control1X: 50.2; control1Y: 226.801; control2X: 55; control2Y: 220.401; x: 62.2; y: 217.601 }
+ PathCubic { control1X: 69.4; control1Y: 214.801; control2X: 76.6; control2Y: 173.201; x: 72.6; y: 165.201 }
+ PathCubic { control1X: 68.6; control1Y: 157.201; control2X: 54.2; control2Y: 152.801; x: 38.2; y: 168.401 }
+ PathCubic { control1X: 22.2; control1Y: 184.001; control2X: 20.2; control2Y: 167.201; x: -9.8; y: 174.401 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffcc"
+ strokeColor: "#000000"
+ strokeWidth: 0.5
+ PathMove { x: -8.2; y: 249.201 }
+ PathCubic { control1X: -8.2; control1Y: 249.201; control2X: -9; control2Y: 247.201; x: -13.4; y: 246.801 }
+ PathCubic { control1X: -13.4; control1Y: 246.801; control2X: -35.8; control2Y: 243.201; x: -44.2; y: 230.801 }
+ PathCubic { control1X: -44.2; control1Y: 230.801; control2X: -51; control2Y: 225.201; x: -46.6; y: 236.801 }
+ PathCubic { control1X: -46.6; control1Y: 236.801; control2X: -36.2; control2Y: 257.201; x: -29.4; y: 260.001 }
+ PathCubic { control1X: -29.4; control1Y: 260.001; control2X: -13; control2Y: 264.001; x: -8.2; y: 249.201 }
+ }
+
+ ShapePath {
+ fillColor: "#cc3f4c"
+ strokeWidth: -1
+ PathMove { x: 71.742; y: 185.229 }
+ PathCubic { control1X: 72.401; control1Y: 177.323; control2X: 74.354; control2Y: 168.709; x: 72.6; y: 165.201 }
+ PathCubic { control1X: 66.154; control1Y: 152.307; control2X: 49.181; control2Y: 157.695; x: 38.2; y: 168.401 }
+ PathCubic { control1X: 22.2; control1Y: 184.001; control2X: 20.2; control2Y: 167.201; x: -9.8; y: 174.401 }
+ PathCubic { control1X: -9.8; control1Y: 174.401; control2X: -11.545; control2Y: 188.364; x: -10.705; y: 198.376 }
+ PathCubic { control1X: -10.705; control1Y: 198.376; control2X: 26.6; control2Y: 186.801; x: 27.4; y: 192.401 }
+ PathCubic { control1X: 27.4; control1Y: 192.401; control2X: 29; control2Y: 189.201; x: 38.2; y: 189.201 }
+ PathCubic { control1X: 47.4; control1Y: 189.201; control2X: 70.142; control2Y: 188.029; x: 71.742; y: 185.229 }
+ }
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: "#a51926"
+ strokeWidth: 2
+ PathMove { x: 28.6; y: 175.201 }
+ PathCubic { control1X: 28.6; control1Y: 175.201; control2X: 33.4; control2Y: 180.001; x: 29.8; y: 189.601 }
+ PathCubic { control1X: 29.8; control1Y: 189.601; control2X: 15.4; control2Y: 205.601; x: 17.4; y: 219.601 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffcc"
+ strokeColor: "#000000"
+ strokeWidth: 0.5
+ PathMove { x: -19.4; y: 260.001 }
+ PathCubic { control1X: -19.4; control1Y: 260.001; control2X: -23.8; control2Y: 247.201; x: -15; y: 254.001 }
+ PathCubic { control1X: -15; control1Y: 254.001; control2X: -10.2; control2Y: 256.001; x: -11.4; y: 257.601 }
+ PathCubic { control1X: -12.6; control1Y: 259.201; control2X: -18.2; control2Y: 263.201; x: -19.4; y: 260.001 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffcc"
+ strokeColor: "#000000"
+ strokeWidth: 0.5
+ PathMove { x: -14.36; y: 261.201 }
+ PathCubic { control1X: -14.36; control1Y: 261.201; control2X: -17.88; control2Y: 250.961; x: -10.84; y: 256.401 }
+ PathCubic { control1X: -10.84; control1Y: 256.401; control2X: -6.419; control2Y: 258.849; x: -7.96; y: 259.281 }
+ PathCubic { control1X: -12.52; control1Y: 260.561; control2X: -7.96; control2Y: 263.121; x: -14.36; y: 261.201 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffcc"
+ strokeColor: "#000000"
+ strokeWidth: 0.5
+ PathMove { x: -9.56; y: 261.201 }
+ PathCubic { control1X: -9.56; control1Y: 261.201; control2X: -13.08; control2Y: 250.961; x: -6.04; y: 256.401 }
+ PathCubic { control1X: -6.04; control1Y: 256.401; control2X: -1.665; control2Y: 258.711; x: -3.16; y: 259.281 }
+ PathCubic { control1X: -6.52; control1Y: 260.561; control2X: -3.16; control2Y: 263.121; x: -9.56; y: 261.201 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffcc"
+ strokeColor: "#000000"
+ strokeWidth: 0.5
+ PathMove { x: -2.96; y: 261.401 }
+ PathCubic { control1X: -2.96; control1Y: 261.401; control2X: -6.48; control2Y: 251.161; x: 0.56; y: 256.601 }
+ PathCubic { control1X: 0.56; control1Y: 256.601; control2X: 4.943; control2Y: 258.933; x: 3.441; y: 259.481 }
+ PathCubic { control1X: 0.48; control1Y: 260.561; control2X: 3.441; control2Y: 263.321; x: -2.96; y: 261.401 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffcc"
+ strokeColor: "#000000"
+ strokeWidth: 0.5
+ PathMove { x: 3.52; y: 261.321 }
+ PathCubic { control1X: 3.52; control1Y: 261.321; control2X: 0; control2Y: 251.081; x: 7.041; y: 256.521 }
+ PathCubic { control1X: 7.041; control1Y: 256.521; control2X: 10.881; control2Y: 258.121; x: 9.921; y: 259.401 }
+ PathCubic { control1X: 8.961; control1Y: 260.681; control2X: 9.921; control2Y: 263.241; x: 3.52; y: 261.321 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffcc"
+ strokeColor: "#000000"
+ strokeWidth: 0.5
+ PathMove { x: 10.2; y: 262.001 }
+ PathCubic { control1X: 10.2; control1Y: 262.001; control2X: 5.4; control2Y: 249.601; x: 14.6; y: 256.001 }
+ PathCubic { control1X: 14.6; control1Y: 256.001; control2X: 19.4; control2Y: 258.001; x: 18.2; y: 259.601 }
+ PathCubic { control1X: 17; control1Y: 261.201; control2X: 18.2; control2Y: 264.401; x: 10.2; y: 262.001 }
+ }
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: "#a5264c"
+ strokeWidth: 2
+ PathMove { x: -18.2; y: 244.801 }
+ PathCubic { control1X: -18.2; control1Y: 244.801; control2X: -5; control2Y: 242.001; x: 1; y: 245.201 }
+ PathCubic { control1X: 1; control1Y: 245.201; control2X: 7; control2Y: 246.401; x: 8.2; y: 246.001 }
+ PathCubic { control1X: 9.4; control1Y: 245.601; control2X: 12.6; control2Y: 245.201; x: 12.6; y: 245.201 }
+ }
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: "#a5264c"
+ strokeWidth: 2
+ PathMove { x: 15.8; y: 253.601 }
+ PathCubic { control1X: 15.8; control1Y: 253.601; control2X: 27.8; control2Y: 240.001; x: 39.8; y: 244.401 }
+ PathCubic { control1X: 46.816; control1Y: 246.974; control2X: 45.8; control2Y: 243.601; x: 46.6; y: 240.801 }
+ PathCubic { control1X: 47.4; control1Y: 238.001; control2X: 47.6; control2Y: 233.801; x: 52.6; y: 230.801 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffcc"
+ strokeColor: "#000000"
+ strokeWidth: 0.5
+ PathMove { x: 33; y: 237.601 }
+ PathCubic { control1X: 33; control1Y: 237.601; control2X: 29; control2Y: 226.801; x: 26.2; y: 239.601 }
+ PathCubic { control1X: 23.4; control1Y: 252.401; control2X: 20.2; control2Y: 256.001; x: 18.6; y: 258.801 }
+ PathCubic { control1X: 18.6; control1Y: 258.801; control2X: 18.6; control2Y: 264.001; x: 27; y: 263.601 }
+ PathCubic { control1X: 27; control1Y: 263.601; control2X: 37.8; control2Y: 263.201; x: 38.2; y: 260.401 }
+ PathCubic { control1X: 38.6; control1Y: 257.601; control2X: 37; control2Y: 246.001; x: 33; y: 237.601 }
+ }
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: "#a5264c"
+ strokeWidth: 2
+ PathMove { x: 47; y: 244.801 }
+ PathCubic { control1X: 47; control1Y: 244.801; control2X: 50.6; control2Y: 242.401; x: 53; y: 243.601 }
+ }
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: "#a5264c"
+ strokeWidth: 2
+ PathMove { x: 53.5; y: 228.401 }
+ PathCubic { control1X: 53.5; control1Y: 228.401; control2X: 56.4; control2Y: 223.501; x: 61.2; y: 222.701 }
+ }
+
+ ShapePath {
+ fillColor: "#b2b2b2"
+ strokeWidth: -1
+ PathMove { x: -25.8; y: 265.201 }
+ PathCubic { control1X: -25.8; control1Y: 265.201; control2X: -7.8; control2Y: 268.401; x: -3.4; y: 266.801 }
+ PathCubic { control1X: -3.4; control1Y: 266.801; control2X: 5.4; control2Y: 266.801; x: -3; y: 268.801 }
+ PathCubic { control1X: -3; control1Y: 268.801; control2X: -15.8; control2Y: 268.801; x: -23.8; y: 267.601 }
+ PathCubic { control1X: -23.8; control1Y: 267.601; control2X: -35.4; control2Y: 262.001; x: -25.8; y: 265.201 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffcc"
+ strokeColor: "#000000"
+ strokeWidth: 0.5
+ PathMove { x: -11.8; y: 172.001 }
+ PathCubic { control1X: -11.8; control1Y: 172.001; control2X: 5.8; control2Y: 172.001; x: 7.8; y: 172.801 }
+ PathCubic { control1X: 7.8; control1Y: 172.801; control2X: 15; control2Y: 203.601; x: 11.4; y: 211.201 }
+ PathCubic { control1X: 11.4; control1Y: 211.201; control2X: 10.2; control2Y: 214.001; x: 7.4; y: 208.401 }
+ PathCubic { control1X: 7.4; control1Y: 208.401; control2X: -11; control2Y: 175.601; x: -14.2; y: 173.601 }
+ PathCubic { control1X: -17.4; control1Y: 171.601; control2X: -13; control2Y: 172.001; x: -11.8; y: 172.001 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffcc"
+ strokeColor: "#000000"
+ strokeWidth: 0.5
+ PathMove { x: -88.9; y: 169.301 }
+ PathCubic { control1X: -88.9; control1Y: 169.301; control2X: -80; control2Y: 171.001; x: -67.4; y: 173.601 }
+ PathCubic { control1X: -67.4; control1Y: 173.601; control2X: -62.6; control2Y: 196.001; x: -59.4; y: 200.801 }
+ PathCubic { control1X: -56.2; control1Y: 205.601; control2X: -59.8; control2Y: 205.601; x: -63.4; y: 202.801 }
+ PathCubic { control1X: -67; control1Y: 200.001; control2X: -81.8; control2Y: 186.001; x: -83.8; y: 181.601 }
+ PathCubic { control1X: -85.8; control1Y: 177.201; control2X: -88.9; control2Y: 169.301; x: -88.9; y: 169.301 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffcc"
+ strokeColor: "#000000"
+ strokeWidth: 0.5
+ PathMove { x: -67.039; y: 173.818 }
+ PathCubic { control1X: -67.039; control1Y: 173.818; control2X: -61.239; control2Y: 175.366; x: -60.23; y: 177.581 }
+ PathCubic { control1X: -59.222; control1Y: 179.795; control2X: -61.432; control2Y: 183.092; x: -61.432; y: 183.092 }
+ PathCubic { control1X: -61.432; control1Y: 183.092; control2X: -62.432; control2Y: 186.397; x: -63.634; y: 184.235 }
+ PathCubic { control1X: -64.836; control1Y: 182.072; control2X: -67.708; control2Y: 174.412; x: -67.039; y: 173.818 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -67; y: 173.601 }
+ PathCubic { control1X: -67; control1Y: 173.601; control2X: -63.4; control2Y: 178.801; x: -59.8; y: 178.801 }
+ PathCubic { control1X: -56.2; control1Y: 178.801; control2X: -55.818; control2Y: 178.388; x: -53; y: 179.001 }
+ PathCubic { control1X: -48.4; control1Y: 180.001; control2X: -48.8; control2Y: 178.001; x: -42.2; y: 179.201 }
+ PathCubic { control1X: -39.56; control1Y: 179.681; control2X: -37; control2Y: 178.801; x: -34.2; y: 180.001 }
+ PathCubic { control1X: -31.4; control1Y: 181.201; control2X: -28.2; control2Y: 180.401; x: -27; y: 178.401 }
+ PathCubic { control1X: -25.8; control1Y: 176.401; control2X: -21; control2Y: 172.201; x: -21; y: 172.201 }
+ PathCubic { control1X: -21; control1Y: 172.201; control2X: -33.8; control2Y: 174.001; x: -36.6; y: 174.801 }
+ PathCubic { control1X: -36.6; control1Y: 174.801; control2X: -59; control2Y: 176.001; x: -67; y: 173.601 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffcc"
+ strokeColor: "#000000"
+ strokeWidth: 0.5
+ PathMove { x: -22.4; y: 173.801 }
+ PathCubic { control1X: -22.4; control1Y: 173.801; control2X: -28.85; control2Y: 177.301; x: -29.25; y: 179.701 }
+ PathCubic { control1X: -29.65; control1Y: 182.101; control2X: -24; control2Y: 185.801; x: -24; y: 185.801 }
+ PathCubic { control1X: -24; control1Y: 185.801; control2X: -21.25; control2Y: 190.401; x: -20.65; y: 188.001 }
+ PathCubic { control1X: -20.05; control1Y: 185.601; control2X: -21.6; control2Y: 174.201; x: -22.4; y: 173.801 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffcc"
+ strokeColor: "#000000"
+ strokeWidth: 0.5
+ PathMove { x: -59.885; y: 179.265 }
+ PathCubic { control1X: -59.885; control1Y: 179.265; control2X: -52.878; control2Y: 190.453; x: -52.661; y: 179.242 }
+ PathCubic { control1X: -52.661; control1Y: 179.242; control2X: -52.104; control2Y: 177.984; x: -53.864; y: 177.962 }
+ PathCubic { control1X: -59.939; control1Y: 177.886; control2X: -58.418; control2Y: 173.784; x: -59.885; y: 179.265 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffcc"
+ strokeColor: "#000000"
+ strokeWidth: 0.5
+ PathMove { x: -52.707; y: 179.514 }
+ PathCubic { control1X: -52.707; control1Y: 179.514; control2X: -44.786; control2Y: 190.701; x: -45.422; y: 179.421 }
+ PathCubic { control1X: -45.422; control1Y: 179.421; control2X: -45.415; control2Y: 179.089; x: -47.168; y: 178.936 }
+ PathCubic { control1X: -51.915; control1Y: 178.522; control2X: -51.57; control2Y: 174.004; x: -52.707; y: 179.514 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffcc"
+ strokeColor: "#000000"
+ strokeWidth: 0.5
+ PathMove { x: -45.494; y: 179.522 }
+ PathCubic { control1X: -45.494; control1Y: 179.522; control2X: -37.534; control2Y: 190.15; x: -38.203; y: 180.484 }
+ PathCubic { control1X: -38.203; control1Y: 180.484; control2X: -38.084; control2Y: 179.251; x: -39.738; y: 178.95 }
+ PathCubic { control1X: -43.63; control1Y: 178.244; control2X: -43.841; control2Y: 174.995; x: -45.494; y: 179.522 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffcc"
+ strokeColor: "#000000"
+ strokeWidth: 0.5
+ PathMove { x: -38.618; y: 179.602 }
+ PathCubic { control1X: -38.618; control1Y: 179.602; control2X: -30.718; control2Y: 191.163; x: -30.37; y: 181.382 }
+ PathCubic { control1X: -30.37; control1Y: 181.382; control2X: -28.726; control2Y: 180.004; x: -30.472; y: 179.782 }
+ PathCubic { control1X: -36.29; control1Y: 179.042; control2X: -35.492; control2Y: 174.588; x: -38.618; y: 179.602 }
+ }
+
+ ShapePath {
+ fillColor: "#e5e5b2"
+ strokeWidth: -1
+ PathMove { x: -74.792; y: 183.132 }
+ PathLine { x: -82.45; y: 181.601 }
+ PathCubic { control1X: -85.05; control1Y: 176.601; control2X: -87.15; control2Y: 170.451; x: -87.15; y: 170.451 }
+ PathCubic { control1X: -87.15; control1Y: 170.451; control2X: -80.8; control2Y: 171.451; x: -68.3; y: 174.251 }
+ PathCubic { control1X: -68.3; control1Y: 174.251; control2X: -67.424; control2Y: 177.569; x: -65.952; y: 183.364 }
+ PathLine { x: -74.792; y: 183.132 }
+ }
+
+ ShapePath {
+ fillColor: "#e5e5b2"
+ strokeWidth: -1
+ PathMove { x: -9.724; y: 178.47 }
+ PathCubic { control1X: -11.39; control1Y: 175.964; control2X: -12.707; control2Y: 174.206; x: -13.357; y: 173.8 }
+ PathCubic { control1X: -16.37; control1Y: 171.917; control2X: -12.227; control2Y: 172.294; x: -11.098; y: 172.294 }
+ PathCubic { control1X: -11.098; control1Y: 172.294; control2X: 5.473; control2Y: 172.294; x: 7.356; y: 173.047 }
+ PathCubic { control1X: 7.356; control1Y: 173.047; control2X: 7.88; control2Y: 175.289; x: 8.564; y: 178.68 }
+ PathCubic { control1X: 8.564; control1Y: 178.68; control2X: -1.524; control2Y: 176.67; x: -9.724; y: 178.47 }
+ }
+
+ ShapePath {
+ fillColor: "#cc7226"
+ strokeWidth: -1
+ PathMove { x: 43.88; y: 40.321 }
+ PathCubic { control1X: 71.601; control1Y: 44.281; control2X: 97.121; control2Y: 8.641; x: 98.881; y: -1.04 }
+ PathCubic { control1X: 100.641; control1Y: -10.72; control2X: 90.521; control2Y: -22.6; x: 90.521; y: -22.6 }
+ PathCubic { control1X: 91.841; control1Y: -25.68; control2X: 87.001; control2Y: -39.76; x: 81.721; y: -49 }
+ PathCubic { control1X: 76.441; control1Y: -58.24; control2X: 60.54; control2Y: -57.266; x: 43; y: -58.24 }
+ PathCubic { control1X: 27.16; control1Y: -59.12; control2X: 8.68; control2Y: -35.8; x: 7.36; y: -34.04 }
+ PathCubic { control1X: 6.04; control1Y: -32.28; control2X: 12.2; control2Y: 6.001; x: 13.52; y: 11.721 }
+ PathCubic { control1X: 14.84; control1Y: 17.441; control2X: 12.2; control2Y: 43.841; x: 12.2; y: 43.841 }
+ PathCubic { control1X: 46.44; control1Y: 34.741; control2X: 16.16; control2Y: 36.361; x: 43.88; y: 40.321 }
+ }
+
+ ShapePath {
+ fillColor: "#ea8e51"
+ strokeWidth: -1
+ PathMove { x: 8.088; y: -33.392 }
+ PathCubic { control1X: 6.792; control1Y: -31.664; control2X: 12.84; control2Y: 5.921; x: 14.136; y: 11.537 }
+ PathCubic { control1X: 15.432; control1Y: 17.153; control2X: 12.84; control2Y: 43.073; x: 12.84; y: 43.073 }
+ PathCubic { control1X: 45.512; control1Y: 34.193; control2X: 16.728; control2Y: 35.729; x: 43.944; y: 39.617 }
+ PathCubic { control1X: 71.161; control1Y: 43.505; control2X: 96.217; control2Y: 8.513; x: 97.945; y: -0.992 }
+ PathCubic { control1X: 99.673; control1Y: -10.496; control2X: 89.737; control2Y: -22.16; x: 89.737; y: -22.16 }
+ PathCubic { control1X: 91.033; control1Y: -25.184; control2X: 86.281; control2Y: -39.008; x: 81.097; y: -48.08 }
+ PathCubic { control1X: 75.913; control1Y: -57.152; control2X: 60.302; control2Y: -56.195; x: 43.08; y: -57.152 }
+ PathCubic { control1X: 27.528; control1Y: -58.016; control2X: 9.384; control2Y: -35.12; x: 8.088; y: -33.392 }
+ }
+
+ ShapePath {
+ fillColor: "#efaa7c"
+ strokeWidth: -1
+ PathMove { x: 8.816; y: -32.744 }
+ PathCubic { control1X: 7.544; control1Y: -31.048; control2X: 13.48; control2Y: 5.841; x: 14.752; y: 11.353 }
+ PathCubic { control1X: 16.024; control1Y: 16.865; control2X: 13.48; control2Y: 42.305; x: 13.48; y: 42.305 }
+ PathCubic { control1X: 44.884; control1Y: 33.145; control2X: 17.296; control2Y: 35.097; x: 44.008; y: 38.913 }
+ PathCubic { control1X: 70.721; control1Y: 42.729; control2X: 95.313; control2Y: 8.385; x: 97.009; y: -0.944 }
+ PathCubic { control1X: 98.705; control1Y: -10.272; control2X: 88.953; control2Y: -21.72; x: 88.953; y: -21.72 }
+ PathCubic { control1X: 90.225; control1Y: -24.688; control2X: 85.561; control2Y: -38.256; x: 80.473; y: -47.16 }
+ PathCubic { control1X: 75.385; control1Y: -56.064; control2X: 60.063; control2Y: -55.125; x: 43.16; y: -56.064 }
+ PathCubic { control1X: 27.896; control1Y: -56.912; control2X: 10.088; control2Y: -34.44; x: 8.816; y: -32.744 }
+ }
+
+ ShapePath {
+ fillColor: "#f4c6a8"
+ strokeWidth: -1
+ PathMove { x: 9.544; y: -32.096 }
+ PathCubic { control1X: 8.296; control1Y: -30.432; control2X: 14.12; control2Y: 5.761; x: 15.368; y: 11.169 }
+ PathCubic { control1X: 16.616; control1Y: 16.577; control2X: 14.12; control2Y: 41.537; x: 14.12; y: 41.537 }
+ PathCubic { control1X: 43.556; control1Y: 32.497; control2X: 17.864; control2Y: 34.465; x: 44.072; y: 38.209 }
+ PathCubic { control1X: 70.281; control1Y: 41.953; control2X: 94.409; control2Y: 8.257; x: 96.073; y: -0.895 }
+ PathCubic { control1X: 97.737; control1Y: -10.048; control2X: 88.169; control2Y: -21.28; x: 88.169; y: -21.28 }
+ PathCubic { control1X: 89.417; control1Y: -24.192; control2X: 84.841; control2Y: -37.504; x: 79.849; y: -46.24 }
+ PathCubic { control1X: 74.857; control1Y: -54.976; control2X: 59.824; control2Y: -54.055; x: 43.24; y: -54.976 }
+ PathCubic { control1X: 28.264; control1Y: -55.808; control2X: 10.792; control2Y: -33.76; x: 9.544; y: -32.096 }
+ }
+
+ ShapePath {
+ fillColor: "#f9e2d3"
+ strokeWidth: -1
+ PathMove { x: 10.272; y: -31.448 }
+ PathCubic { control1X: 9.048; control1Y: -29.816; control2X: 14.76; control2Y: 5.681; x: 15.984; y: 10.985 }
+ PathCubic { control1X: 17.208; control1Y: 16.289; control2X: 14.76; control2Y: 40.769; x: 14.76; y: 40.769 }
+ PathCubic { control1X: 42.628; control1Y: 31.849; control2X: 18.432; control2Y: 33.833; x: 44.136; y: 37.505 }
+ PathCubic { control1X: 69.841; control1Y: 41.177; control2X: 93.505; control2Y: 8.129; x: 95.137; y: -0.848 }
+ PathCubic { control1X: 96.769; control1Y: -9.824; control2X: 87.385; control2Y: -20.84; x: 87.385; y: -20.84 }
+ PathCubic { control1X: 88.609; control1Y: -23.696; control2X: 84.121; control2Y: -36.752; x: 79.225; y: -45.32 }
+ PathCubic { control1X: 74.329; control1Y: -53.888; control2X: 59.585; control2Y: -52.985; x: 43.32; y: -53.888 }
+ PathCubic { control1X: 28.632; control1Y: -54.704; control2X: 11.496; control2Y: -33.08; x: 10.272; y: -31.448 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeWidth: -1
+ PathMove { x: 44.2; y: 36.8 }
+ PathCubic { control1X: 69.4; control1Y: 40.4; control2X: 92.601; control2Y: 8; x: 94.201; y: -0.8 }
+ PathCubic { control1X: 95.801; control1Y: -9.6; control2X: 86.601; control2Y: -20.4; x: 86.601; y: -20.4 }
+ PathCubic { control1X: 87.801; control1Y: -23.2; control2X: 83.4; control2Y: -36; x: 78.6; y: -44.4 }
+ PathCubic { control1X: 73.8; control1Y: -52.8; control2X: 59.346; control2Y: -51.914; x: 43.4; y: -52.8 }
+ PathCubic { control1X: 29; control1Y: -53.6; control2X: 12.2; control2Y: -32.4; x: 11; y: -30.8 }
+ PathCubic { control1X: 9.8; control1Y: -29.2; control2X: 15.4; control2Y: 5.6; x: 16.6; y: 10.8 }
+ PathCubic { control1X: 17.8; control1Y: 16; control2X: 15.4; control2Y: 40; x: 15.4; y: 40 }
+ PathCubic { control1X: 40.9; control1Y: 31.4; control2X: 19; control2Y: 33.2; x: 44.2; y: 36.8 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: 90.601; y: 2.8 }
+ PathCubic { control1X: 90.601; control1Y: 2.8; control2X: 62.8; control2Y: 10.4; x: 51.2; y: 8.8 }
+ PathCubic { control1X: 51.2; control1Y: 8.8; control2X: 35.4; control2Y: 2.2; x: 26.6; y: 24 }
+ PathCubic { control1X: 26.6; control1Y: 24; control2X: 23; control2Y: 31.2; x: 21; y: 33.2 }
+ PathCubic { control1X: 19; control1Y: 35.2; control2X: 90.601; control2Y: 2.8; x: 90.601; y: 2.8 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 94.401; y: 0.6 }
+ PathCubic { control1X: 94.401; control1Y: 0.6; control2X: 65.4; control2Y: 12.8; x: 55.4; y: 12.4 }
+ PathCubic { control1X: 55.4; control1Y: 12.4; control2X: 39; control2Y: 7.8; x: 30.6; y: 22.4 }
+ PathCubic { control1X: 30.6; control1Y: 22.4; control2X: 22.2; control2Y: 31.6; x: 19; y: 33.2 }
+ PathCubic { control1X: 19; control1Y: 33.2; control2X: 18.6; control2Y: 34.8; x: 25; y: 30.8 }
+ PathLine { x: 35.4; y: 36 }
+ PathCubic { control1X: 35.4; control1Y: 36; control2X: 50.2; control2Y: 45.6; x: 59.8; y: 29.6 }
+ PathCubic { control1X: 59.8; control1Y: 29.6; control2X: 63.8; control2Y: 18.4; x: 63.8; y: 16.4 }
+ PathCubic { control1X: 63.8; control1Y: 14.4; control2X: 85; control2Y: 8.8; x: 86.601; y: 8.4 }
+ PathCubic { control1X: 88.201; control1Y: 8; control2X: 94.801; control2Y: 3.8; x: 94.401; y: 0.6 }
+ }
+
+ ShapePath {
+ fillColor: "#99cc32"
+ strokeWidth: -1
+ PathMove { x: 47; y: 36.514 }
+ PathCubic { control1X: 40.128; control1Y: 36.514; control2X: 31.755; control2Y: 32.649; x: 31.755; y: 26.4 }
+ PathCubic { control1X: 31.755; control1Y: 20.152; control2X: 40.128; control2Y: 13.887; x: 47; y: 13.887 }
+ PathCubic { control1X: 53.874; control1Y: 13.887; control2X: 59.446; control2Y: 18.952; x: 59.446; y: 25.2 }
+ PathCubic { control1X: 59.446; control1Y: 31.449; control2X: 53.874; control2Y: 36.514; x: 47; y: 36.514 }
+ }
+
+ ShapePath {
+ fillColor: "#659900"
+ strokeWidth: -1
+ PathMove { x: 43.377; y: 19.83 }
+ PathCubic { control1X: 38.531; control1Y: 20.552; control2X: 33.442; control2Y: 22.055; x: 33.514; y: 21.839 }
+ PathCubic { control1X: 35.054; control1Y: 17.22; control2X: 41.415; control2Y: 13.887; x: 47; y: 13.887 }
+ PathCubic { control1X: 51.296; control1Y: 13.887; control2X: 55.084; control2Y: 15.865; x: 57.32; y: 18.875 }
+ PathCubic { control1X: 57.32; control1Y: 18.875; control2X: 52.004; control2Y: 18.545; x: 43.377; y: 19.83 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeWidth: -1
+ PathMove { x: 55.4; y: 19.6 }
+ PathCubic { control1X: 55.4; control1Y: 19.6; control2X: 51; control2Y: 16.4; x: 51; y: 18.6 }
+ PathCubic { control1X: 51; control1Y: 18.6; control2X: 54.6; control2Y: 23; x: 55.4; y: 19.6 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 45.4; y: 27.726 }
+ PathCubic { control1X: 42.901; control1Y: 27.726; control2X: 40.875; control2Y: 25.7; x: 40.875; y: 23.2 }
+ PathCubic { control1X: 40.875; control1Y: 20.701; control2X: 42.901; control2Y: 18.675; x: 45.4; y: 18.675 }
+ PathCubic { control1X: 47.9; control1Y: 18.675; control2X: 49.926; control2Y: 20.701; x: 49.926; y: 23.2 }
+ PathCubic { control1X: 49.926; control1Y: 25.7; control2X: 47.9; control2Y: 27.726; x: 45.4; y: 27.726 }
+ }
+
+ ShapePath {
+ fillColor: "#cc7226"
+ strokeWidth: -1
+ PathMove { x: -58.6; y: 14.4 }
+ PathCubic { control1X: -58.6; control1Y: 14.4; control2X: -61.8; control2Y: -6.8; x: -59.4; y: -11.2 }
+ PathCubic { control1X: -59.4; control1Y: -11.2; control2X: -48.6; control2Y: -21.2; x: -49; y: -24.8 }
+ PathCubic { control1X: -49; control1Y: -24.8; control2X: -49.4; control2Y: -42.8; x: -50.6; y: -43.6 }
+ PathCubic { control1X: -51.8; control1Y: -44.4; control2X: -59.4; control2Y: -50.4; x: -65.4; y: -44 }
+ PathCubic { control1X: -65.4; control1Y: -44; control2X: -75.8; control2Y: -26; x: -75; y: -19.6 }
+ PathLine { x: -75; y: -17.6 }
+ PathCubic { control1X: -75; control1Y: -17.6; control2X: -82.6; control2Y: -18; x: -84.2; y: -16 }
+ PathCubic { control1X: -84.2; control1Y: -16; control2X: -85.4; control2Y: -10.8; x: -86.6; y: -10.4 }
+ PathCubic { control1X: -86.6; control1Y: -10.4; control2X: -89.4; control2Y: -8; x: -87.4; y: -5.2 }
+ PathCubic { control1X: -87.4; control1Y: -5.2; control2X: -89.4; control2Y: -2.8; x: -89; y: 1.2 }
+ PathLine { x: -81.4; y: 5.2 }
+ PathCubic { control1X: -81.4; control1Y: 5.2; control2X: -79.4; control2Y: 19.6; x: -68.6; y: 24.8 }
+ PathCubic { control1X: -63.764; control1Y: 27.129; control2X: -60.6; control2Y: 20.4; x: -58.6; y: 14.4 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeWidth: -1
+ PathMove { x: -59.6; y: 12.56 }
+ PathCubic { control1X: -59.6; control1Y: 12.56; control2X: -62.48; control2Y: -6.52; x: -60.32; y: -10.48 }
+ PathCubic { control1X: -60.32; control1Y: -10.48; control2X: -50.6; control2Y: -19.48; x: -50.96; y: -22.72 }
+ PathCubic { control1X: -50.96; control1Y: -22.72; control2X: -51.32; control2Y: -38.92; x: -52.4; y: -39.64 }
+ PathCubic { control1X: -53.48; control1Y: -40.36; control2X: -60.32; control2Y: -45.76; x: -65.72; y: -40 }
+ PathCubic { control1X: -65.72; control1Y: -40; control2X: -75.08; control2Y: -23.8; x: -74.36; y: -18.04 }
+ PathLine { x: -74.36; y: -16.24 }
+ PathCubic { control1X: -74.36; control1Y: -16.24; control2X: -81.2; control2Y: -16.6; x: -82.64; y: -14.8 }
+ PathCubic { control1X: -82.64; control1Y: -14.8; control2X: -83.72; control2Y: -10.12; x: -84.8; y: -9.76 }
+ PathCubic { control1X: -84.8; control1Y: -9.76; control2X: -87.32; control2Y: -7.6; x: -85.52; y: -5.08 }
+ PathCubic { control1X: -85.52; control1Y: -5.08; control2X: -87.32; control2Y: -2.92; x: -86.96; y: 0.68 }
+ PathLine { x: -80.12; y: 4.28 }
+ PathCubic { control1X: -80.12; control1Y: 4.28; control2X: -78.32; control2Y: 17.24; x: -68.6; y: 21.92 }
+ PathCubic { control1X: -64.248; control1Y: 24.015; control2X: -61.4; control2Y: 17.96; x: -59.6; y: 12.56 }
+ }
+
+ ShapePath {
+ fillColor: "#eb955c"
+ strokeWidth: -1
+ PathMove { x: -51.05; y: -42.61 }
+ PathCubic { control1X: -52.14; control1Y: -43.47; control2X: -59.63; control2Y: -49.24; x: -65.48; y: -43 }
+ PathCubic { control1X: -65.48; control1Y: -43; control2X: -75.62; control2Y: -25.45; x: -74.84; y: -19.21 }
+ PathLine { x: -74.84; y: -17.26 }
+ PathCubic { control1X: -74.84; control1Y: -17.26; control2X: -82.25; control2Y: -17.65; x: -83.81; y: -15.7 }
+ PathCubic { control1X: -83.81; control1Y: -15.7; control2X: -84.98; control2Y: -10.63; x: -86.15; y: -10.24 }
+ PathCubic { control1X: -86.15; control1Y: -10.24; control2X: -88.88; control2Y: -7.9; x: -86.93; y: -5.17 }
+ PathCubic { control1X: -86.93; control1Y: -5.17; control2X: -88.88; control2Y: -2.83; x: -88.49; y: 1.07 }
+ PathLine { x: -81.08; y: 4.97 }
+ PathCubic { control1X: -81.08; control1Y: 4.97; control2X: -79.13; control2Y: 19.01; x: -68.6; y: 24.08 }
+ PathCubic { control1X: -63.886; control1Y: 26.35; control2X: -60.8; control2Y: 19.79; x: -58.85; y: 13.94 }
+ PathCubic { control1X: -58.85; control1Y: 13.94; control2X: -61.97; control2Y: -6.73; x: -59.63; y: -11.02 }
+ PathCubic { control1X: -59.63; control1Y: -11.02; control2X: -49.1; control2Y: -20.77; x: -49.49; y: -24.28 }
+ PathCubic { control1X: -49.49; control1Y: -24.28; control2X: -49.88; control2Y: -41.83; x: -51.05; y: -42.61 }
+ }
+
+ ShapePath {
+ fillColor: "#f2b892"
+ strokeWidth: -1
+ PathMove { x: -51.5; y: -41.62 }
+ PathCubic { control1X: -52.48; control1Y: -42.54; control2X: -59.86; control2Y: -48.08; x: -65.56; y: -42 }
+ PathCubic { control1X: -65.56; control1Y: -42; control2X: -75.44; control2Y: -24.9; x: -74.68; y: -18.82 }
+ PathLine { x: -74.68; y: -16.92 }
+ PathCubic { control1X: -74.68; control1Y: -16.92; control2X: -81.9; control2Y: -17.3; x: -83.42; y: -15.4 }
+ PathCubic { control1X: -83.42; control1Y: -15.4; control2X: -84.56; control2Y: -10.46; x: -85.7; y: -10.08 }
+ PathCubic { control1X: -85.7; control1Y: -10.08; control2X: -88.36; control2Y: -7.8; x: -86.46; y: -5.14 }
+ PathCubic { control1X: -86.46; control1Y: -5.14; control2X: -88.36; control2Y: -2.86; x: -87.98; y: 0.94 }
+ PathLine { x: -80.76; y: 4.74 }
+ PathCubic { control1X: -80.76; control1Y: 4.74; control2X: -78.86; control2Y: 18.42; x: -68.6; y: 23.36 }
+ PathCubic { control1X: -64.006; control1Y: 25.572; control2X: -61; control2Y: 19.18; x: -59.1; y: 13.48 }
+ PathCubic { control1X: -59.1; control1Y: 13.48; control2X: -62.14; control2Y: -6.66; x: -59.86; y: -10.84 }
+ PathCubic { control1X: -59.86; control1Y: -10.84; control2X: -49.6; control2Y: -20.34; x: -49.98; y: -23.76 }
+ PathCubic { control1X: -49.98; control1Y: -23.76; control2X: -50.36; control2Y: -40.86; x: -51.5; y: -41.62 }
+ }
+
+ ShapePath {
+ fillColor: "#f8dcc8"
+ strokeWidth: -1
+ PathMove { x: -51.95; y: -40.63 }
+ PathCubic { control1X: -52.82; control1Y: -41.61; control2X: -60.09; control2Y: -46.92; x: -65.64; y: -41 }
+ PathCubic { control1X: -65.64; control1Y: -41; control2X: -75.26; control2Y: -24.35; x: -74.52; y: -18.43 }
+ PathLine { x: -74.52; y: -16.58 }
+ PathCubic { control1X: -74.52; control1Y: -16.58; control2X: -81.55; control2Y: -16.95; x: -83.03; y: -15.1 }
+ PathCubic { control1X: -83.03; control1Y: -15.1; control2X: -84.14; control2Y: -10.29; x: -85.25; y: -9.92 }
+ PathCubic { control1X: -85.25; control1Y: -9.92; control2X: -87.84; control2Y: -7.7; x: -85.99; y: -5.11 }
+ PathCubic { control1X: -85.99; control1Y: -5.11; control2X: -87.84; control2Y: -2.89; x: -87.47; y: 0.81 }
+ PathLine { x: -80.44; y: 4.51 }
+ PathCubic { control1X: -80.44; control1Y: 4.51; control2X: -78.59; control2Y: 17.83; x: -68.6; y: 22.64 }
+ PathCubic { control1X: -64.127; control1Y: 24.794; control2X: -61.2; control2Y: 18.57; x: -59.35; y: 13.02 }
+ PathCubic { control1X: -59.35; control1Y: 13.02; control2X: -62.31; control2Y: -6.59; x: -60.09; y: -10.66 }
+ PathCubic { control1X: -60.09; control1Y: -10.66; control2X: -50.1; control2Y: -19.91; x: -50.47; y: -23.24 }
+ PathCubic { control1X: -50.47; control1Y: -23.24; control2X: -50.84; control2Y: -39.89; x: -51.95; y: -40.63 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeWidth: -1
+ PathMove { x: -59.6; y: 12.46 }
+ PathCubic { control1X: -59.6; control1Y: 12.46; control2X: -62.48; control2Y: -6.52; x: -60.32; y: -10.48 }
+ PathCubic { control1X: -60.32; control1Y: -10.48; control2X: -50.6; control2Y: -19.48; x: -50.96; y: -22.72 }
+ PathCubic { control1X: -50.96; control1Y: -22.72; control2X: -51.32; control2Y: -38.92; x: -52.4; y: -39.64 }
+ PathCubic { control1X: -53.16; control1Y: -40.68; control2X: -60.32; control2Y: -45.76; x: -65.72; y: -40 }
+ PathCubic { control1X: -65.72; control1Y: -40; control2X: -75.08; control2Y: -23.8; x: -74.36; y: -18.04 }
+ PathLine { x: -74.36; y: -16.24 }
+ PathCubic { control1X: -74.36; control1Y: -16.24; control2X: -81.2; control2Y: -16.6; x: -82.64; y: -14.8 }
+ PathCubic { control1X: -82.64; control1Y: -14.8; control2X: -83.72; control2Y: -10.12; x: -84.8; y: -9.76 }
+ PathCubic { control1X: -84.8; control1Y: -9.76; control2X: -87.32; control2Y: -7.6; x: -85.52; y: -5.08 }
+ PathCubic { control1X: -85.52; control1Y: -5.08; control2X: -87.32; control2Y: -2.92; x: -86.96; y: 0.68 }
+ PathLine { x: -80.12; y: 4.28 }
+ PathCubic { control1X: -80.12; control1Y: 4.28; control2X: -78.32; control2Y: 17.24; x: -68.6; y: 21.92 }
+ PathCubic { control1X: -64.248; control1Y: 24.015; control2X: -61.4; control2Y: 17.86; x: -59.6; y: 12.46 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -62.7; y: 6.2 }
+ PathCubic { control1X: -62.7; control1Y: 6.2; control2X: -84.3; control2Y: -4; x: -85.2; y: -4.8 }
+ PathCubic { control1X: -85.2; control1Y: -4.8; control2X: -76.1; control2Y: 3.4; x: -75.3; y: 3.4 }
+ PathCubic { control1X: -74.5; control1Y: 3.4; control2X: -62.7; control2Y: 6.2; x: -62.7; y: 6.2 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -79.8; y: 0 }
+ PathCubic { control1X: -79.8; control1Y: 0; control2X: -61.4; control2Y: 3.6; x: -61.4; y: 8 }
+ PathCubic { control1X: -61.4; control1Y: 10.912; control2X: -61.643; control2Y: 24.331; x: -67; y: 22.8 }
+ PathCubic { control1X: -75.4; control1Y: 20.4; control2X: -71.8; control2Y: 6; x: -79.8; y: 0 }
+ }
+
+ ShapePath {
+ fillColor: "#99cc32"
+ strokeWidth: -1
+ PathMove { x: -71.4; y: 3.8 }
+ PathCubic { control1X: -71.4; control1Y: 3.8; control2X: -62.422; control2Y: 5.274; x: -61.4; y: 8 }
+ PathCubic { control1X: -60.8; control1Y: 9.6; control2X: -60.137; control2Y: 17.908; x: -65.6; y: 19 }
+ PathCubic { control1X: -70.152; control1Y: 19.911; control2X: -72.382; control2Y: 9.69; x: -71.4; y: 3.8 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 14.595; y: 46.349 }
+ PathCubic { control1X: 14.098; control1Y: 44.607; control2X: 15.409; control2Y: 44.738; x: 17.2; y: 44.2 }
+ PathCubic { control1X: 19.2; control1Y: 43.6; control2X: 31.4; control2Y: 39.8; x: 32.2; y: 37.2 }
+ PathCubic { control1X: 33; control1Y: 34.6; control2X: 46.2; control2Y: 39; x: 46.2; y: 39 }
+ PathCubic { control1X: 48; control1Y: 39.8; control2X: 52.4; control2Y: 42.4; x: 52.4; y: 42.4 }
+ PathCubic { control1X: 57.2; control1Y: 43.6; control2X: 63.8; control2Y: 44; x: 63.8; y: 44 }
+ PathCubic { control1X: 66.2; control1Y: 45; control2X: 69.6; control2Y: 47.8; x: 69.6; y: 47.8 }
+ PathCubic { control1X: 84.2; control1Y: 58; control2X: 96.601; control2Y: 50.8; x: 96.601; y: 50.8 }
+ PathCubic { control1X: 116.601; control1Y: 44.2; control2X: 110.601; control2Y: 27; x: 110.601; y: 27 }
+ PathCubic { control1X: 107.601; control1Y: 18; control2X: 110.801; control2Y: 14.6; x: 110.801; y: 14.6 }
+ PathCubic { control1X: 111.001; control1Y: 10.8; control2X: 118.201; control2Y: 17.2; x: 118.201; y: 17.2 }
+ PathCubic { control1X: 120.801; control1Y: 21.4; control2X: 121.601; control2Y: 26.4; x: 121.601; y: 26.4 }
+ PathCubic { control1X: 129.601; control1Y: 37.6; control2X: 126.201; control2Y: 19.8; x: 126.201; y: 19.8 }
+ PathCubic { control1X: 126.401; control1Y: 18.8; control2X: 123.601; control2Y: 15.2; x: 123.601; y: 14 }
+ PathCubic { control1X: 123.601; control1Y: 12.8; control2X: 121.801; control2Y: 9.4; x: 121.801; y: 9.4 }
+ PathCubic { control1X: 118.801; control1Y: 6; control2X: 121.201; control2Y: -1; x: 121.201; y: -1 }
+ PathCubic { control1X: 123.001; control1Y: -14.8; control2X: 120.801; control2Y: -13; x: 120.801; y: -13 }
+ PathCubic { control1X: 119.601; control1Y: -14.8; control2X: 110.401; control2Y: -4.8; x: 110.401; y: -4.8 }
+ PathCubic { control1X: 108.201; control1Y: -1.4; control2X: 102.201; control2Y: 0.2; x: 102.201; y: 0.2 }
+ PathCubic { control1X: 99.401; control1Y: 2; control2X: 96.001; control2Y: 0.6; x: 96.001; y: 0.6 }
+ PathCubic { control1X: 93.401; control1Y: 0.2; control2X: 87.801; control2Y: 7.2; x: 87.801; y: 7.2 }
+ PathCubic { control1X: 90.601; control1Y: 7; control2X: 93.001; control2Y: 11.4; x: 95.401; y: 11.6 }
+ PathCubic { control1X: 97.801; control1Y: 11.8; control2X: 99.601; control2Y: 9.2; x: 101.201; y: 8.6 }
+ PathCubic { control1X: 102.801; control1Y: 8; control2X: 105.601; control2Y: 13.8; x: 105.601; y: 13.8 }
+ PathCubic { control1X: 106.001; control1Y: 16.4; control2X: 100.401; control2Y: 21.2; x: 100.401; y: 21.2 }
+ PathCubic { control1X: 100.001; control1Y: 25.8; control2X: 98.401; control2Y: 24.2; x: 98.401; y: 24.2 }
+ PathCubic { control1X: 95.401; control1Y: 23.6; control2X: 94.201; control2Y: 27.4; x: 93.201; y: 32 }
+ PathCubic { control1X: 92.201; control1Y: 36.6; control2X: 88.001; control2Y: 37; x: 88.001; y: 37 }
+ PathCubic { control1X: 86.401; control1Y: 44.4; control2X: 85.2; control2Y: 41.4; x: 85.2; y: 41.4 }
+ PathCubic { control1X: 85; control1Y: 35.8; control2X: 79; control2Y: 41.6; x: 79; y: 41.6 }
+ PathCubic { control1X: 77.8; control1Y: 43.6; control2X: 73.2; control2Y: 41.4; x: 73.2; y: 41.4 }
+ PathCubic { control1X: 66.4; control1Y: 39.4; control2X: 68.8; control2Y: 37.4; x: 68.8; y: 37.4 }
+ PathCubic { control1X: 70.6; control1Y: 35.2; control2X: 81.8; control2Y: 37.4; x: 81.8; y: 37.4 }
+ PathCubic { control1X: 84; control1Y: 35.8; control2X: 76; control2Y: 31.8; x: 76; y: 31.8 }
+ PathCubic { control1X: 75.4; control1Y: 30; control2X: 76.4; control2Y: 25.6; x: 76.4; y: 25.6 }
+ PathCubic { control1X: 77.6; control1Y: 22.4; control2X: 84.4; control2Y: 16.8; x: 84.4; y: 16.8 }
+ PathCubic { control1X: 93.801; control1Y: 15.6; control2X: 91.001; control2Y: 14; x: 91.001; y: 14 }
+ PathCubic { control1X: 84.801; control1Y: 8.8; control2X: 79; control2Y: 16.4; x: 79; y: 16.4 }
+ PathCubic { control1X: 76.8; control1Y: 22.6; control2X: 59.4; control2Y: 37.6; x: 59.4; y: 37.6 }
+ PathCubic { control1X: 54.6; control1Y: 41; control2X: 57.2; control2Y: 34.2; x: 53.2; y: 37.6 }
+ PathCubic { control1X: 49.2; control1Y: 41; control2X: 28.6; control2Y: 32; x: 28.6; y: 32 }
+ PathCubic { control1X: 17.038; control1Y: 30.807; control2X: 14.306; control2Y: 46.549; x: 10.777; y: 43.429 }
+ PathCubic { control1X: 10.777; control1Y: 43.429; control2X: 16.195; control2Y: 51.949; x: 14.595; y: 46.349 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 209.401; y: -120 }
+ PathCubic { control1X: 209.401; control1Y: -120; control2X: 183.801; control2Y: -112; x: 181.001; y: -93.2 }
+ PathCubic { control1X: 181.001; control1Y: -93.2; control2X: 178.601; control2Y: -70.4; x: 199.001; y: -52.8 }
+ PathCubic { control1X: 199.001; control1Y: -52.8; control2X: 199.401; control2Y: -46.4; x: 201.401; y: -43.2 }
+ PathCubic { control1X: 201.401; control1Y: -43.2; control2X: 199.801; control2Y: -38.4; x: 218.601; y: -46 }
+ PathLine { x: 245.801; y: -54.4 }
+ PathCubic { control1X: 245.801; control1Y: -54.4; control2X: 252.201; control2Y: -56.8; x: 257.401; y: -65.6 }
+ PathCubic { control1X: 262.601; control1Y: -74.4; control2X: 277.801; control2Y: -93.2; x: 274.201; y: -118.4 }
+ PathCubic { control1X: 274.201; control1Y: -118.4; control2X: 275.401; control2Y: -129.6; x: 269.401; y: -130 }
+ PathCubic { control1X: 269.401; control1Y: -130; control2X: 261.001; control2Y: -131.6; x: 253.801; y: -124 }
+ PathCubic { control1X: 253.801; control1Y: -124; control2X: 247.001; control2Y: -120.8; x: 244.601; y: -121.2 }
+ PathLine { x: 209.401; y: -120 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 264.022; y: -120.99 }
+ PathCubic { control1X: 264.022; control1Y: -120.99; control2X: 266.122; control2Y: -129.92; x: 261.282; y: -125.08 }
+ PathCubic { control1X: 261.282; control1Y: -125.08; control2X: 254.242; control2Y: -119.36; x: 246.761; y: -119.36 }
+ PathCubic { control1X: 246.761; control1Y: -119.36; control2X: 232.241; control2Y: -117.16; x: 227.841; y: -103.96 }
+ PathCubic { control1X: 227.841; control1Y: -103.96; control2X: 223.881; control2Y: -77.12; x: 231.801; y: -71.4 }
+ PathCubic { control1X: 231.801; control1Y: -71.4; control2X: 236.641; control2Y: -63.92; x: 243.681; y: -70.52 }
+ PathCubic { control1X: 250.722; control1Y: -77.12; control2X: 266.222; control2Y: -107.35; x: 264.022; y: -120.99 }
+ }
+
+ ShapePath {
+ fillColor: "#323232"
+ strokeWidth: -1
+ PathMove { x: 263.648; y: -120.632 }
+ PathCubic { control1X: 263.648; control1Y: -120.632; control2X: 265.738; control2Y: -129.376; x: 260.986; y: -124.624 }
+ PathCubic { control1X: 260.986; control1Y: -124.624; control2X: 254.074; control2Y: -119.008; x: 246.729; y: -119.008 }
+ PathCubic { control1X: 246.729; control1Y: -119.008; control2X: 232.473; control2Y: -116.848; x: 228.153; y: -103.888 }
+ PathCubic { control1X: 228.153; control1Y: -103.888; control2X: 224.265; control2Y: -77.536; x: 232.041; y: -71.92 }
+ PathCubic { control1X: 232.041; control1Y: -71.92; control2X: 236.793; control2Y: -64.576; x: 243.705; y: -71.056 }
+ PathCubic { control1X: 250.618; control1Y: -77.536; control2X: 265.808; control2Y: -107.24; x: 263.648; y: -120.632 }
+ }
+
+ ShapePath {
+ fillColor: "#666666"
+ strokeWidth: -1
+ PathMove { x: 263.274; y: -120.274 }
+ PathCubic { control1X: 263.274; control1Y: -120.274; control2X: 265.354; control2Y: -128.832; x: 260.69; y: -124.168 }
+ PathCubic { control1X: 260.69; control1Y: -124.168; control2X: 253.906; control2Y: -118.656; x: 246.697; y: -118.656 }
+ PathCubic { control1X: 246.697; control1Y: -118.656; control2X: 232.705; control2Y: -116.536; x: 228.465; y: -103.816 }
+ PathCubic { control1X: 228.465; control1Y: -103.816; control2X: 224.649; control2Y: -77.952; x: 232.281; y: -72.44 }
+ PathCubic { control1X: 232.281; control1Y: -72.44; control2X: 236.945; control2Y: -65.232; x: 243.729; y: -71.592 }
+ PathCubic { control1X: 250.514; control1Y: -77.952; control2X: 265.394; control2Y: -107.13; x: 263.274; y: -120.274 }
+ }
+
+ ShapePath {
+ fillColor: "#999999"
+ strokeWidth: -1
+ PathMove { x: 262.9; y: -119.916 }
+ PathCubic { control1X: 262.9; control1Y: -119.916; control2X: 264.97; control2Y: -128.288; x: 260.394; y: -123.712 }
+ PathCubic { control1X: 260.394; control1Y: -123.712; control2X: 253.738; control2Y: -118.304; x: 246.665; y: -118.304 }
+ PathCubic { control1X: 246.665; control1Y: -118.304; control2X: 232.937; control2Y: -116.224; x: 228.777; y: -103.744 }
+ PathCubic { control1X: 228.777; control1Y: -103.744; control2X: 225.033; control2Y: -78.368; x: 232.521; y: -72.96 }
+ PathCubic { control1X: 232.521; control1Y: -72.96; control2X: 237.097; control2Y: -65.888; x: 243.753; y: -72.128 }
+ PathCubic { control1X: 250.41; control1Y: -78.368; control2X: 264.98; control2Y: -107.02; x: 262.9; y: -119.916 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: 262.526; y: -119.558 }
+ PathCubic { control1X: 262.526; control1Y: -119.558; control2X: 264.586; control2Y: -127.744; x: 260.098; y: -123.256 }
+ PathCubic { control1X: 260.098; control1Y: -123.256; control2X: 253.569; control2Y: -117.952; x: 246.633; y: -117.952 }
+ PathCubic { control1X: 246.633; control1Y: -117.952; control2X: 233.169; control2Y: -115.912; x: 229.089; y: -103.672 }
+ PathCubic { control1X: 229.089; control1Y: -103.672; control2X: 225.417; control2Y: -78.784; x: 232.761; y: -73.48 }
+ PathCubic { control1X: 232.761; control1Y: -73.48; control2X: 237.249; control2Y: -66.544; x: 243.777; y: -72.664 }
+ PathCubic { control1X: 250.305; control1Y: -78.784; control2X: 264.566; control2Y: -106.91; x: 262.526; y: -119.558 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeWidth: -1
+ PathMove { x: 262.151; y: -119.2 }
+ PathCubic { control1X: 262.151; control1Y: -119.2; control2X: 264.201; control2Y: -127.2; x: 259.801; y: -122.8 }
+ PathCubic { control1X: 259.801; control1Y: -122.8; control2X: 253.401; control2Y: -117.6; x: 246.601; y: -117.6 }
+ PathCubic { control1X: 246.601; control1Y: -117.6; control2X: 233.401; control2Y: -115.6; x: 229.401; y: -103.6 }
+ PathCubic { control1X: 229.401; control1Y: -103.6; control2X: 225.801; control2Y: -79.2; x: 233.001; y: -74 }
+ PathCubic { control1X: 233.001; control1Y: -74; control2X: 237.401; control2Y: -67.2; x: 243.801; y: -73.2 }
+ PathCubic { control1X: 250.201; control1Y: -79.2; control2X: 264.151; control2Y: -106.8; x: 262.151; y: -119.2 }
+ }
+
+ ShapePath {
+ fillColor: "#992600"
+ strokeWidth: -1
+ PathMove { x: 50.6; y: 84 }
+ PathCubic { control1X: 50.6; control1Y: 84; control2X: 30.2; control2Y: 64.8; x: 22.2; y: 64 }
+ PathCubic { control1X: 22.2; control1Y: 64; control2X: -12.2; control2Y: 60; x: -27; y: 78 }
+ PathCubic { control1X: -27; control1Y: 78; control2X: -9.4; control2Y: 57.6; x: 18.2; y: 63.2 }
+ PathCubic { control1X: 18.2; control1Y: 63.2; control2X: -3.4; control2Y: 58.8; x: -15.8; y: 62 }
+ PathCubic { control1X: -15.8; control1Y: 62; control2X: -32.6; control2Y: 62; x: -42.2; y: 76 }
+ PathLine { x: -45; y: 80.8 }
+ PathCubic { control1X: -45; control1Y: 80.8; control2X: -41; control2Y: 66; x: -22.6; y: 60 }
+ PathCubic { control1X: -22.6; control1Y: 60; control2X: 0.2; control2Y: 55.2; x: 11; y: 60 }
+ PathCubic { control1X: 11; control1Y: 60; control2X: -10.6; control2Y: 53.2; x: -20.6; y: 55.2 }
+ PathCubic { control1X: -20.6; control1Y: 55.2; control2X: -51; control2Y: 52.8; x: -63.8; y: 79.2 }
+ PathCubic { control1X: -63.8; control1Y: 79.2; control2X: -59.8; control2Y: 64.8; x: -45; y: 57.6 }
+ PathCubic { control1X: -45; control1Y: 57.6; control2X: -31.4; control2Y: 48.8; x: -11; y: 51.6 }
+ PathCubic { control1X: -11; control1Y: 51.6; control2X: 3.4; control2Y: 54.8; x: 8.6; y: 57.2 }
+ PathCubic { control1X: 13.8; control1Y: 59.6; control2X: 12.6; control2Y: 56.8; x: 4.2; y: 52 }
+ PathCubic { control1X: 4.2; control1Y: 52; control2X: -1.4; control2Y: 42; x: -15.4; y: 42.4 }
+ PathCubic { control1X: -15.4; control1Y: 42.4; control2X: -58.2; control2Y: 46; x: -68.6; y: 58 }
+ PathCubic { control1X: -68.6; control1Y: 58; control2X: -55; control2Y: 46.8; x: -44.6; y: 44 }
+ PathCubic { control1X: -44.6; control1Y: 44; control2X: -22.2; control2Y: 36; x: -13.8; y: 36.8 }
+ PathCubic { control1X: -13.8; control1Y: 36.8; control2X: 11; control2Y: 37.8; x: 18.6; y: 33.8 }
+ PathCubic { control1X: 18.6; control1Y: 33.8; control2X: 7.4; control2Y: 38.8; x: 10.6; y: 42 }
+ PathCubic { control1X: 13.8; control1Y: 45.2; control2X: 20.6; control2Y: 52.8; x: 20.6; y: 54 }
+ PathCubic { control1X: 20.6; control1Y: 55.2; control2X: 44.8; control2Y: 77.3; x: 48.4; y: 81.7 }
+ PathLine { x: 50.6; y: 84 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: 189; y: 278 }
+ PathCubic { control1X: 189; control1Y: 278; control2X: 173.5; control2Y: 241.5; x: 161; y: 232 }
+ PathCubic { control1X: 161; control1Y: 232; control2X: 187; control2Y: 248; x: 190.5; y: 266 }
+ PathCubic { control1X: 190.5; control1Y: 266; control2X: 190.5; control2Y: 276; x: 189; y: 278 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: 236; y: 285.5 }
+ PathCubic { control1X: 236; control1Y: 285.5; control2X: 209.5; control2Y: 230.5; x: 191; y: 206.5 }
+ PathCubic { control1X: 191; control1Y: 206.5; control2X: 234.5; control2Y: 244; x: 239.5; y: 270.5 }
+ PathLine { x: 240; y: 276 }
+ PathLine { x: 237; y: 273.5 }
+ PathCubic { control1X: 237; control1Y: 273.5; control2X: 236.5; control2Y: 282.5; x: 236; y: 285.5 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: 292.5; y: 237 }
+ PathCubic { control1X: 292.5; control1Y: 237; control2X: 230; control2Y: 177.5; x: 228.5; y: 175 }
+ PathCubic { control1X: 228.5; control1Y: 175; control2X: 289; control2Y: 241; x: 292; y: 248.5 }
+ PathCubic { control1X: 292; control1Y: 248.5; control2X: 290; control2Y: 239.5; x: 292.5; y: 237 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: 104; y: 280.5 }
+ PathCubic { control1X: 104; control1Y: 280.5; control2X: 123.5; control2Y: 228.5; x: 142.5; y: 251 }
+ PathCubic { control1X: 142.5; control1Y: 251; control2X: 157.5; control2Y: 261; x: 157; y: 264 }
+ PathCubic { control1X: 157; control1Y: 264; control2X: 153; control2Y: 257.5; x: 135; y: 258 }
+ PathCubic { control1X: 135; control1Y: 258; control2X: 116; control2Y: 255; x: 104; y: 280.5 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: 294.5; y: 153 }
+ PathCubic { control1X: 294.5; control1Y: 153; control2X: 249.5; control2Y: 124.5; x: 242; y: 123 }
+ PathCubic { control1X: 230.193; control1Y: 120.639; control2X: 291.5; control2Y: 152; x: 296.5; y: 162.5 }
+ PathCubic { control1X: 296.5; control1Y: 162.5; control2X: 298.5; control2Y: 160; x: 294.5; y: 153 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 143.801; y: 259.601 }
+ PathCubic { control1X: 143.801; control1Y: 259.601; control2X: 164.201; control2Y: 257.601; x: 171.001; y: 250.801 }
+ PathLine { x: 175.401; y: 254.401 }
+ PathLine { x: 193.001; y: 216.001 }
+ PathLine { x: 196.601; y: 221.201 }
+ PathCubic { control1X: 196.601; control1Y: 221.201; control2X: 211.001; control2Y: 206.401; x: 210.201; y: 198.401 }
+ PathCubic { control1X: 209.401; control1Y: 190.401; control2X: 223.001; control2Y: 204.401; x: 223.001; y: 204.401 }
+ PathCubic { control1X: 223.001; control1Y: 204.401; control2X: 222.201; control2Y: 192.801; x: 229.401; y: 199.601 }
+ PathCubic { control1X: 229.401; control1Y: 199.601; control2X: 227.001; control2Y: 184.001; x: 235.401; y: 192.001 }
+ PathCubic { control1X: 235.401; control1Y: 192.001; control2X: 224.864; control2Y: 161.844; x: 247.401; y: 187.601 }
+ PathCubic { control1X: 253.001; control1Y: 194.001; control2X: 248.601; control2Y: 187.201; x: 248.601; y: 187.201 }
+ PathCubic { control1X: 248.601; control1Y: 187.201; control2X: 222.601; control2Y: 139.201; x: 244.201; y: 153.601 }
+ PathCubic { control1X: 244.201; control1Y: 153.601; control2X: 246.201; control2Y: 130.801; x: 245.001; y: 126.401 }
+ PathCubic { control1X: 243.801; control1Y: 122.001; control2X: 241.801; control2Y: 99.6; x: 237.001; y: 94.4 }
+ PathCubic { control1X: 232.201; control1Y: 89.2; control2X: 237.401; control2Y: 87.6; x: 243.001; y: 92.8 }
+ PathCubic { control1X: 243.001; control1Y: 92.8; control2X: 231.801; control2Y: 68.8; x: 245.001; y: 80.8 }
+ PathCubic { control1X: 245.001; control1Y: 80.8; control2X: 241.401; control2Y: 65.6; x: 237.001; y: 62.8 }
+ PathCubic { control1X: 237.001; control1Y: 62.8; control2X: 231.401; control2Y: 45.6; x: 246.601; y: 56.4 }
+ PathCubic { control1X: 246.601; control1Y: 56.4; control2X: 242.201; control2Y: 44; x: 239.001; y: 40.8 }
+ PathCubic { control1X: 239.001; control1Y: 40.8; control2X: 227.401; control2Y: 13.2; x: 234.601; y: 18 }
+ PathLine { x: 239.001; y: 21.6 }
+ PathCubic { control1X: 239.001; control1Y: 21.6; control2X: 232.201; control2Y: 7.6; x: 238.601; y: 12 }
+ PathCubic { control1X: 245.001; control1Y: 16.4; control2X: 245.001; control2Y: 16; x: 245.001; y: 16 }
+ PathCubic { control1X: 245.001; control1Y: 16; control2X: 223.801; control2Y: -17.2; x: 244.201; y: 0.4 }
+ PathCubic { control1X: 244.201; control1Y: 0.4; control2X: 236.042; control2Y: -13.518; x: 232.601; y: -20.4 }
+ PathCubic { control1X: 232.601; control1Y: -20.4; control2X: 213.801; control2Y: -40.8; x: 228.201; y: -34.4 }
+ PathLine { x: 233.001; y: -32.8 }
+ PathCubic { control1X: 233.001; control1Y: -32.8; control2X: 224.201; control2Y: -42.8; x: 216.201; y: -44.4 }
+ PathCubic { control1X: 208.201; control1Y: -46; control2X: 218.601; control2Y: -52.4; x: 225.001; y: -50.4 }
+ PathCubic { control1X: 231.401; control1Y: -48.4; control2X: 247.001; control2Y: -40.8; x: 247.001; y: -40.8 }
+ PathCubic { control1X: 247.001; control1Y: -40.8; control2X: 259.801; control2Y: -22; x: 263.801; y: -21.6 }
+ PathCubic { control1X: 263.801; control1Y: -21.6; control2X: 243.801; control2Y: -29.2; x: 249.801; y: -21.2 }
+ PathCubic { control1X: 249.801; control1Y: -21.2; control2X: 264.201; control2Y: -7.2; x: 257.001; y: -7.6 }
+ PathCubic { control1X: 257.001; control1Y: -7.6; control2X: 251.001; control2Y: -0.4; x: 255.801; y: 8.4 }
+ PathCubic { control1X: 255.801; control1Y: 8.4; control2X: 237.342; control2Y: -9.991; x: 252.201; y: 15.6 }
+ PathLine { x: 259.001; y: 32 }
+ PathCubic { control1X: 259.001; control1Y: 32; control2X: 234.601; control2Y: 7.2; x: 245.801; y: 29.2 }
+ PathCubic { control1X: 245.801; control1Y: 29.2; control2X: 263.001; control2Y: 52.8; x: 265.001; y: 53.2 }
+ PathCubic { control1X: 267.001; control1Y: 53.6; control2X: 271.401; control2Y: 62.4; x: 271.401; y: 62.4 }
+ PathLine { x: 267.001; y: 60.4 }
+ PathLine { x: 272.201; y: 69.2 }
+ PathCubic { control1X: 272.201; control1Y: 69.2; control2X: 261.001; control2Y: 57.2; x: 267.001; y: 70.4 }
+ PathLine { x: 272.601; y: 84.8 }
+ PathCubic { control1X: 272.601; control1Y: 84.8; control2X: 252.201; control2Y: 62.8; x: 265.801; y: 92.4 }
+ PathCubic { control1X: 265.801; control1Y: 92.4; control2X: 249.401; control2Y: 87.2; x: 258.201; y: 104.4 }
+ PathCubic { control1X: 258.201; control1Y: 104.4; control2X: 256.601; control2Y: 120.401; x: 257.001; y: 125.601 }
+ PathCubic { control1X: 257.401; control1Y: 130.801; control2X: 258.601; control2Y: 159.201; x: 254.201; y: 167.201 }
+ PathCubic { control1X: 249.801; control1Y: 175.201; control2X: 260.201; control2Y: 194.401; x: 262.201; y: 198.401 }
+ PathCubic { control1X: 264.201; control1Y: 202.401; control2X: 267.801; control2Y: 213.201; x: 259.001; y: 204.001 }
+ PathCubic { control1X: 250.201; control1Y: 194.801; control2X: 254.601; control2Y: 200.401; x: 256.601; y: 209.201 }
+ PathCubic { control1X: 258.601; control1Y: 218.001; control2X: 264.601; control2Y: 233.601; x: 263.801; y: 239.201 }
+ PathCubic { control1X: 263.801; control1Y: 239.201; control2X: 262.601; control2Y: 240.401; x: 259.401; y: 236.801 }
+ PathCubic { control1X: 259.401; control1Y: 236.801; control2X: 244.601; control2Y: 214.001; x: 246.201; y: 228.401 }
+ PathCubic { control1X: 246.201; control1Y: 228.401; control2X: 245.001; control2Y: 236.401; x: 241.801; y: 245.201 }
+ PathCubic { control1X: 241.801; control1Y: 245.201; control2X: 238.601; control2Y: 256.001; x: 238.601; y: 247.201 }
+ PathCubic { control1X: 238.601; control1Y: 247.201; control2X: 235.401; control2Y: 230.401; x: 232.601; y: 238.001 }
+ PathCubic { control1X: 229.801; control1Y: 245.601; control2X: 226.201; control2Y: 251.601; x: 223.401; y: 254.001 }
+ PathCubic { control1X: 220.601; control1Y: 256.401; control2X: 215.401; control2Y: 233.601; x: 214.201; y: 244.001 }
+ PathCubic { control1X: 214.201; control1Y: 244.001; control2X: 202.201; control2Y: 231.601; x: 197.401; y: 248.001 }
+ PathLine { x: 185.801; y: 264.401 }
+ PathCubic { control1X: 185.801; control1Y: 264.401; control2X: 185.401; control2Y: 252.001; x: 184.201; y: 258.001 }
+ PathCubic { control1X: 184.201; control1Y: 258.001; control2X: 154.201; control2Y: 264.001; x: 143.801; y: 259.601 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 109.401; y: -97.2 }
+ PathCubic { control1X: 109.401; control1Y: -97.2; control2X: 97.801; control2Y: -105.2; x: 93.801; y: -104.8 }
+ PathCubic { control1X: 89.801; control1Y: -104.4; control2X: 121.401; control2Y: -113.6; x: 162.601; y: -86 }
+ PathCubic { control1X: 162.601; control1Y: -86; control2X: 167.401; control2Y: -83.2; x: 171.001; y: -83.6 }
+ PathCubic { control1X: 171.001; control1Y: -83.6; control2X: 174.201; control2Y: -81.2; x: 171.401; y: -77.6 }
+ PathCubic { control1X: 171.401; control1Y: -77.6; control2X: 162.601; control2Y: -68; x: 173.801; y: -56.8 }
+ PathCubic { control1X: 173.801; control1Y: -56.8; control2X: 192.201; control2Y: -50; x: 186.601; y: -58.8 }
+ PathCubic { control1X: 186.601; control1Y: -58.8; control2X: 197.401; control2Y: -54.8; x: 199.801; y: -50.8 }
+ PathCubic { control1X: 202.201; control1Y: -46.8; control2X: 201.001; control2Y: -50.8; x: 201.001; y: -50.8 }
+ PathCubic { control1X: 201.001; control1Y: -50.8; control2X: 194.601; control2Y: -58; x: 188.601; y: -63.2 }
+ PathCubic { control1X: 188.601; control1Y: -63.2; control2X: 183.401; control2Y: -65.2; x: 180.601; y: -73.6 }
+ PathCubic { control1X: 177.801; control1Y: -82; control2X: 175.401; control2Y: -92; x: 179.801; y: -95.2 }
+ PathCubic { control1X: 179.801; control1Y: -95.2; control2X: 175.801; control2Y: -90.8; x: 176.601; y: -94.8 }
+ PathCubic { control1X: 177.401; control1Y: -98.8; control2X: 181.001; control2Y: -102.4; x: 182.601; y: -102.8 }
+ PathCubic { control1X: 184.201; control1Y: -103.2; control2X: 200.601; control2Y: -119; x: 207.401; y: -119.4 }
+ PathCubic { control1X: 207.401; control1Y: -119.4; control2X: 198.201; control2Y: -118; x: 195.201; y: -119 }
+ PathCubic { control1X: 192.201; control1Y: -120; control2X: 165.601; control2Y: -131.4; x: 159.601; y: -132.6 }
+ PathCubic { control1X: 159.601; control1Y: -132.6; control2X: 142.801; control2Y: -139.2; x: 154.801; y: -137.2 }
+ PathCubic { control1X: 154.801; control1Y: -137.2; control2X: 190.601; control2Y: -133.4; x: 208.801; y: -120.2 }
+ PathCubic { control1X: 208.801; control1Y: -120.2; control2X: 201.601; control2Y: -128.6; x: 183.201; y: -135.6 }
+ PathCubic { control1X: 183.201; control1Y: -135.6; control2X: 161.001; control2Y: -148.2; x: 125.801; y: -143.2 }
+ PathCubic { control1X: 125.801; control1Y: -143.2; control2X: 108.001; control2Y: -140; x: 100.201; y: -138.2 }
+ PathCubic { control1X: 100.201; control1Y: -138.2; control2X: 97.601; control2Y: -138.8; x: 97.001; y: -139.2 }
+ PathCubic { control1X: 96.401; control1Y: -139.6; control2X: 84.6; control2Y: -148.6; x: 57; y: -141.6 }
+ PathCubic { control1X: 57; control1Y: -141.6; control2X: 40; control2Y: -137; x: 31.4; y: -132.2 }
+ PathCubic { control1X: 31.4; control1Y: -132.2; control2X: 16.2; control2Y: -131; x: 12.6; y: -127.8 }
+ PathCubic { control1X: 12.6; control1Y: -127.8; control2X: -6; control2Y: -113.2; x: -8; y: -112.4 }
+ PathCubic { control1X: -10; control1Y: -111.6; control2X: -21.4; control2Y: -104; x: -22.2; y: -103.6 }
+ PathCubic { control1X: -22.2; control1Y: -103.6; control2X: 2.4; control2Y: -110.2; x: 4.8; y: -112.6 }
+ PathCubic { control1X: 7.2; control1Y: -115; control2X: 24.6; control2Y: -117.6; x: 27; y: -116.2 }
+ PathCubic { control1X: 29.4; control1Y: -114.8; control2X: 37.8; control2Y: -115.4; x: 28.2; y: -114.8 }
+ PathCubic { control1X: 28.2; control1Y: -114.8; control2X: 103.801; control2Y: -100; x: 104.601; y: -98 }
+ PathCubic { control1X: 105.401; control1Y: -96; control2X: 109.401; control2Y: -97.2; x: 109.401; y: -97.2 }
+ }
+
+ ShapePath {
+ fillColor: "#cc7226"
+ strokeWidth: -1
+ PathMove { x: 180.801; y: -106.4 }
+ PathCubic { control1X: 180.801; control1Y: -106.4; control2X: 170.601; control2Y: -113.8; x: 168.601; y: -113.8 }
+ PathCubic { control1X: 166.601; control1Y: -113.8; control2X: 154.201; control2Y: -124; x: 150.001; y: -123.6 }
+ PathCubic { control1X: 145.801; control1Y: -123.2; control2X: 133.601; control2Y: -133.2; x: 106.201; y: -125 }
+ PathCubic { control1X: 106.201; control1Y: -125; control2X: 105.601; control2Y: -127; x: 109.201; y: -127.8 }
+ PathCubic { control1X: 109.201; control1Y: -127.8; control2X: 115.601; control2Y: -130; x: 116.001; y: -130.6 }
+ PathCubic { control1X: 116.001; control1Y: -130.6; control2X: 136.201; control2Y: -134.8; x: 143.401; y: -131.2 }
+ PathCubic { control1X: 143.401; control1Y: -131.2; control2X: 152.601; control2Y: -128.6; x: 158.801; y: -122.4 }
+ PathCubic { control1X: 158.801; control1Y: -122.4; control2X: 170.001; control2Y: -119.2; x: 173.201; y: -120.2 }
+ PathCubic { control1X: 173.201; control1Y: -120.2; control2X: 182.001; control2Y: -118; x: 182.401; y: -116.2 }
+ PathCubic { control1X: 182.401; control1Y: -116.2; control2X: 188.201; control2Y: -113.2; x: 186.401; y: -110.6 }
+ PathCubic { control1X: 186.401; control1Y: -110.6; control2X: 186.801; control2Y: -109; x: 180.801; y: -106.4 }
+ }
+
+ ShapePath {
+ fillColor: "#cc7226"
+ strokeWidth: -1
+ PathMove { x: 168.33; y: -108.509 }
+ PathCubic { control1X: 169.137; control1Y: -107.877; control2X: 170.156; control2Y: -107.779; x: 170.761; y: -106.97 }
+ PathCubic { control1X: 170.995; control1Y: -106.656; control2X: 170.706; control2Y: -106.33; x: 170.391; y: -106.233 }
+ PathCubic { control1X: 169.348; control1Y: -105.916; control2X: 168.292; control2Y: -106.486; x: 167.15; y: -105.898 }
+ PathCubic { control1X: 166.748; control1Y: -105.691; control2X: 166.106; control2Y: -105.873; x: 165.553; y: -106.022 }
+ PathCubic { control1X: 163.921; control1Y: -106.463; control2X: 162.092; control2Y: -106.488; x: 160.401; y: -105.8 }
+ PathCubic { control1X: 158.416; control1Y: -106.929; control2X: 156.056; control2Y: -106.345; x: 153.975; y: -107.346 }
+ PathCubic { control1X: 153.917; control1Y: -107.373; control2X: 153.695; control2Y: -107.027; x: 153.621; y: -107.054 }
+ PathCubic { control1X: 150.575; control1Y: -108.199; control2X: 146.832; control2Y: -107.916; x: 144.401; y: -110.2 }
+ PathCubic { control1X: 141.973; control1Y: -110.612; control2X: 139.616; control2Y: -111.074; x: 137.188; y: -111.754 }
+ PathCubic { control1X: 135.37; control1Y: -112.263; control2X: 133.961; control2Y: -113.252; x: 132.341; y: -114.084 }
+ PathCubic { control1X: 130.964; control1Y: -114.792; control2X: 129.507; control2Y: -115.314; x: 127.973; y: -115.686 }
+ PathCubic { control1X: 126.11; control1Y: -116.138; control2X: 124.279; control2Y: -116.026; x: 122.386; y: -116.546 }
+ PathCubic { control1X: 122.293; control1Y: -116.571; control2X: 122.101; control2Y: -116.227; x: 122.019; y: -116.254 }
+ PathCubic { control1X: 121.695; control1Y: -116.362; control2X: 121.405; control2Y: -116.945; x: 121.234; y: -116.892 }
+ PathCubic { control1X: 119.553; control1Y: -116.37; control2X: 118.065; control2Y: -117.342; x: 116.401; y: -117 }
+ PathCubic { control1X: 115.223; control1Y: -118.224; control2X: 113.495; control2Y: -117.979; x: 111.949; y: -118.421 }
+ PathCubic { control1X: 108.985; control1Y: -119.269; control2X: 105.831; control2Y: -117.999; x: 102.801; y: -119 }
+ PathCubic { control1X: 106.914; control1Y: -120.842; control2X: 111.601; control2Y: -119.61; x: 115.663; y: -121.679 }
+ PathCubic { control1X: 117.991; control1Y: -122.865; control2X: 120.653; control2Y: -121.763; x: 123.223; y: -122.523 }
+ PathCubic { control1X: 123.71; control1Y: -122.667; control2X: 124.401; control2Y: -122.869; x: 124.801; y: -122.2 }
+ PathCubic { control1X: 124.935; control1Y: -122.335; control2X: 125.117; control2Y: -122.574; x: 125.175; y: -122.546 }
+ PathCubic { control1X: 127.625; control1Y: -121.389; control2X: 129.94; control2Y: -120.115; x: 132.422; y: -119.049 }
+ PathCubic { control1X: 132.763; control1Y: -118.903; control2X: 133.295; control2Y: -119.135; x: 133.547; y: -118.933 }
+ PathCubic { control1X: 135.067; control1Y: -117.717; control2X: 137.01; control2Y: -117.82; x: 138.401; y: -116.6 }
+ PathCubic { control1X: 140.099; control1Y: -117.102; control2X: 141.892; control2Y: -116.722; x: 143.621; y: -117.346 }
+ PathCubic { control1X: 143.698; control1Y: -117.373; control2X: 143.932; control2Y: -117.032; x: 143.965; y: -117.054 }
+ PathCubic { control1X: 145.095; control1Y: -117.802; control2X: 146.25; control2Y: -117.531; x: 147.142; y: -117.227 }
+ PathCubic { control1X: 147.48; control1Y: -117.112; control2X: 148.143; control2Y: -116.865; x: 148.448; y: -116.791 }
+ PathCubic { control1X: 149.574; control1Y: -116.515; control2X: 150.43; control2Y: -116.035; x: 151.609; y: -115.852 }
+ PathCubic { control1X: 151.723; control1Y: -115.834; control2X: 151.908; control2Y: -116.174; x: 151.98; y: -116.146 }
+ PathCubic { control1X: 153.103; control1Y: -115.708; control2X: 154.145; control2Y: -115.764; x: 154.801; y: -114.6 }
+ PathCubic { control1X: 154.936; control1Y: -114.735; control2X: 155.101; control2Y: -114.973; x: 155.183; y: -114.946 }
+ PathCubic { control1X: 156.21; control1Y: -114.608; control2X: 156.859; control2Y: -113.853; x: 157.96; y: -113.612 }
+ PathCubic { control1X: 158.445; control1Y: -113.506; control2X: 159.057; control2Y: -112.88; x: 159.633; y: -112.704 }
+ PathCubic { control1X: 162.025; control1Y: -111.973; control2X: 163.868; control2Y: -110.444; x: 166.062; y: -109.549 }
+ PathCubic { control1X: 166.821; control1Y: -109.239; control2X: 167.697; control2Y: -109.005; x: 168.33; y: -108.509 }
+ }
+
+ ShapePath {
+ fillColor: "#cc7226"
+ strokeWidth: -1
+ PathMove { x: 91.696; y: -122.739 }
+ PathCubic { control1X: 89.178; control1Y: -124.464; control2X: 86.81; control2Y: -125.57; x: 84.368; y: -127.356 }
+ PathCubic { control1X: 84.187; control1Y: -127.489; control2X: 83.827; control2Y: -127.319; x: 83.625; y: -127.441 }
+ PathCubic { control1X: 82.618; control1Y: -128.05; control2X: 81.73; control2Y: -128.631; x: 80.748; y: -129.327 }
+ PathCubic { control1X: 80.209; control1Y: -129.709; control2X: 79.388; control2Y: -129.698; x: 78.88; y: -129.956 }
+ PathCubic { control1X: 76.336; control1Y: -131.248; control2X: 73.707; control2Y: -131.806; x: 71.2; y: -133 }
+ PathCubic { control1X: 71.882; control1Y: -133.638; control2X: 73.004; control2Y: -133.394; x: 73.6; y: -134.2 }
+ PathCubic { control1X: 73.795; control1Y: -133.92; control2X: 74.033; control2Y: -133.636; x: 74.386; y: -133.827 }
+ PathCubic { control1X: 76.064; control1Y: -134.731; control2X: 77.914; control2Y: -134.884; x: 79.59; y: -134.794 }
+ PathCubic { control1X: 81.294; control1Y: -134.702; control2X: 83.014; control2Y: -134.397; x: 84.789; y: -134.125 }
+ PathCubic { control1X: 85.096; control1Y: -134.078; control2X: 85.295; control2Y: -133.555; x: 85.618; y: -133.458 }
+ PathCubic { control1X: 87.846; control1Y: -132.795; control2X: 90.235; control2Y: -133.32; x: 92.354; y: -132.482 }
+ PathCubic { control1X: 93.945; control1Y: -131.853; control2X: 95.515; control2Y: -131.03; x: 96.754; y: -129.755 }
+ PathCubic { control1X: 97.006; control1Y: -129.495; control2X: 96.681; control2Y: -129.194; x: 96.401; y: -129 }
+ PathCubic { control1X: 96.789; control1Y: -129.109; control2X: 97.062; control2Y: -128.903; x: 97.173; y: -128.59 }
+ PathCubic { control1X: 97.257; control1Y: -128.351; control2X: 97.257; control2Y: -128.049; x: 97.173; y: -127.81 }
+ PathCubic { control1X: 97.061; control1Y: -127.498; control2X: 96.782; control2Y: -127.397; x: 96.408; y: -127.346 }
+ PathCubic { control1X: 95.001; control1Y: -127.156; control2X: 96.773; control2Y: -128.536; x: 96.073; y: -128.088 }
+ PathCubic { control1X: 94.8; control1Y: -127.274; control2X: 95.546; control2Y: -125.868; x: 94.801; y: -124.6 }
+ PathCubic { control1X: 94.521; control1Y: -124.794; control2X: 94.291; control2Y: -125.012; x: 94.401; y: -125.4 }
+ PathCubic { control1X: 94.635; control1Y: -124.878; control2X: 94.033; control2Y: -124.588; x: 93.865; y: -124.272 }
+ PathCubic { control1X: 93.48; control1Y: -123.547; control2X: 92.581; control2Y: -122.132; x: 91.696; y: -122.739 }
+ }
+
+ ShapePath {
+ fillColor: "#cc7226"
+ strokeWidth: -1
+ PathMove { x: 59.198; y: -115.391 }
+ PathCubic { control1X: 56.044; control1Y: -116.185; control2X: 52.994; control2Y: -116.07; x: 49.978; y: -117.346 }
+ PathCubic { control1X: 49.911; control1Y: -117.374; control2X: 49.688; control2Y: -117.027; x: 49.624; y: -117.054 }
+ PathCubic { control1X: 48.258; control1Y: -117.648; control2X: 47.34; control2Y: -118.614; x: 46.264; y: -119.66 }
+ PathCubic { control1X: 45.351; control1Y: -120.548; control2X: 43.693; control2Y: -120.161; x: 42.419; y: -120.648 }
+ PathCubic { control1X: 42.095; control1Y: -120.772; control2X: 41.892; control2Y: -121.284; x: 41.591; y: -121.323 }
+ PathCubic { control1X: 40.372; control1Y: -121.48; control2X: 39.445; control2Y: -122.429; x: 38.4; y: -123 }
+ PathCubic { control1X: 40.736; control1Y: -123.795; control2X: 43.147; control2Y: -123.764; x: 45.609; y: -124.148 }
+ PathCubic { control1X: 45.722; control1Y: -124.166; control2X: 45.867; control2Y: -123.845; x: 46; y: -123.845 }
+ PathCubic { control1X: 46.136; control1Y: -123.845; control2X: 46.266; control2Y: -124.066; x: 46.4; y: -124.2 }
+ PathCubic { control1X: 46.595; control1Y: -123.92; control2X: 46.897; control2Y: -123.594; x: 47.154; y: -123.848 }
+ PathCubic { control1X: 47.702; control1Y: -124.388; control2X: 48.258; control2Y: -124.198; x: 48.798; y: -124.158 }
+ PathCubic { control1X: 48.942; control1Y: -124.148; control2X: 49.067; control2Y: -123.845; x: 49.2; y: -123.845 }
+ PathCubic { control1X: 49.336; control1Y: -123.845; control2X: 49.467; control2Y: -124.156; x: 49.6; y: -124.156 }
+ PathCubic { control1X: 49.736; control1Y: -124.155; control2X: 49.867; control2Y: -123.845; x: 50; y: -123.845 }
+ PathCubic { control1X: 50.136; control1Y: -123.845; control2X: 50.266; control2Y: -124.066; x: 50.4; y: -124.2 }
+ PathCubic { control1X: 51.092; control1Y: -123.418; control2X: 51.977; control2Y: -123.972; x: 52.799; y: -123.793 }
+ PathCubic { control1X: 53.837; control1Y: -123.566; control2X: 54.104; control2Y: -122.418; x: 55.178; y: -122.12 }
+ PathCubic { control1X: 59.893; control1Y: -120.816; control2X: 64.03; control2Y: -118.671; x: 68.393; y: -116.584 }
+ PathCubic { control1X: 68.7; control1Y: -116.437; control2X: 68.91; control2Y: -116.189; x: 68.8; y: -115.8 }
+ PathCubic { control1X: 69.067; control1Y: -115.8; control2X: 69.38; control2Y: -115.888; x: 69.57; y: -115.756 }
+ PathCubic { control1X: 70.628; control1Y: -115.024; control2X: 71.669; control2Y: -114.476; x: 72.366; y: -113.378 }
+ PathCubic { control1X: 72.582; control1Y: -113.039; control2X: 72.253; control2Y: -112.632; x: 72.02; y: -112.684 }
+ PathCubic { control1X: 67.591; control1Y: -113.679; control2X: 63.585; control2Y: -114.287; x: 59.198; y: -115.391 }
+ }
+
+ ShapePath {
+ fillColor: "#cc7226"
+ strokeWidth: -1
+ PathMove { x: 45.338; y: -71.179 }
+ PathCubic { control1X: 43.746; control1Y: -72.398; control2X: 43.162; control2Y: -74.429; x: 42.034; y: -76.221 }
+ PathCubic { control1X: 41.82; control1Y: -76.561; control2X: 42.094; control2Y: -76.875; x: 42.411; y: -76.964 }
+ PathCubic { control1X: 42.971; control1Y: -77.123; control2X: 43.514; control2Y: -76.645; x: 43.923; y: -76.443 }
+ PathCubic { control1X: 45.668; control1Y: -75.581; control2X: 47.203; control2Y: -74.339; x: 49.2; y: -74.2 }
+ PathCubic { control1X: 51.19; control1Y: -71.966; control2X: 55.45; control2Y: -71.581; x: 55.457; y: -68.2 }
+ PathCubic { control1X: 55.458; control1Y: -67.341; control2X: 54.03; control2Y: -68.259; x: 53.6; y: -67.4 }
+ PathCubic { control1X: 51.149; control1Y: -68.403; control2X: 48.76; control2Y: -68.3; x: 46.38; y: -69.767 }
+ PathCubic { control1X: 45.763; control1Y: -70.148; control2X: 46.093; control2Y: -70.601; x: 45.338; y: -71.179 }
+ }
+
+ ShapePath {
+ fillColor: "#cc7226"
+ strokeWidth: -1
+ PathMove { x: 17.8; y: -123.756 }
+ PathCubic { control1X: 17.935; control1Y: -123.755; control2X: 24.966; control2Y: -123.522; x: 24.949; y: -123.408 }
+ PathCubic { control1X: 24.904; control1Y: -123.099; control2X: 17.174; control2Y: -122.05; x: 16.81; y: -122.22 }
+ PathCubic { control1X: 16.646; control1Y: -122.296; control2X: 9.134; control2Y: -119.866; x: 9; y: -120 }
+ PathCubic { control1X: 9.268; control1Y: -120.135; control2X: 17.534; control2Y: -123.756; x: 17.8; y: -123.756 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 33.2; y: -114 }
+ PathCubic { control1X: 33.2; control1Y: -114; control2X: 18.4; control2Y: -112.2; x: 14; y: -111 }
+ PathCubic { control1X: 9.6; control1Y: -109.8; control2X: -9; control2Y: -102.2; x: -12; y: -100.2 }
+ PathCubic { control1X: -12; control1Y: -100.2; control2X: -25.4; control2Y: -94.8; x: -42.4; y: -74.8 }
+ PathCubic { control1X: -42.4; control1Y: -74.8; control2X: -34.8; control2Y: -78.2; x: -32.6; y: -81 }
+ PathCubic { control1X: -32.6; control1Y: -81; control2X: -19; control2Y: -93.6; x: -19.2; y: -91 }
+ PathCubic { control1X: -19.2; control1Y: -91; control2X: -7; control2Y: -99.6; x: -7.6; y: -97.4 }
+ PathCubic { control1X: -7.6; control1Y: -97.4; control2X: 16.8; control2Y: -108.6; x: 14.8; y: -105.4 }
+ PathCubic { control1X: 14.8; control1Y: -105.4; control2X: 36.4; control2Y: -110; x: 35.4; y: -108 }
+ PathCubic { control1X: 35.4; control1Y: -108; control2X: 54.2; control2Y: -103.6; x: 51.4; y: -103.4 }
+ PathCubic { control1X: 51.4; control1Y: -103.4; control2X: 45.6; control2Y: -102.2; x: 52; y: -98.6 }
+ PathCubic { control1X: 52; control1Y: -98.6; control2X: 48.6; control2Y: -94.2; x: 43.2; y: -98.2 }
+ PathCubic { control1X: 37.8; control1Y: -102.2; control2X: 40.8; control2Y: -100; x: 35.8; y: -99 }
+ PathCubic { control1X: 35.8; control1Y: -99; control2X: 33.2; control2Y: -98.2; x: 28.6; y: -102.2 }
+ PathCubic { control1X: 28.6; control1Y: -102.2; control2X: 23; control2Y: -106.8; x: 14.2; y: -103.2 }
+ PathCubic { control1X: 14.2; control1Y: -103.2; control2X: -16.4; control2Y: -90.6; x: -18.4; y: -90 }
+ PathCubic { control1X: -18.4; control1Y: -90; control2X: -22; control2Y: -87.2; x: -24.4; y: -83.6 }
+ PathCubic { control1X: -24.4; control1Y: -83.6; control2X: -30.2; control2Y: -79.2; x: -33.2; y: -77.8 }
+ PathCubic { control1X: -33.2; control1Y: -77.8; control2X: -46; control2Y: -66.2; x: -47.2; y: -64.8 }
+ PathCubic { control1X: -47.2; control1Y: -64.8; control2X: -50.6; control2Y: -59.6; x: -51.4; y: -59.2 }
+ PathCubic { control1X: -51.4; control1Y: -59.2; control2X: -45; control2Y: -63; x: -43; y: -65 }
+ PathCubic { control1X: -43; control1Y: -65; control2X: -29; control2Y: -75; x: -23.6; y: -75.8 }
+ PathCubic { control1X: -23.6; control1Y: -75.8; control2X: -19.2; control2Y: -78.8; x: -18.4; y: -80.2 }
+ PathCubic { control1X: -18.4; control1Y: -80.2; control2X: -4; control2Y: -89.4; x: 0.2; y: -89.4 }
+ PathCubic { control1X: 0.2; control1Y: -89.4; control2X: 9.4; control2Y: -84.2; x: 11.8; y: -91.2 }
+ PathCubic { control1X: 11.8; control1Y: -91.2; control2X: 17.6; control2Y: -93; x: 23.2; y: -91.8 }
+ PathCubic { control1X: 23.2; control1Y: -91.8; control2X: 26.4; control2Y: -94.4; x: 25.6; y: -96.6 }
+ PathCubic { control1X: 25.6; control1Y: -96.6; control2X: 27.2; control2Y: -98.4; x: 28.2; y: -94.6 }
+ PathCubic { control1X: 28.2; control1Y: -94.6; control2X: 31.6; control2Y: -91; x: 36.4; y: -93 }
+ PathCubic { control1X: 36.4; control1Y: -93; control2X: 40.4; control2Y: -93.2; x: 38.4; y: -90.8 }
+ PathCubic { control1X: 38.4; control1Y: -90.8; control2X: 34; control2Y: -87; x: 22.2; y: -86.8 }
+ PathCubic { control1X: 22.2; control1Y: -86.8; control2X: 9.8; control2Y: -86.2; x: -6.6; y: -78.6 }
+ PathCubic { control1X: -6.6; control1Y: -78.6; control2X: -36.4; control2Y: -68.2; x: -45.6; y: -57.8 }
+ PathCubic { control1X: -45.6; control1Y: -57.8; control2X: -52; control2Y: -49; x: -57.4; y: -47.8 }
+ PathCubic { control1X: -57.4; control1Y: -47.8; control2X: -63.2; control2Y: -47; x: -69.2; y: -39.6 }
+ PathCubic { control1X: -69.2; control1Y: -39.6; control2X: -59.4; control2Y: -45.4; x: -50.4; y: -45.4 }
+ PathCubic { control1X: -50.4; control1Y: -45.4; control2X: -46.4; control2Y: -47.8; x: -50.2; y: -44.2 }
+ PathCubic { control1X: -50.2; control1Y: -44.2; control2X: -53.8; control2Y: -36.6; x: -52.2; y: -31.2 }
+ PathCubic { control1X: -52.2; control1Y: -31.2; control2X: -52.8; control2Y: -26; x: -53.6; y: -24.4 }
+ PathCubic { control1X: -53.6; control1Y: -24.4; control2X: -61.4; control2Y: -11.6; x: -61.4; y: -9.2 }
+ PathCubic { control1X: -61.4; control1Y: -6.8; control2X: -60.2; control2Y: 3; x: -59.8; y: 3.6 }
+ PathCubic { control1X: -59.4; control1Y: 4.2; control2X: -60.8; control2Y: 2; x: -57; y: 4.4 }
+ PathCubic { control1X: -53.2; control1Y: 6.8; control2X: -50.4; control2Y: 8.4; x: -49.6; y: 11.2 }
+ PathCubic { control1X: -48.8; control1Y: 14; control2X: -51.6; control2Y: 5.8; x: -51.8; y: 4 }
+ PathCubic { control1X: -52; control1Y: 2.2; control2X: -56.2; control2Y: -5; x: -55.4; y: -7.4 }
+ PathCubic { control1X: -55.4; control1Y: -7.4; control2X: -54.4; control2Y: -6.4; x: -53.6; y: -5 }
+ PathCubic { control1X: -53.6; control1Y: -5; control2X: -54.2; control2Y: -5.6; x: -53.6; y: -9.2 }
+ PathCubic { control1X: -53.6; control1Y: -9.2; control2X: -52.8; control2Y: -14.4; x: -51.4; y: -17.6 }
+ PathCubic { control1X: -50; control1Y: -20.8; control2X: -48; control2Y: -24.6; x: -47.6; y: -25.4 }
+ PathCubic { control1X: -47.2; control1Y: -26.2; control2X: -47.2; control2Y: -32; x: -45.8; y: -29.4 }
+ PathLine { x: -42.4; y: -26.8 }
+ PathCubic { control1X: -42.4; control1Y: -26.8; control2X: -45.2; control2Y: -29.4; x: -43; y: -31.6 }
+ PathCubic { control1X: -43; control1Y: -31.6; control2X: -44; control2Y: -37.2; x: -42.2; y: -39.8 }
+ PathCubic { control1X: -42.2; control1Y: -39.8; control2X: -35.2; control2Y: -48.2; x: -33.6; y: -49.2 }
+ PathCubic { control1X: -32; control1Y: -50.2; control2X: -33.4; control2Y: -49.8; x: -33.4; y: -49.8 }
+ PathCubic { control1X: -33.4; control1Y: -49.8; control2X: -27.4; control2Y: -54; x: -33.2; y: -52.4 }
+ PathCubic { control1X: -33.2; control1Y: -52.4; control2X: -37.2; control2Y: -50.8; x: -40.2; y: -50.8 }
+ PathCubic { control1X: -40.2; control1Y: -50.8; control2X: -47.8; control2Y: -48.8; x: -43.8; y: -53 }
+ PathCubic { control1X: -39.8; control1Y: -57.2; control2X: -29.8; control2Y: -62.6; x: -26; y: -62.4 }
+ PathLine { x: -25.2; y: -60.8 }
+ PathLine { x: -14; y: -63.2 }
+ PathLine { x: -15.2; y: -62.4 }
+ PathCubic { control1X: -15.2; control1Y: -62.4; control2X: -15.4; control2Y: -62.6; x: -11.2; y: -63 }
+ PathCubic { control1X: -7; control1Y: -63.4; control2X: -1.2; control2Y: -62; x: 0.2; y: -63.8 }
+ PathCubic { control1X: 1.6; control1Y: -65.6; control2X: 5; control2Y: -66.6; x: 4.6; y: -65.2 }
+ PathCubic { control1X: 4.2; control1Y: -63.8; control2X: 4; control2Y: -61.8; x: 4; y: -61.8 }
+ PathCubic { control1X: 4; control1Y: -61.8; control2X: 9; control2Y: -67.6; x: 8.4; y: -65.4 }
+ PathCubic { control1X: 7.8; control1Y: -63.2; control2X: -0.4; control2Y: -58; x: -1.8; y: -51.8 }
+ PathLine { x: 8.6; y: -60 }
+ PathLine { x: 12.2; y: -63 }
+ PathCubic { control1X: 12.2; control1Y: -63; control2X: 15.8; control2Y: -60.8; x: 16; y: -62.4 }
+ PathCubic { control1X: 16.2; control1Y: -64; control2X: 20.8; control2Y: -69.8; x: 22; y: -69.6 }
+ PathCubic { control1X: 23.2; control1Y: -69.4; control2X: 25.2; control2Y: -72.2; x: 25; y: -69.6 }
+ PathCubic { control1X: 24.8; control1Y: -67; control2X: 32.4; control2Y: -61.6; x: 32.4; y: -61.6 }
+ PathCubic { control1X: 32.4; control1Y: -61.6; control2X: 35.6; control2Y: -63.4; x: 37; y: -62 }
+ PathCubic { control1X: 38.4; control1Y: -60.6; control2X: 42.6; control2Y: -81.8; x: 42.6; y: -81.8 }
+ PathLine { x: 67.6; y: -92.4 }
+ PathLine { x: 111.201; y: -95.8 }
+ PathLine { x: 94.201; y: -102.6 }
+ PathLine { x: 33.2; y: -114 }
+ }
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: "#4c0000"
+ strokeWidth: 2
+ PathMove { x: 51.4; y: 85 }
+ PathCubic { control1X: 51.4; control1Y: 85; control2X: 36.4; control2Y: 68.2; x: 28; y: 65.6 }
+ PathCubic { control1X: 28; control1Y: 65.6; control2X: 14.6; control2Y: 58.8; x: -10; y: 66.6 }
+ }
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: "#4c0000"
+ strokeWidth: 2
+ PathMove { x: 24.8; y: 64.2 }
+ PathCubic { control1X: 24.8; control1Y: 64.2; control2X: -0.4; control2Y: 56.2; x: -15.8; y: 60.4 }
+ PathCubic { control1X: -15.8; control1Y: 60.4; control2X: -34.2; control2Y: 62.4; x: -42.6; y: 76.2 }
+ }
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: "#4c0000"
+ strokeWidth: 2
+ PathMove { x: 21.2; y: 63 }
+ PathCubic { control1X: 21.2; control1Y: 63; control2X: 4.2; control2Y: 55.8; x: -10.6; y: 53.6 }
+ PathCubic { control1X: -10.6; control1Y: 53.6; control2X: -27.2; control2Y: 51; x: -43.8; y: 58.2 }
+ PathCubic { control1X: -43.8; control1Y: 58.2; control2X: -56; control2Y: 64.2; x: -61.4; y: 74.4 }
+ }
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: "#4c0000"
+ strokeWidth: 2
+ PathMove { x: 22.2; y: 63.4 }
+ PathCubic { control1X: 22.2; control1Y: 63.4; control2X: 6.8; control2Y: 52.4; x: 5.8; y: 51 }
+ PathCubic { control1X: 5.8; control1Y: 51; control2X: -1.2; control2Y: 40; x: -14.2; y: 39.6 }
+ PathCubic { control1X: -14.2; control1Y: 39.6; control2X: -35.6; control2Y: 40.4; x: -52.8; y: 48.4 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 20.895; y: 54.407 }
+ PathCubic { control1X: 22.437; control1Y: 55.87; control2X: 49.4; control2Y: 84.8; x: 49.4; y: 84.8 }
+ PathCubic { control1X: 84.6; control1Y: 121.401; control2X: 56.6; control2Y: 87.2; x: 56.6; y: 87.2 }
+ PathCubic { control1X: 49; control1Y: 82.4; control2X: 39.8; control2Y: 63.6; x: 39.8; y: 63.6 }
+ PathCubic { control1X: 38.6; control1Y: 60.8; control2X: 53.8; control2Y: 70.8; x: 53.8; y: 70.8 }
+ PathCubic { control1X: 57.8; control1Y: 71.6; control2X: 71.4; control2Y: 90.8; x: 71.4; y: 90.8 }
+ PathCubic { control1X: 64.6; control1Y: 88.4; control2X: 69.4; control2Y: 95.6; x: 69.4; y: 95.6 }
+ PathCubic { control1X: 72.2; control1Y: 97.6; control2X: 92.601; control2Y: 113.201; x: 92.601; y: 113.201 }
+ PathCubic { control1X: 96.201; control1Y: 117.201; control2X: 100.201; control2Y: 118.801; x: 100.201; y: 118.801 }
+ PathCubic { control1X: 114.201; control1Y: 113.601; control2X: 107.801; control2Y: 126.801; x: 107.801; y: 126.801 }
+ PathCubic { control1X: 110.201; control1Y: 133.601; control2X: 115.801; control2Y: 122.001; x: 115.801; y: 122.001 }
+ PathCubic { control1X: 127.001; control1Y: 105.2; control2X: 110.601; control2Y: 107.601; x: 110.601; y: 107.601 }
+ PathCubic { control1X: 80.6; control1Y: 110.401; control2X: 73.8; control2Y: 94.4; x: 73.8; y: 94.4 }
+ PathCubic { control1X: 71.4; control1Y: 92; control2X: 80.2; control2Y: 94.4; x: 80.2; y: 94.4 }
+ PathCubic { control1X: 88.601; control1Y: 96.4; control2X: 73; control2Y: 82; x: 73; y: 82 }
+ PathCubic { control1X: 75.4; control1Y: 82; control2X: 84.6; control2Y: 88.8; x: 84.6; y: 88.8 }
+ PathCubic { control1X: 95.001; control1Y: 98; control2X: 97.001; control2Y: 96; x: 97.001; y: 96 }
+ PathCubic { control1X: 115.001; control1Y: 87.2; control2X: 125.401; control2Y: 94.8; x: 125.401; y: 94.8 }
+ PathCubic { control1X: 127.401; control1Y: 96.4; control2X: 121.801; control2Y: 103.2; x: 123.401; y: 108.401 }
+ PathCubic { control1X: 125.001; control1Y: 113.601; control2X: 129.801; control2Y: 126.001; x: 129.801; y: 126.001 }
+ PathCubic { control1X: 127.401; control1Y: 127.601; control2X: 127.801; control2Y: 138.401; x: 127.801; y: 138.401 }
+ PathCubic { control1X: 144.601; control1Y: 161.601; control2X: 135.001; control2Y: 159.601; x: 135.001; y: 159.601 }
+ PathCubic { control1X: 119.401; control1Y: 159.201; control2X: 134.201; control2Y: 166.801; x: 134.201; y: 166.801 }
+ PathCubic { control1X: 137.401; control1Y: 168.801; control2X: 146.201; control2Y: 176.001; x: 146.201; y: 176.001 }
+ PathCubic { control1X: 143.401; control1Y: 174.801; control2X: 141.801; control2Y: 180.001; x: 141.801; y: 180.001 }
+ PathCubic { control1X: 146.601; control1Y: 184.001; control2X: 143.801; control2Y: 188.801; x: 143.801; y: 188.801 }
+ PathCubic { control1X: 137.801; control1Y: 190.001; control2X: 136.601; control2Y: 194.001; x: 136.601; y: 194.001 }
+ PathCubic { control1X: 143.401; control1Y: 202.001; control2X: 133.401; control2Y: 202.401; x: 133.401; y: 202.401 }
+ PathCubic { control1X: 137.001; control1Y: 206.801; control2X: 132.201; control2Y: 218.801; x: 132.201; y: 218.801 }
+ PathCubic { control1X: 127.401; control1Y: 218.801; control2X: 121.001; control2Y: 224.401; x: 121.001; y: 224.401 }
+ PathCubic { control1X: 123.401; control1Y: 229.201; control2X: 113.001; control2Y: 234.801; x: 113.001; y: 234.801 }
+ PathCubic { control1X: 104.601; control1Y: 236.401; control2X: 107.401; control2Y: 243.201; x: 107.401; y: 243.201 }
+ PathCubic { control1X: 99.401; control1Y: 249.201; control2X: 97.001; control2Y: 265.201; x: 97.001; y: 265.201 }
+ PathCubic { control1X: 96.201; control1Y: 275.601; control2X: 93.801; control2Y: 278.801; x: 99.001; y: 276.801 }
+ PathCubic { control1X: 104.201; control1Y: 274.801; control2X: 103.401; control2Y: 262.401; x: 103.401; y: 262.401 }
+ PathCubic { control1X: 98.601; control1Y: 246.801; control2X: 141.401; control2Y: 230.801; x: 141.401; y: 230.801 }
+ PathCubic { control1X: 145.401; control1Y: 229.201; control2X: 146.201; control2Y: 224.001; x: 146.201; y: 224.001 }
+ PathCubic { control1X: 148.201; control1Y: 224.401; control2X: 157.001; control2Y: 232.001; x: 157.001; y: 232.001 }
+ PathCubic { control1X: 164.601; control1Y: 243.201; control2X: 165.001; control2Y: 234.001; x: 165.001; y: 234.001 }
+ PathCubic { control1X: 166.201; control1Y: 230.401; control2X: 164.601; control2Y: 224.401; x: 164.601; y: 224.401 }
+ PathCubic { control1X: 170.601; control1Y: 202.801; control2X: 156.601; control2Y: 196.401; x: 156.601; y: 196.401 }
+ PathCubic { control1X: 146.601; control1Y: 162.801; control2X: 160.601; control2Y: 171.201; x: 160.601; y: 171.201 }
+ PathCubic { control1X: 163.401; control1Y: 176.801; control2X: 174.201; control2Y: 182.001; x: 174.201; y: 182.001 }
+ PathLine { x: 177.801; y: 179.601 }
+ PathCubic { control1X: 176.201; control1Y: 174.801; control2X: 184.601; control2Y: 168.801; x: 184.601; y: 168.801 }
+ PathCubic { control1X: 187.401; control1Y: 175.201; control2X: 193.401; control2Y: 167.201; x: 193.401; y: 167.201 }
+ PathCubic { control1X: 197.001; control1Y: 142.801; control2X: 209.401; control2Y: 157.201; x: 209.401; y: 157.201 }
+ PathCubic { control1X: 213.401; control1Y: 158.401; control2X: 214.601; control2Y: 151.601; x: 214.601; y: 151.601 }
+ PathCubic { control1X: 218.201; control1Y: 141.201; control2X: 214.601; control2Y: 127.601; x: 214.601; y: 127.601 }
+ PathCubic { control1X: 218.201; control1Y: 127.201; control2X: 227.801; control2Y: 133.201; x: 227.801; y: 133.201 }
+ PathCubic { control1X: 230.601; control1Y: 129.601; control2X: 221.401; control2Y: 112.801; x: 225.401; y: 115.201 }
+ PathCubic { control1X: 229.401; control1Y: 117.601; control2X: 233.801; control2Y: 119.201; x: 233.801; y: 119.201 }
+ PathCubic { control1X: 234.601; control1Y: 117.201; control2X: 224.601; control2Y: 104.801; x: 224.601; y: 104.801 }
+ PathCubic { control1X: 220.201; control1Y: 102; control2X: 215.001; control2Y: 81.6; x: 215.001; y: 81.6 }
+ PathCubic { control1X: 222.201; control1Y: 85.2; control2X: 212.201; control2Y: 70; x: 212.201; y: 70 }
+ PathCubic { control1X: 212.201; control1Y: 66.8; control2X: 218.201; control2Y: 55.6; x: 218.201; y: 55.6 }
+ PathCubic { control1X: 217.401; control1Y: 48.8; control2X: 218.201; control2Y: 49.2; x: 218.201; y: 49.2 }
+ PathCubic { control1X: 221.001; control1Y: 50.4; control2X: 229.001; control2Y: 52; x: 222.201; y: 45.6 }
+ PathCubic { control1X: 215.401; control1Y: 39.2; control2X: 223.001; control2Y: 34.4; x: 223.001; y: 34.4 }
+ PathCubic { control1X: 227.401; control1Y: 31.6; control2X: 213.801; control2Y: 32; x: 213.801; y: 32 }
+ PathCubic { control1X: 208.601; control1Y: 27.6; control2X: 209.001; control2Y: 23.6; x: 209.001; y: 23.6 }
+ PathCubic { control1X: 217.001; control1Y: 25.6; control2X: 202.601; control2Y: 11.2; x: 200.201; y: 7.6 }
+ PathCubic { control1X: 197.801; control1Y: 4; control2X: 207.401; control2Y: -1.2; x: 207.401; y: -1.2 }
+ PathCubic { control1X: 220.601; control1Y: -4.8; control2X: 209.001; control2Y: -8; x: 209.001; y: -8 }
+ PathCubic { control1X: 189.401; control1Y: -7.6; control2X: 200.201; control2Y: -18.4; x: 200.201; y: -18.4 }
+ PathCubic { control1X: 206.201; control1Y: -18; control2X: 204.601; control2Y: -20.4; x: 204.601; y: -20.4 }
+ PathCubic { control1X: 199.401; control1Y: -21.6; control2X: 189.801; control2Y: -28; x: 189.801; y: -28 }
+ PathCubic { control1X: 185.801; control1Y: -31.6; control2X: 189.401; control2Y: -30.8; x: 189.401; y: -30.8 }
+ PathCubic { control1X: 206.201; control1Y: -29.6; control2X: 177.401; control2Y: -40.8; x: 177.401; y: -40.8 }
+ PathCubic { control1X: 185.401; control1Y: -40.8; control2X: 167.401; control2Y: -51.2; x: 167.401; y: -51.2 }
+ PathCubic { control1X: 165.401; control1Y: -52.8; control2X: 162.201; control2Y: -60.4; x: 162.201; y: -60.4 }
+ PathCubic { control1X: 156.201; control1Y: -65.6; control2X: 151.401; control2Y: -72.4; x: 151.401; y: -72.4 }
+ PathCubic { control1X: 151.001; control1Y: -76.8; control2X: 146.201; control2Y: -81.6; x: 146.201; y: -81.6 }
+ PathCubic { control1X: 134.601; control1Y: -95.2; control2X: 129.001; control2Y: -94.8; x: 129.001; y: -94.8 }
+ PathCubic { control1X: 114.201; control1Y: -98.4; control2X: 109.001; control2Y: -97.6; x: 109.001; y: -97.6 }
+ PathLine { x: 56.2; y: -93.2 }
+ PathCubic { control1X: 29.8; control1Y: -80.4; control2X: 37.6; control2Y: -59.4; x: 37.6; y: -59.4 }
+ PathCubic { control1X: 44; control1Y: -51; control2X: 53.2; control2Y: -54.8; x: 53.2; y: -54.8 }
+ PathCubic { control1X: 57.8; control1Y: -61; control2X: 69.4; control2Y: -58.8; x: 69.4; y: -58.8 }
+ PathCubic { control1X: 89.801; control1Y: -55.6; control2X: 87.201; control2Y: -59.2; x: 87.201; y: -59.2 }
+ PathCubic { control1X: 84.801; control1Y: -63.8; control2X: 68.6; control2Y: -70; x: 68.4; y: -70.6 }
+ PathCubic { control1X: 68.2; control1Y: -71.2; control2X: 59.4; control2Y: -74.6; x: 59.4; y: -74.6 }
+ PathCubic { control1X: 56.4; control1Y: -75.8; control2X: 52; control2Y: -85; x: 52; y: -85 }
+ PathCubic { control1X: 48.8; control1Y: -88.4; control2X: 64.6; control2Y: -82.6; x: 64.6; y: -82.6 }
+ PathCubic { control1X: 63.4; control1Y: -81.6; control2X: 70.8; control2Y: -77.6; x: 70.8; y: -77.6 }
+ PathCubic { control1X: 88.201; control1Y: -78.6; control2X: 98.801; control2Y: -67.8; x: 98.801; y: -67.8 }
+ PathCubic { control1X: 109.601; control1Y: -51.2; control2X: 109.801; control2Y: -59.4; x: 109.801; y: -59.4 }
+ PathCubic { control1X: 112.601; control1Y: -68.8; control2X: 100.801; control2Y: -90; x: 100.801; y: -90 }
+ PathCubic { control1X: 101.201; control1Y: -92; control2X: 109.401; control2Y: -85.4; x: 109.401; y: -85.4 }
+ PathCubic { control1X: 110.801; control1Y: -87.4; control2X: 111.601; control2Y: -81.6; x: 111.601; y: -81.6 }
+ PathCubic { control1X: 111.801; control1Y: -79.2; control2X: 115.601; control2Y: -71.2; x: 115.601; y: -71.2 }
+ PathCubic { control1X: 118.401; control1Y: -58.2; control2X: 122.001; control2Y: -65.6; x: 122.001; y: -65.6 }
+ PathLine { x: 126.601; y: -56.2 }
+ PathCubic { control1X: 128.001; control1Y: -53.6; control2X: 122.001; control2Y: -46; x: 122.001; y: -46 }
+ PathCubic { control1X: 121.801; control1Y: -43.2; control2X: 122.601; control2Y: -43.4; x: 117.001; y: -35.8 }
+ PathCubic { control1X: 111.401; control1Y: -28.2; control2X: 114.801; control2Y: -23.8; x: 114.801; y: -23.8 }
+ PathCubic { control1X: 113.401; control1Y: -17.2; control2X: 122.201; control2Y: -17.6; x: 122.201; y: -17.6 }
+ PathCubic { control1X: 124.801; control1Y: -15.4; control2X: 128.201; control2Y: -15.4; x: 128.201; y: -15.4 }
+ PathCubic { control1X: 130.001; control1Y: -13.4; control2X: 132.401; control2Y: -14; x: 132.401; y: -14 }
+ PathCubic { control1X: 134.001; control1Y: -17.8; control2X: 140.201; control2Y: -15.8; x: 140.201; y: -15.8 }
+ PathCubic { control1X: 141.601; control1Y: -18.2; control2X: 149.801; control2Y: -18.6; x: 149.801; y: -18.6 }
+ PathCubic { control1X: 150.801; control1Y: -21.2; control2X: 151.201; control2Y: -22.8; x: 154.601; y: -23.4 }
+ PathCubic { control1X: 158.001; control1Y: -24; control2X: 133.401; control2Y: -67; x: 133.401; y: -67 }
+ PathCubic { control1X: 139.801; control1Y: -67.8; control2X: 131.601; control2Y: -80.2; x: 131.601; y: -80.2 }
+ PathCubic { control1X: 129.401; control1Y: -86.8; control2X: 140.801; control2Y: -72.2; x: 143.001; y: -70.8 }
+ PathCubic { control1X: 145.201; control1Y: -69.4; control2X: 146.201; control2Y: -67.2; x: 144.601; y: -67.4 }
+ PathCubic { control1X: 143.001; control1Y: -67.6; control2X: 141.201; control2Y: -65.4; x: 142.601; y: -65.2 }
+ PathCubic { control1X: 144.001; control1Y: -65; control2X: 157.001; control2Y: -50; x: 160.401; y: -39.8 }
+ PathCubic { control1X: 163.801; control1Y: -29.6; control2X: 169.801; control2Y: -25.6; x: 176.001; y: -19.6 }
+ PathCubic { control1X: 182.201; control1Y: -13.6; control2X: 181.401; control2Y: 10.6; x: 181.401; y: 10.6 }
+ PathCubic { control1X: 181.001; control1Y: 19.4; control2X: 187.001; control2Y: 30; x: 187.001; y: 30 }
+ PathCubic { control1X: 189.001; control1Y: 33.8; control2X: 184.801; control2Y: 52; x: 184.801; y: 52 }
+ PathCubic { control1X: 182.801; control1Y: 54.2; control2X: 184.201; control2Y: 55; x: 184.201; y: 55 }
+ PathCubic { control1X: 185.201; control1Y: 56.2; control2X: 192.001; control2Y: 69.4; x: 192.001; y: 69.4 }
+ PathCubic { control1X: 190.201; control1Y: 69.2; control2X: 193.801; control2Y: 72.8; x: 193.801; y: 72.8 }
+ PathCubic { control1X: 199.001; control1Y: 78.8; control2X: 192.601; control2Y: 75.8; x: 192.601; y: 75.8 }
+ PathCubic { control1X: 186.601; control1Y: 74.2; control2X: 193.601; control2Y: 84; x: 193.601; y: 84 }
+ PathCubic { control1X: 194.801; control1Y: 85.8; control2X: 185.801; control2Y: 81.2; x: 185.801; y: 81.2 }
+ PathCubic { control1X: 176.601; control1Y: 80.6; control2X: 188.201; control2Y: 87.8; x: 188.201; y: 87.8 }
+ PathCubic { control1X: 196.801; control1Y: 95; control2X: 185.401; control2Y: 90.6; x: 185.401; y: 90.6 }
+ PathCubic { control1X: 180.801; control1Y: 88.8; control2X: 184.001; control2Y: 95.6; x: 184.001; y: 95.6 }
+ PathCubic { control1X: 187.201; control1Y: 97.2; control2X: 204.401; control2Y: 104.2; x: 204.401; y: 104.2 }
+ PathCubic { control1X: 204.801; control1Y: 108.001; control2X: 201.801; control2Y: 113.001; x: 201.801; y: 113.001 }
+ PathCubic { control1X: 202.201; control1Y: 117.001; control2X: 200.001; control2Y: 120.401; x: 200.001; y: 120.401 }
+ PathCubic { control1X: 198.801; control1Y: 128.601; control2X: 198.201; control2Y: 129.401; x: 198.201; y: 129.401 }
+ PathCubic { control1X: 194.001; control1Y: 129.601; control2X: 186.601; control2Y: 143.401; x: 186.601; y: 143.401 }
+ PathCubic { control1X: 184.801; control1Y: 146.001; control2X: 174.601; control2Y: 158.001; x: 174.601; y: 158.001 }
+ PathCubic { control1X: 172.601; control1Y: 165.001; control2X: 154.601; control2Y: 157.801; x: 154.601; y: 157.801 }
+ PathCubic { control1X: 148.001; control1Y: 161.201; control2X: 150.001; control2Y: 157.801; x: 150.001; y: 157.801 }
+ PathCubic { control1X: 149.601; control1Y: 155.601; control2X: 154.401; control2Y: 149.601; x: 154.401; y: 149.601 }
+ PathCubic { control1X: 161.401; control1Y: 147.001; control2X: 158.801; control2Y: 136.201; x: 158.801; y: 136.201 }
+ PathCubic { control1X: 162.801; control1Y: 134.801; control2X: 151.601; control2Y: 132.001; x: 151.801; y: 130.801 }
+ PathCubic { control1X: 152.001; control1Y: 129.601; control2X: 157.801; control2Y: 128.201; x: 157.801; y: 128.201 }
+ PathCubic { control1X: 165.801; control1Y: 126.201; control2X: 161.401; control2Y: 123.801; x: 161.401; y: 123.801 }
+ PathCubic { control1X: 160.801; control1Y: 119.801; control2X: 163.801; control2Y: 114.201; x: 163.801; y: 114.201 }
+ PathCubic { control1X: 175.401; control1Y: 113.401; control2X: 163.801; control2Y: 97.2; x: 163.801; y: 97.2 }
+ PathCubic { control1X: 153.001; control1Y: 89.6; control2X: 152.001; control2Y: 83.8; x: 152.001; y: 83.8 }
+ PathCubic { control1X: 164.601; control1Y: 75.6; control2X: 156.401; control2Y: 63.2; x: 156.601; y: 59.6 }
+ PathCubic { control1X: 156.801; control1Y: 56; control2X: 158.001; control2Y: 34.4; x: 158.001; y: 34.4 }
+ PathCubic { control1X: 156.001; control1Y: 28.2; control2X: 153.001; control2Y: 14.6; x: 153.001; y: 14.6 }
+ PathCubic { control1X: 155.201; control1Y: 9.4; control2X: 162.601; control2Y: -3.2; x: 162.601; y: -3.2 }
+ PathCubic { control1X: 165.401; control1Y: -7.4; control2X: 174.201; control2Y: -12.2; x: 172.001; y: -15.2 }
+ PathCubic { control1X: 169.801; control1Y: -18.2; control2X: 162.001; control2Y: -16.4; x: 162.001; y: -16.4 }
+ PathCubic { control1X: 154.201; control1Y: -17.8; control2X: 154.801; control2Y: -12.6; x: 154.801; y: -12.6 }
+ PathCubic { control1X: 153.201; control1Y: -11.6; control2X: 152.401; control2Y: -6.6; x: 152.401; y: -6.6 }
+ PathCubic { control1X: 151.68; control1Y: 1.333; control2X: 142.801; control2Y: 7.6; x: 142.801; y: 7.6 }
+ PathCubic { control1X: 131.601; control1Y: 13.8; control2X: 140.801; control2Y: 17.8; x: 140.801; y: 17.8 }
+ PathCubic { control1X: 146.801; control1Y: 24.4; control2X: 137.001; control2Y: 24.6; x: 137.001; y: 24.6 }
+ PathCubic { control1X: 126.001; control1Y: 22.8; control2X: 134.201; control2Y: 33; x: 134.201; y: 33 }
+ PathCubic { control1X: 145.001; control1Y: 45.8; control2X: 142.001; control2Y: 48.6; x: 142.001; y: 48.6 }
+ PathCubic { control1X: 131.801; control1Y: 49.6; control2X: 144.401; control2Y: 58.8; x: 144.401; y: 58.8 }
+ PathCubic { control1X: 144.401; control1Y: 58.8; control2X: 143.601; control2Y: 56.8; x: 143.801; y: 58.6 }
+ PathCubic { control1X: 144.001; control1Y: 60.4; control2X: 147.001; control2Y: 64.6; x: 147.801; y: 66.6 }
+ PathCubic { control1X: 148.601; control1Y: 68.6; control2X: 144.601; control2Y: 68.8; x: 144.601; y: 68.8 }
+ PathCubic { control1X: 145.201; control1Y: 78.4; control2X: 129.801; control2Y: 74.2; x: 129.801; y: 74.2 }
+ PathCubic { control1X: 129.801; control1Y: 74.2; control2X: 129.801; control2Y: 74.2; x: 128.201; y: 74.4 }
+ PathCubic { control1X: 126.601; control1Y: 74.6; control2X: 115.401; control2Y: 73.8; x: 109.601; y: 71.6 }
+ PathCubic { control1X: 103.801; control1Y: 69.4; control2X: 97.001; control2Y: 69.4; x: 97.001; y: 69.4 }
+ PathCubic { control1X: 97.001; control1Y: 69.4; control2X: 93.001; control2Y: 71.2; x: 85.4; y: 71 }
+ PathCubic { control1X: 77.8; control1Y: 70.8; control2X: 69.8; control2Y: 73.6; x: 69.8; y: 73.6 }
+ PathCubic { control1X: 65.4; control1Y: 73.2; control2X: 74; control2Y: 68.8; x: 74.2; y: 69 }
+ PathCubic { control1X: 74.4; control1Y: 69.2; control2X: 80; control2Y: 63.6; x: 72; y: 64.2 }
+ PathCubic { control1X: 50.203; control1Y: 65.835; control2X: 39.4; control2Y: 55.6; x: 39.4; y: 55.6 }
+ PathCubic { control1X: 37.4; control1Y: 54.2; control2X: 34.8; control2Y: 51.4; x: 34.8; y: 51.4 }
+ PathCubic { control1X: 24.8; control1Y: 49.4; control2X: 36.2; control2Y: 63.8; x: 36.2; y: 63.8 }
+ PathCubic { control1X: 37.4; control1Y: 65.2; control2X: 36; control2Y: 66.2; x: 36; y: 66.2 }
+ PathCubic { control1X: 35.2; control1Y: 64.6; control2X: 27.4; control2Y: 59.2; x: 27.4; y: 59.2 }
+ PathCubic { control1X: 24.589; control1Y: 58.227; control2X: 23.226; control2Y: 56.893; x: 20.895; y: 54.407 }
+ }
+
+ ShapePath {
+ fillColor: "#4c0000"
+ strokeWidth: -1
+ PathMove { x: -3; y: 42.8 }
+ PathCubic { control1X: -3; control1Y: 42.8; control2X: 8.6; control2Y: 48.4; x: 11.2; y: 51.2 }
+ PathCubic { control1X: 13.8; control1Y: 54; control2X: 27.8; control2Y: 65.4; x: 27.8; y: 65.4 }
+ PathCubic { control1X: 27.8; control1Y: 65.4; control2X: 22.4; control2Y: 63.4; x: 19.8; y: 61.6 }
+ PathCubic { control1X: 17.2; control1Y: 59.8; control2X: 6.4; control2Y: 51.6; x: 6.4; y: 51.6 }
+ PathCubic { control1X: 6.4; control1Y: 51.6; control2X: 2.6; control2Y: 45.6; x: -3; y: 42.8 }
+ }
+
+ ShapePath {
+ fillColor: "#99cc32"
+ strokeWidth: -1
+ PathMove { x: -61.009; y: 11.603 }
+ PathCubic { control1X: -60.672; control1Y: 11.455; control2X: -61.196; control2Y: 8.743; x: -61.4; y: 8.2 }
+ PathCubic { control1X: -62.422; control1Y: 5.474; control2X: -71.4; control2Y: 4; x: -71.4; y: 4 }
+ PathCubic { control1X: -71.627; control1Y: 5.365; control2X: -71.682; control2Y: 6.961; x: -71.576; y: 8.599 }
+ PathCubic { control1X: -71.576; control1Y: 8.599; control2X: -66.708; control2Y: 14.118; x: -61.009; y: 11.603 }
+ }
+
+ ShapePath {
+ fillColor: "#659900"
+ strokeWidth: -1
+ PathMove { x: -61.009; y: 11.403 }
+ PathCubic { control1X: -61.458; control1Y: 11.561; control2X: -61.024; control2Y: 8.669; x: -61.2; y: 8.2 }
+ PathCubic { control1X: -62.222; control1Y: 5.474; control2X: -71.4; control2Y: 3.9; x: -71.4; y: 3.9 }
+ PathCubic { control1X: -71.627; control1Y: 5.265; control2X: -71.682; control2Y: 6.861; x: -71.576; y: 8.499 }
+ PathCubic { control1X: -71.576; control1Y: 8.499; control2X: -67.308; control2Y: 13.618; x: -61.009; y: 11.403 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -65.4; y: 11.546 }
+ PathCubic { control1X: -66.025; control1Y: 11.546; control2X: -66.531; control2Y: 10.406; x: -66.531; y: 9 }
+ PathCubic { control1X: -66.531; control1Y: 7.595; control2X: -66.025; control2Y: 6.455; x: -65.4; y: 6.455 }
+ PathCubic { control1X: -64.775; control1Y: 6.455; control2X: -64.268; control2Y: 7.595; x: -64.268; y: 9 }
+ PathCubic { control1X: -64.268; control1Y: 10.406; control2X: -64.775; control2Y: 11.546; x: -65.4; y: 11.546 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -65.4; y: 9 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -111; y: 109.601 }
+ PathCubic { control1X: -111; control1Y: 109.601; control2X: -116.6; control2Y: 119.601; x: -91.8; y: 113.601 }
+ PathCubic { control1X: -91.8; control1Y: 113.601; control2X: -77.8; control2Y: 112.401; x: -75.4; y: 110.001 }
+ PathCubic { control1X: -74.2; control1Y: 110.801; control2X: -65.834; control2Y: 113.734; x: -63; y: 114.401 }
+ PathCubic { control1X: -56.2; control1Y: 116.001; control2X: -47.8; control2Y: 106; x: -47.8; y: 106 }
+ PathCubic { control1X: -47.8; control1Y: 106; control2X: -43.2; control2Y: 95.5; x: -40.4; y: 95.5 }
+ PathCubic { control1X: -37.6; control1Y: 95.5; control2X: -40.8; control2Y: 97.1; x: -40.8; y: 97.1 }
+ PathCubic { control1X: -40.8; control1Y: 97.1; control2X: -47.4; control2Y: 107.201; x: -47; y: 108.801 }
+ PathCubic { control1X: -47; control1Y: 108.801; control2X: -52.2; control2Y: 128.801; x: -68.2; y: 129.601 }
+ PathCubic { control1X: -68.2; control1Y: 129.601; control2X: -84.35; control2Y: 130.551; x: -83; y: 136.401 }
+ PathCubic { control1X: -83; control1Y: 136.401; control2X: -74.2; control2Y: 134.001; x: -71.8; y: 136.401 }
+ PathCubic { control1X: -71.8; control1Y: 136.401; control2X: -61; control2Y: 136.001; x: -69; y: 142.401 }
+ PathLine { x: -75.8; y: 154.001 }
+ PathCubic { control1X: -75.8; control1Y: 154.001; control2X: -75.66; control2Y: 157.919; x: -85.8; y: 154.401 }
+ PathCubic { control1X: -95.6; control1Y: 151.001; control2X: -105.9; control2Y: 138.101; x: -105.9; y: 138.101 }
+ PathCubic { control1X: -105.9; control1Y: 138.101; control2X: -121.85; control2Y: 123.551; x: -111; y: 109.601 }
+ }
+
+ ShapePath {
+ fillColor: "#e59999"
+ strokeWidth: -1
+ PathMove { x: -112.2; y: 113.601 }
+ PathCubic { control1X: -112.2; control1Y: 113.601; control2X: -114.2; control2Y: 123.201; x: -77.4; y: 112.801 }
+ PathCubic { control1X: -77.4; control1Y: 112.801; control2X: -73; control2Y: 112.801; x: -70.6; y: 113.601 }
+ PathCubic { control1X: -68.2; control1Y: 114.401; control2X: -56.2; control2Y: 117.201; x: -54.2; y: 116.001 }
+ PathCubic { control1X: -54.2; control1Y: 116.001; control2X: -61.4; control2Y: 129.601; x: -73; y: 128.001 }
+ PathCubic { control1X: -73; control1Y: 128.001; control2X: -86.2; control2Y: 129.601; x: -85.8; y: 134.401 }
+ PathCubic { control1X: -85.8; control1Y: 134.401; control2X: -81.8; control2Y: 141.601; x: -77; y: 144.001 }
+ PathCubic { control1X: -77; control1Y: 144.001; control2X: -74.2; control2Y: 146.401; x: -74.6; y: 149.601 }
+ PathCubic { control1X: -75; control1Y: 152.801; control2X: -77.8; control2Y: 154.401; x: -79.8; y: 155.201 }
+ PathCubic { control1X: -81.8; control1Y: 156.001; control2X: -85; control2Y: 152.801; x: -86.6; y: 152.801 }
+ PathCubic { control1X: -88.2; control1Y: 152.801; control2X: -96.6; control2Y: 146.401; x: -101; y: 141.601 }
+ PathCubic { control1X: -105.4; control1Y: 136.801; control2X: -113.8; control2Y: 124.801; x: -113.4; y: 122.001 }
+ PathCubic { control1X: -113; control1Y: 119.201; control2X: -112.2; control2Y: 113.601; x: -112.2; y: 113.601 }
+ }
+
+ ShapePath {
+ fillColor: "#b26565"
+ strokeWidth: -1
+ PathMove { x: -109; y: 131.051 }
+ PathCubic { control1X: -106.4; control1Y: 135.001; control2X: -103.2; control2Y: 139.201; x: -101; y: 141.601 }
+ PathCubic { control1X: -96.6; control1Y: 146.401; control2X: -88.2; control2Y: 152.801; x: -86.6; y: 152.801 }
+ PathCubic { control1X: -85; control1Y: 152.801; control2X: -81.8; control2Y: 156.001; x: -79.8; y: 155.201 }
+ PathCubic { control1X: -77.8; control1Y: 154.401; control2X: -75; control2Y: 152.801; x: -74.6; y: 149.601 }
+ PathCubic { control1X: -74.2; control1Y: 146.401; control2X: -77; control2Y: 144.001; x: -77; y: 144.001 }
+ PathCubic { control1X: -80.066; control1Y: 142.468; control2X: -82.806; control2Y: 138.976; x: -84.385; y: 136.653 }
+ PathCubic { control1X: -84.385; control1Y: 136.653; control2X: -84.2; control2Y: 139.201; x: -89.4; y: 138.401 }
+ PathCubic { control1X: -94.6; control1Y: 137.601; control2X: -99.8; control2Y: 134.801; x: -101.4; y: 131.601 }
+ PathCubic { control1X: -103; control1Y: 128.401; control2X: -105.4; control2Y: 126.001; x: -103.8; y: 129.601 }
+ PathCubic { control1X: -102.2; control1Y: 133.201; control2X: -99.8; control2Y: 136.801; x: -98.2; y: 137.201 }
+ PathCubic { control1X: -96.6; control1Y: 137.601; control2X: -97; control2Y: 138.801; x: -99.4; y: 138.401 }
+ PathCubic { control1X: -101.8; control1Y: 138.001; control2X: -104.6; control2Y: 137.601; x: -109; y: 132.401 }
+ }
+
+ ShapePath {
+ fillColor: "#992600"
+ strokeWidth: -1
+ PathMove { x: -111.6; y: 110.001 }
+ PathCubic { control1X: -111.6; control1Y: 110.001; control2X: -109.8; control2Y: 96.4; x: -108.6; y: 92.4 }
+ PathCubic { control1X: -108.6; control1Y: 92.4; control2X: -109.4; control2Y: 85.6; x: -107; y: 81.4 }
+ PathCubic { control1X: -104.6; control1Y: 77.2; control2X: -102.6; control2Y: 71; x: -99.6; y: 65.6 }
+ PathCubic { control1X: -96.6; control1Y: 60.2; control2X: -96.4; control2Y: 56.2; x: -92.4; y: 54.6 }
+ PathCubic { control1X: -88.4; control1Y: 53; control2X: -82.4; control2Y: 44.4; x: -79.6; y: 43.4 }
+ PathCubic { control1X: -76.8; control1Y: 42.4; control2X: -77; control2Y: 43.2; x: -77; y: 43.2 }
+ PathCubic { control1X: -77; control1Y: 43.2; control2X: -70.2; control2Y: 28.4; x: -56.6; y: 32.4 }
+ PathCubic { control1X: -56.6; control1Y: 32.4; control2X: -72.8; control2Y: 29.6; x: -57; y: 20.2 }
+ PathCubic { control1X: -57; control1Y: 20.2; control2X: -61.8; control2Y: 21.3; x: -58.5; y: 14.3 }
+ PathCubic { control1X: -56.299; control1Y: 9.632; control2X: -56.8; control2Y: 16.4; x: -67.8; y: 28.2 }
+ PathCubic { control1X: -67.8; control1Y: 28.2; control2X: -72.8; control2Y: 36.8; x: -78; y: 39.8 }
+ PathCubic { control1X: -83.2; control1Y: 42.8; control2X: -95.2; control2Y: 49.8; x: -96.4; y: 53.6 }
+ PathCubic { control1X: -97.6; control1Y: 57.4; control2X: -100.8; control2Y: 63.2; x: -102.8; y: 64.8 }
+ PathCubic { control1X: -104.8; control1Y: 66.4; control2X: -107.6; control2Y: 70.6; x: -108; y: 74 }
+ PathCubic { control1X: -108; control1Y: 74; control2X: -109.2; control2Y: 78; x: -110.6; y: 79.2 }
+ PathCubic { control1X: -112; control1Y: 80.4; control2X: -112.2; control2Y: 83.6; x: -112.2; y: 85.6 }
+ PathCubic { control1X: -112.2; control1Y: 87.6; control2X: -114.2; control2Y: 90.4; x: -114; y: 92.8 }
+ PathCubic { control1X: -114; control1Y: 92.8; control2X: -113.2; control2Y: 111.801; x: -113.6; y: 113.801 }
+ PathLine { x: -111.6; y: 110.001 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeWidth: -1
+ PathMove { x: -120.2; y: 114.601 }
+ PathCubic { control1X: -120.2; control1Y: 114.601; control2X: -122.2; control2Y: 113.201; x: -126.6; y: 119.201 }
+ PathCubic { control1X: -126.6; control1Y: 119.201; control2X: -119.3; control2Y: 152.201; x: -119.3; y: 153.601 }
+ PathCubic { control1X: -119.3; control1Y: 153.601; control2X: -118.2; control2Y: 151.501; x: -119.5; y: 144.301 }
+ PathCubic { control1X: -120.8; control1Y: 137.101; control2X: -121.7; control2Y: 124.401; x: -121.7; y: 124.401 }
+ PathLine { x: -120.2; y: 114.601 }
+ }
+
+ ShapePath {
+ fillColor: "#992600"
+ strokeWidth: -1
+ PathMove { x: -98.6; y: 54 }
+ PathCubic { control1X: -98.6; control1Y: 54; control2X: -116.2; control2Y: 57.2; x: -115.8; y: 86.4 }
+ PathLine { x: -116.6; y: 111.201 }
+ PathCubic { control1X: -116.6; control1Y: 111.201; control2X: -117.8; control2Y: 85.6; x: -119; y: 84 }
+ PathCubic { control1X: -120.2; control1Y: 82.4; control2X: -116.2; control2Y: 71.2; x: -119.4; y: 77.2 }
+ PathCubic { control1X: -119.4; control1Y: 77.2; control2X: -133.4; control2Y: 91.2; x: -125.4; y: 112.401 }
+ PathCubic { control1X: -125.4; control1Y: 112.401; control2X: -123.9; control2Y: 115.701; x: -126.9; y: 111.101 }
+ PathCubic { control1X: -126.9; control1Y: 111.101; control2X: -131.5; control2Y: 98.5; x: -130.4; y: 92.1 }
+ PathCubic { control1X: -130.4; control1Y: 92.1; control2X: -130.2; control2Y: 89.9; x: -128.3; y: 87.1 }
+ PathCubic { control1X: -128.3; control1Y: 87.1; control2X: -119.7; control2Y: 75.4; x: -117; y: 73.1 }
+ PathCubic { control1X: -117; control1Y: 73.1; control2X: -115.2; control2Y: 58.7; x: -99.8; y: 53.5 }
+ PathCubic { control1X: -99.8; control1Y: 53.5; control2X: -94.1; control2Y: 51.2; x: -98.6; y: 54 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 40.8; y: -12.2 }
+ PathCubic { control1X: 41.46; control1Y: -12.554; control2X: 41.451; control2Y: -13.524; x: 42.031; y: -13.697 }
+ PathCubic { control1X: 43.18; control1Y: -14.041; control2X: 43.344; control2Y: -15.108; x: 43.862; y: -15.892 }
+ PathCubic { control1X: 44.735; control1Y: -17.211; control2X: 44.928; control2Y: -18.744; x: 45.51; y: -20.235 }
+ PathCubic { control1X: 45.782; control1Y: -20.935; control2X: 45.809; control2Y: -21.89; x: 45.496; y: -22.55 }
+ PathCubic { control1X: 44.322; control1Y: -25.031; control2X: 43.62; control2Y: -27.48; x: 42.178; y: -29.906 }
+ PathCubic { control1X: 41.91; control1Y: -30.356; control2X: 41.648; control2Y: -31.15; x: 41.447; y: -31.748 }
+ PathCubic { control1X: 40.984; control1Y: -33.132; control2X: 39.727; control2Y: -34.123; x: 38.867; y: -35.443 }
+ PathCubic { control1X: 38.579; control1Y: -35.884; control2X: 39.104; control2Y: -36.809; x: 38.388; y: -36.893 }
+ PathCubic { control1X: 37.491; control1Y: -36.998; control2X: 36.042; control2Y: -37.578; x: 35.809; y: -36.552 }
+ PathCubic { control1X: 35.221; control1Y: -33.965; control2X: 36.232; control2Y: -31.442; x: 37.2; y: -29 }
+ PathCubic { control1X: 36.418; control1Y: -28.308; control2X: 36.752; control2Y: -27.387; x: 36.904; y: -26.62 }
+ PathCubic { control1X: 37.614; control1Y: -23.014; control2X: 36.416; control2Y: -19.662; x: 35.655; y: -16.188 }
+ PathCubic { control1X: 35.632; control1Y: -16.084; control2X: 35.974; control2Y: -15.886; x: 35.946; y: -15.824 }
+ PathCubic { control1X: 34.724; control1Y: -13.138; control2X: 33.272; control2Y: -10.693; x: 31.453; y: -8.312 }
+ PathCubic { control1X: 30.695; control1Y: -7.32; control2X: 29.823; control2Y: -6.404; x: 29.326; y: -5.341 }
+ PathCubic { control1X: 28.958; control1Y: -4.554; control2X: 28.55; control2Y: -3.588; x: 28.8; y: -2.6 }
+ PathCubic { control1X: 25.365; control1Y: 0.18; control2X: 23.115; control2Y: 4.025; x: 20.504; y: 7.871 }
+ PathCubic { control1X: 20.042; control1Y: 8.551; control2X: 20.333; control2Y: 9.76; x: 20.884; y: 10.029 }
+ PathCubic { control1X: 21.697; control1Y: 10.427; control2X: 22.653; control2Y: 9.403; x: 23.123; y: 8.557 }
+ PathCubic { control1X: 23.512; control1Y: 7.859; control2X: 23.865; control2Y: 7.209; x: 24.356; y: 6.566 }
+ PathCubic { control1X: 24.489; control1Y: 6.391; control2X: 24.31; control2Y: 5.972; x: 24.445; y: 5.851 }
+ PathCubic { control1X: 27.078; control1Y: 3.504; control2X: 28.747; control2Y: 0.568; x: 31.2; y: -1.8 }
+ PathCubic { control1X: 33.15; control1Y: -2.129; control2X: 34.687; control2Y: -3.127; x: 36.435; y: -4.14 }
+ PathCubic { control1X: 36.743; control1Y: -4.319; control2X: 37.267; control2Y: -4.07; x: 37.557; y: -4.265 }
+ PathCubic { control1X: 39.31; control1Y: -5.442; control2X: 39.308; control2Y: -7.478; x: 39.414; y: -9.388 }
+ PathCubic { control1X: 39.464; control1Y: -10.272; control2X: 39.66; control2Y: -11.589; x: 40.8; y: -12.2 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 31.959; y: -16.666 }
+ PathCubic { control1X: 32.083; control1Y: -16.743; control2X: 31.928; control2Y: -17.166; x: 32.037; y: -17.382 }
+ PathCubic { control1X: 32.199; control1Y: -17.706; control2X: 32.602; control2Y: -17.894; x: 32.764; y: -18.218 }
+ PathCubic { control1X: 32.873; control1Y: -18.434; control2X: 32.71; control2Y: -18.814; x: 32.846; y: -18.956 }
+ PathCubic { control1X: 35.179; control1Y: -21.403; control2X: 35.436; control2Y: -24.427; x: 34.4; y: -27.4 }
+ PathCubic { control1X: 35.424; control1Y: -28.02; control2X: 35.485; control2Y: -29.282; x: 35.06; y: -30.129 }
+ PathCubic { control1X: 34.207; control1Y: -31.829; control2X: 34.014; control2Y: -33.755; x: 33.039; y: -35.298 }
+ PathCubic { control1X: 32.237; control1Y: -36.567; control2X: 30.659; control2Y: -37.811; x: 29.288; y: -36.508 }
+ PathCubic { control1X: 28.867; control1Y: -36.108; control2X: 28.546; control2Y: -35.321; x: 28.824; y: -34.609 }
+ PathCubic { control1X: 28.888; control1Y: -34.446; control2X: 29.173; control2Y: -34.3; x: 29.146; y: -34.218 }
+ PathCubic { control1X: 29.039; control1Y: -33.894; control2X: 28.493; control2Y: -33.67; x: 28.487; y: -33.398 }
+ PathCubic { control1X: 28.457; control1Y: -31.902; control2X: 27.503; control2Y: -30.391; x: 28.133; y: -29.062 }
+ PathCubic { control1X: 28.905; control1Y: -27.433; control2X: 29.724; control2Y: -25.576; x: 30.4; y: -23.8 }
+ PathCubic { control1X: 29.166; control1Y: -21.684; control2X: 30.199; control2Y: -19.235; x: 28.446; y: -17.358 }
+ PathCubic { control1X: 28.31; control1Y: -17.212; control2X: 28.319; control2Y: -16.826; x: 28.441; y: -16.624 }
+ PathCubic { control1X: 28.733; control1Y: -16.138; control2X: 29.139; control2Y: -15.732; x: 29.625; y: -15.44 }
+ PathCubic { control1X: 29.827; control1Y: -15.319; control2X: 30.175; control2Y: -15.317; x: 30.375; y: -15.441 }
+ PathCubic { control1X: 30.953; control1Y: -15.803; control2X: 31.351; control2Y: -16.29; x: 31.959; y: -16.666 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 94.771; y: -26.977 }
+ PathCubic { control1X: 96.16; control1Y: -25.185; control2X: 96.45; control2Y: -22.39; x: 94.401; y: -21 }
+ PathCubic { control1X: 94.951; control1Y: -17.691; control2X: 98.302; control2Y: -19.67; x: 100.401; y: -20.2 }
+ PathCubic { control1X: 100.292; control1Y: -20.588; control2X: 100.519; control2Y: -20.932; x: 100.802; y: -20.937 }
+ PathCubic { control1X: 101.859; control1Y: -20.952; control2X: 102.539; control2Y: -21.984; x: 103.601; y: -21.8 }
+ PathCubic { control1X: 104.035; control1Y: -23.357; control2X: 105.673; control2Y: -24.059; x: 106.317; y: -25.439 }
+ PathCubic { control1X: 108.043; control1Y: -29.134; control2X: 107.452; control2Y: -33.407; x: 104.868; y: -36.653 }
+ PathCubic { control1X: 104.666; control1Y: -36.907; control2X: 104.883; control2Y: -37.424; x: 104.759; y: -37.786 }
+ PathCubic { control1X: 104.003; control1Y: -39.997; control2X: 101.935; control2Y: -40.312; x: 100.001; y: -41 }
+ PathCubic { control1X: 98.824; control1Y: -44.875; control2X: 98.163; control2Y: -48.906; x: 96.401; y: -52.6 }
+ PathCubic { control1X: 94.787; control1Y: -52.85; control2X: 94.089; control2Y: -54.589; x: 92.752; y: -55.309 }
+ PathCubic { control1X: 91.419; control1Y: -56.028; control2X: 90.851; control2Y: -54.449; x: 90.892; y: -53.403 }
+ PathCubic { control1X: 90.899; control1Y: -53.198; control2X: 91.351; control2Y: -52.974; x: 91.181; y: -52.609 }
+ PathCubic { control1X: 91.105; control1Y: -52.445; control2X: 90.845; control2Y: -52.334; x: 90.845; y: -52.2 }
+ PathCubic { control1X: 90.846; control1Y: -52.065; control2X: 91.067; control2Y: -51.934; x: 91.201; y: -51.8 }
+ PathCubic { control1X: 90.283; control1Y: -50.98; control2X: 88.86; control2Y: -50.503; x: 88.565; y: -49.358 }
+ PathCubic { control1X: 87.611; control1Y: -45.648; control2X: 90.184; control2Y: -42.523; x: 91.852; y: -39.322 }
+ PathCubic { control1X: 92.443; control1Y: -38.187; control2X: 91.707; control2Y: -36.916; x: 90.947; y: -35.708 }
+ PathCubic { control1X: 90.509; control1Y: -35.013; control2X: 90.617; control2Y: -33.886; x: 90.893; y: -33.03 }
+ PathCubic { control1X: 91.645; control1Y: -30.699; control2X: 93.236; control2Y: -28.96; x: 94.771; y: -26.977 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 57.611; y: -8.591 }
+ PathCubic { control1X: 56.124; control1Y: -6.74; control2X: 52.712; control2Y: -4.171; x: 55.629; y: -2.243 }
+ PathCubic { control1X: 55.823; control1Y: -2.114; control2X: 56.193; control2Y: -2.11; x: 56.366; y: -2.244 }
+ PathCubic { control1X: 58.387; control1Y: -3.809; control2X: 60.39; control2Y: -4.712; x: 62.826; y: -5.294 }
+ PathCubic { control1X: 62.95; control1Y: -5.323; control2X: 63.224; control2Y: -4.856; x: 63.593; y: -5.017 }
+ PathCubic { control1X: 65.206; control1Y: -5.72; control2X: 67.216; control2Y: -5.662; x: 68.4; y: -7 }
+ PathCubic { control1X: 72.167; control1Y: -6.776; control2X: 75.732; control2Y: -7.892; x: 79.123; y: -9.2 }
+ PathCubic { control1X: 80.284; control1Y: -9.648; control2X: 81.554; control2Y: -10.207; x: 82.755; y: -10.709 }
+ PathCubic { control1X: 84.131; control1Y: -11.285; control2X: 85.335; control2Y: -12.213; x: 86.447; y: -13.354 }
+ PathCubic { control1X: 86.58; control1Y: -13.49; control2X: 86.934; control2Y: -13.4; x: 87.201; y: -13.4 }
+ PathCubic { control1X: 87.161; control1Y: -14.263; control2X: 88.123; control2Y: -14.39; x: 88.37; y: -15.012 }
+ PathCubic { control1X: 88.462; control1Y: -15.244; control2X: 88.312; control2Y: -15.64; x: 88.445; y: -15.742 }
+ PathCubic { control1X: 90.583; control1Y: -17.372; control2X: 91.503; control2Y: -19.39; x: 90.334; y: -21.767 }
+ PathCubic { control1X: 90.049; control1Y: -22.345; control2X: 89.8; control2Y: -22.963; x: 89.234; y: -23.439 }
+ PathCubic { control1X: 88.149; control1Y: -24.35; control2X: 87.047; control2Y: -23.496; x: 86; y: -23.8 }
+ PathCubic { control1X: 85.841; control1Y: -23.172; control2X: 85.112; control2Y: -23.344; x: 84.726; y: -23.146 }
+ PathCubic { control1X: 83.867; control1Y: -22.707; control2X: 82.534; control2Y: -23.292; x: 81.675; y: -22.854 }
+ PathCubic { control1X: 80.313; control1Y: -22.159; control2X: 79.072; control2Y: -21.99; x: 77.65; y: -21.613 }
+ PathCubic { control1X: 77.338; control1Y: -21.531; control2X: 76.56; control2Y: -21.627; x: 76.4; y: -21 }
+ PathCubic { control1X: 76.266; control1Y: -21.134; control2X: 76.118; control2Y: -21.368; x: 76.012; y: -21.346 }
+ PathCubic { control1X: 74.104; control1Y: -20.95; control2X: 72.844; control2Y: -20.736; x: 71.543; y: -19.044 }
+ PathCubic { control1X: 71.44; control1Y: -18.911; control2X: 70.998; control2Y: -19.09; x: 70.839; y: -18.955 }
+ PathCubic { control1X: 69.882; control1Y: -18.147; control2X: 69.477; control2Y: -16.913; x: 68.376; y: -16.241 }
+ PathCubic { control1X: 68.175; control1Y: -16.118; control2X: 67.823; control2Y: -16.286; x: 67.629; y: -16.157 }
+ PathCubic { control1X: 66.983; control1Y: -15.726; control2X: 66.616; control2Y: -15.085; x: 65.974; y: -14.638 }
+ PathCubic { control1X: 65.645; control1Y: -14.409; control2X: 65.245; control2Y: -14.734; x: 65.277; y: -14.99 }
+ PathCubic { control1X: 65.522; control1Y: -16.937; control2X: 66.175; control2Y: -18.724; x: 65.6; y: -20.6 }
+ PathCubic { control1X: 67.677; control1Y: -23.12; control2X: 70.194; control2Y: -25.069; x: 72; y: -27.8 }
+ PathCubic { control1X: 72.015; control1Y: -29.966; control2X: 72.707; control2Y: -32.112; x: 72.594; y: -34.189 }
+ PathCubic { control1X: 72.584; control1Y: -34.382; control2X: 72.296; control2Y: -35.115; x: 72.17; y: -35.462 }
+ PathCubic { control1X: 71.858; control1Y: -36.316; control2X: 72.764; control2Y: -37.382; x: 71.92; y: -38.106 }
+ PathCubic { control1X: 70.516; control1Y: -39.309; control2X: 69.224; control2Y: -38.433; x: 68.4; y: -37 }
+ PathCubic { control1X: 66.562; control1Y: -36.61; control2X: 64.496; control2Y: -35.917; x: 62.918; y: -37.151 }
+ PathCubic { control1X: 61.911; control1Y: -37.938; control2X: 61.333; control2Y: -38.844; x: 60.534; y: -39.9 }
+ PathCubic { control1X: 59.549; control1Y: -41.202; control2X: 59.884; control2Y: -42.638; x: 59.954; y: -44.202 }
+ PathCubic { control1X: 59.96; control1Y: -44.33; control2X: 59.645; control2Y: -44.466; x: 59.645; y: -44.6 }
+ PathCubic { control1X: 59.646; control1Y: -44.735; control2X: 59.866; control2Y: -44.866; x: 60; y: -45 }
+ PathCubic { control1X: 59.294; control1Y: -45.626; control2X: 59.019; control2Y: -46.684; x: 58; y: -47 }
+ PathCubic { control1X: 58.305; control1Y: -48.092; control2X: 57.629; control2Y: -48.976; x: 56.758; y: -49.278 }
+ PathCubic { control1X: 54.763; control1Y: -49.969; control2X: 53.086; control2Y: -48.057; x: 51.194; y: -47.984 }
+ PathCubic { control1X: 50.68; control1Y: -47.965; control2X: 50.213; control2Y: -49.003; x: 49.564; y: -49.328 }
+ PathCubic { control1X: 49.132; control1Y: -49.544; control2X: 48.428; control2Y: -49.577; x: 48.066; y: -49.311 }
+ PathCubic { control1X: 47.378; control1Y: -48.807; control2X: 46.789; control2Y: -48.693; x: 46.031; y: -48.488 }
+ PathCubic { control1X: 44.414; control1Y: -48.052; control2X: 43.136; control2Y: -46.958; x: 41.656; y: -46.103 }
+ PathCubic { control1X: 40.171; control1Y: -45.246; control2X: 39.216; control2Y: -43.809; x: 38.136; y: -42.489 }
+ PathCubic { control1X: 37.195; control1Y: -41.337; control2X: 37.059; control2Y: -38.923; x: 38.479; y: -38.423 }
+ PathCubic { control1X: 40.322; control1Y: -37.773; control2X: 41.626; control2Y: -40.476; x: 43.592; y: -40.15 }
+ PathCubic { control1X: 43.904; control1Y: -40.099; control2X: 44.11; control2Y: -39.788; x: 44; y: -39.4 }
+ PathCubic { control1X: 44.389; control1Y: -39.291; control2X: 44.607; control2Y: -39.52; x: 44.8; y: -39.8 }
+ PathCubic { control1X: 45.658; control1Y: -38.781; control2X: 46.822; control2Y: -38.444; x: 47.76; y: -37.571 }
+ PathCubic { control1X: 48.73; control1Y: -36.667; control2X: 50.476; control2Y: -37.085; x: 51.491; y: -36.088 }
+ PathCubic { control1X: 53.02; control1Y: -34.586; control2X: 52.461; control2Y: -31.905; x: 54.4; y: -30.6 }
+ PathCubic { control1X: 53.814; control1Y: -29.287; control2X: 53.207; control2Y: -28.01; x: 52.872; y: -26.583 }
+ PathCubic { control1X: 52.59; control1Y: -25.377; control2X: 53.584; control2Y: -24.18; x: 54.795; y: -24.271 }
+ PathCubic { control1X: 56.053; control1Y: -24.365; control2X: 56.315; control2Y: -25.124; x: 56.8; y: -26.2 }
+ PathCubic { control1X: 57.067; control1Y: -25.933; control2X: 57.536; control2Y: -25.636; x: 57.495; y: -25.42 }
+ PathCubic { control1X: 57.038; control1Y: -23.033; control2X: 56.011; control2Y: -21.04; x: 55.553; y: -18.609 }
+ PathCubic { control1X: 55.494; control1Y: -18.292; control2X: 55.189; control2Y: -18.09; x: 54.8; y: -18.2 }
+ PathCubic { control1X: 54.332; control1Y: -14.051; control2X: 50.28; control2Y: -11.657; x: 47.735; y: -8.492 }
+ PathCubic { control1X: 47.332; control1Y: -7.99; control2X: 47.328; control2Y: -6.741; x: 47.737; y: -6.338 }
+ PathCubic { control1X: 49.14; control1Y: -4.951; control2X: 51.1; control2Y: -6.497; x: 52.8; y: -7 }
+ PathCubic { control1X: 53.013; control1Y: -8.206; control2X: 53.872; control2Y: -9.148; x: 55.204; y: -9.092 }
+ PathCubic { control1X: 55.46; control1Y: -9.082; control2X: 55.695; control2Y: -9.624; x: 56.019; y: -9.754 }
+ PathCubic { control1X: 56.367; control1Y: -9.892; control2X: 56.869; control2Y: -9.668; x: 57.155; y: -9.866 }
+ PathCubic { control1X: 58.884; control1Y: -11.061; control2X: 60.292; control2Y: -12.167; x: 62.03; y: -13.356 }
+ PathCubic { control1X: 62.222; control1Y: -13.487; control2X: 62.566; control2Y: -13.328; x: 62.782; y: -13.436 }
+ PathCubic { control1X: 63.107; control1Y: -13.598; control2X: 63.294; control2Y: -13.985; x: 63.617; y: -14.17 }
+ PathCubic { control1X: 63.965; control1Y: -14.37; control2X: 64.207; control2Y: -14.08; x: 64.4; y: -13.8 }
+ PathCubic { control1X: 63.754; control1Y: -13.451; control2X: 63.75; control2Y: -12.494; x: 63.168; y: -12.292 }
+ PathCubic { control1X: 62.393; control1Y: -12.024; control2X: 61.832; control2Y: -11.511; x: 61.158; y: -11.064 }
+ PathCubic { control1X: 60.866; control1Y: -10.871; control2X: 60.207; control2Y: -11.119; x: 60.103; y: -10.94 }
+ PathCubic { control1X: 59.505; control1Y: -9.912; control2X: 58.321; control2Y: -9.474; x: 57.611; y: -8.591 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 2.2; y: -58 }
+ PathCubic { control1X: 2.2; control1Y: -58; control2X: -7.038; control2Y: -60.872; x: -18.2; y: -35.2 }
+ PathCubic { control1X: -18.2; control1Y: -35.2; control2X: -20.6; control2Y: -30; x: -23; y: -28 }
+ PathCubic { control1X: -25.4; control1Y: -26; control2X: -36.6; control2Y: -22.4; x: -38.6; y: -18.4 }
+ PathLine { x: -49; y: -2.4 }
+ PathCubic { control1X: -49; control1Y: -2.4; control2X: -34.2; control2Y: -18.4; x: -31; y: -20.8 }
+ PathCubic { control1X: -31; control1Y: -20.8; control2X: -23; control2Y: -29.2; x: -26.2; y: -22.4 }
+ PathCubic { control1X: -26.2; control1Y: -22.4; control2X: -40.2; control2Y: -11.6; x: -39; y: -2.4 }
+ PathCubic { control1X: -39; control1Y: -2.4; control2X: -44.6; control2Y: 12; x: -45.4; y: 14 }
+ PathCubic { control1X: -45.4; control1Y: 14; control2X: -29.4; control2Y: -18; x: -27; y: -19.2 }
+ PathCubic { control1X: -24.6; control1Y: -20.4; control2X: -23.4; control2Y: -20.4; x: -24.6; y: -16.8 }
+ PathCubic { control1X: -25.8; control1Y: -13.2; control2X: -26.2; control2Y: 3.2; x: -29; y: 5.2 }
+ PathCubic { control1X: -29; control1Y: 5.2; control2X: -21; control2Y: -15.2; x: -21.8; y: -18.4 }
+ PathCubic { control1X: -21.8; control1Y: -18.4; control2X: -18.6; control2Y: -22; x: -16.2; y: -16.8 }
+ PathLine { x: -17.4; y: -0.8 }
+ PathLine { x: -13; y: 11.2 }
+ PathCubic { control1X: -13; control1Y: 11.2; control2X: -15.4; control2Y: 0; x: -13.8; y: -15.6 }
+ PathCubic { control1X: -13.8; control1Y: -15.6; control2X: -15.8; control2Y: -26; x: -11.8; y: -20.4 }
+ PathCubic { control1X: -7.8; control1Y: -14.8; control2X: 1.8; control2Y: -8.8; x: 1.8; y: -4 }
+ PathCubic { control1X: 1.8; control1Y: -4; control2X: -3.4; control2Y: -21.6; x: -12.6; y: -26.4 }
+ PathLine { x: -16.6; y: -20.4 }
+ PathLine { x: -17.8; y: -22.4 }
+ PathCubic { control1X: -17.8; control1Y: -22.4; control2X: -21.4; control2Y: -23.2; x: -17; y: -30 }
+ PathCubic { control1X: -12.6; control1Y: -36.8; control2X: -13; control2Y: -37.6; x: -13; y: -37.6 }
+ PathCubic { control1X: -13; control1Y: -37.6; control2X: -6.6; control2Y: -30.4; x: -5; y: -30.4 }
+ PathCubic { control1X: -5; control1Y: -30.4; control2X: 8.2; control2Y: -38; x: 9.4; y: -13.6 }
+ PathCubic { control1X: 9.4; control1Y: -13.6; control2X: 16.2; control2Y: -28; x: 7; y: -34.8 }
+ PathCubic { control1X: 7; control1Y: -34.8; control2X: -7.8; control2Y: -36.8; x: -6.6; y: -42 }
+ PathLine { x: 0.6; y: -54.4 }
+ PathCubic { control1X: 4.2; control1Y: -59.6; control2X: 2.6; control2Y: -56.8; x: 2.6; y: -56.8 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -17.8; y: -41.6 }
+ PathCubic { control1X: -17.8; control1Y: -41.6; control2X: -30.6; control2Y: -41.6; x: -33.8; y: -36.4 }
+ PathLine { x: -41; y: -26.8 }
+ PathCubic { control1X: -41; control1Y: -26.8; control2X: -23.8; control2Y: -36.8; x: -19.8; y: -38 }
+ PathCubic { control1X: -15.8; control1Y: -39.2; control2X: -17.8; control2Y: -41.6; x: -17.8; y: -41.6 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -57.8; y: -35.2 }
+ PathCubic { control1X: -57.8; control1Y: -35.2; control2X: -59.8; control2Y: -34; x: -60.2; y: -31.2 }
+ PathCubic { control1X: -60.6; control1Y: -28.4; control2X: -63; control2Y: -28; x: -62.2; y: -25.2 }
+ PathCubic { control1X: -61.4; control1Y: -22.4; control2X: -59.4; control2Y: -20; x: -59.4; y: -24 }
+ PathCubic { control1X: -59.4; control1Y: -28; control2X: -57.8; control2Y: -30; x: -57; y: -31.2 }
+ PathCubic { control1X: -56.2; control1Y: -32.4; control2X: -54.6; control2Y: -36.8; x: -57.8; y: -35.2 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -66.6; y: 26 }
+ PathCubic { control1X: -66.6; control1Y: 26; control2X: -75; control2Y: 22; x: -78.2; y: 18.4 }
+ PathCubic { control1X: -81.4; control1Y: 14.8; control2X: -80.948; control2Y: 19.966; x: -85.8; y: 19.6 }
+ PathCubic { control1X: -91.647; control1Y: 19.159; control2X: -90.6; control2Y: 3.2; x: -90.6; y: 3.2 }
+ PathLine { x: -94.6; y: 10.8 }
+ PathCubic { control1X: -94.6; control1Y: 10.8; control2X: -95.8; control2Y: 25.2; x: -87.8; y: 22.8 }
+ PathCubic { control1X: -83.893; control1Y: 21.628; control2X: -82.6; control2Y: 23.2; x: -84.2; y: 24 }
+ PathCubic { control1X: -85.8; control1Y: 24.8; control2X: -78.6; control2Y: 25.2; x: -81.4; y: 26.8 }
+ PathCubic { control1X: -84.2; control1Y: 28.4; control2X: -69.8; control2Y: 23.2; x: -72.2; y: 33.6 }
+ PathLine { x: -66.6; y: 26 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -79.2; y: 40.4 }
+ PathCubic { control1X: -79.2; control1Y: 40.4; control2X: -94.6; control2Y: 44.8; x: -98.2; y: 35.2 }
+ PathCubic { control1X: -98.2; control1Y: 35.2; control2X: -103; control2Y: 37.6; x: -100.8; y: 40.6 }
+ PathCubic { control1X: -98.6; control1Y: 43.6; control2X: -97.4; control2Y: 44; x: -97.4; y: 44 }
+ PathCubic { control1X: -97.4; control1Y: 44; control2X: -92; control2Y: 45.2; x: -92.6; y: 46 }
+ PathCubic { control1X: -93.2; control1Y: 46.8; control2X: -95.6; control2Y: 50.2; x: -95.6; y: 50.2 }
+ PathCubic { control1X: -95.6; control1Y: 50.2; control2X: -85.4; control2Y: 44.2; x: -79.2; y: 40.4 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeWidth: -1
+ PathMove { x: 149.201; y: 118.601 }
+ PathCubic { control1X: 148.774; control1Y: 120.735; control2X: 147.103; control2Y: 121.536; x: 145.201; y: 122.201 }
+ PathCubic { control1X: 143.284; control1Y: 121.243; control2X: 140.686; control2Y: 118.137; x: 138.801; y: 120.201 }
+ PathCubic { control1X: 138.327; control1Y: 119.721; control2X: 137.548; control2Y: 119.661; x: 137.204; y: 118.999 }
+ PathCubic { control1X: 136.739; control1Y: 118.101; control2X: 137.011; control2Y: 117.055; x: 136.669; y: 116.257 }
+ PathCubic { control1X: 136.124; control1Y: 114.985; control2X: 135.415; control2Y: 113.619; x: 135.601; y: 112.201 }
+ PathCubic { control1X: 137.407; control1Y: 111.489; control2X: 138.002; control2Y: 109.583; x: 137.528; y: 107.82 }
+ PathCubic { control1X: 137.459; control1Y: 107.563; control2X: 137.03; control2Y: 107.366; x: 137.23; y: 107.017 }
+ PathCubic { control1X: 137.416; control1Y: 106.694; control2X: 137.734; control2Y: 106.467; x: 138.001; y: 106.2 }
+ PathCubic { control1X: 137.866; control1Y: 106.335; control2X: 137.721; control2Y: 106.568; x: 137.61; y: 106.548 }
+ PathCubic { control1X: 137; control1Y: 106.442; control2X: 137.124; control2Y: 105.805; x: 137.254; y: 105.418 }
+ PathCubic { control1X: 137.839; control1Y: 103.672; control2X: 139.853; control2Y: 103.408; x: 141.201; y: 104.6 }
+ PathCubic { control1X: 141.457; control1Y: 104.035; control2X: 141.966; control2Y: 104.229; x: 142.401; y: 104.2 }
+ PathCubic { control1X: 142.351; control1Y: 103.621; control2X: 142.759; control2Y: 103.094; x: 142.957; y: 102.674 }
+ PathCubic { control1X: 143.475; control1Y: 101.576; control2X: 145.104; control2Y: 102.682; x: 145.901; y: 102.07 }
+ PathCubic { control1X: 146.977; control1Y: 101.245; control2X: 148.04; control2Y: 100.546; x: 149.118; y: 101.149 }
+ PathCubic { control1X: 150.927; control1Y: 102.162; control2X: 152.636; control2Y: 103.374; x: 153.835; y: 105.115 }
+ PathCubic { control1X: 154.41; control1Y: 105.949; control2X: 154.65; control2Y: 107.23; x: 154.592; y: 108.188 }
+ PathCubic { control1X: 154.554; control1Y: 108.835; control2X: 153.173; control2Y: 108.483; x: 152.83; y: 109.412 }
+ PathCubic { control1X: 152.185; control1Y: 111.16; control2X: 154.016; control2Y: 111.679; x: 154.772; y: 113.017 }
+ PathCubic { control1X: 154.97; control1Y: 113.366; control2X: 154.706; control2Y: 113.67; x: 154.391; y: 113.768 }
+ PathCubic { control1X: 153.98; control1Y: 113.896; control2X: 153.196; control2Y: 113.707; x: 153.334; y: 114.16 }
+ PathCubic { control1X: 154.306; control1Y: 117.353; control2X: 151.55; control2Y: 118.031; x: 149.201; y: 118.601 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeWidth: -1
+ PathMove { x: 139.6; y: 138.201 }
+ PathCubic { control1X: 139.593; control1Y: 136.463; control2X: 137.992; control2Y: 134.707; x: 139.201; y: 133.001 }
+ PathCubic { control1X: 139.336; control1Y: 133.135; control2X: 139.467; control2Y: 133.356; x: 139.601; y: 133.356 }
+ PathCubic { control1X: 139.736; control1Y: 133.356; control2X: 139.867; control2Y: 133.135; x: 140.001; y: 133.001 }
+ PathCubic { control1X: 141.496; control1Y: 135.217; control2X: 145.148; control2Y: 136.145; x: 145.006; y: 138.991 }
+ PathCubic { control1X: 144.984; control1Y: 139.438; control2X: 143.897; control2Y: 140.356; x: 144.801; y: 141.001 }
+ PathCubic { control1X: 142.988; control1Y: 142.349; control2X: 142.933; control2Y: 144.719; x: 142.001; y: 146.601 }
+ PathCubic { control1X: 140.763; control1Y: 146.315; control2X: 139.551; control2Y: 145.952; x: 138.401; y: 145.401 }
+ PathCubic { control1X: 138.753; control1Y: 143.915; control2X: 138.636; control2Y: 142.231; x: 139.456; y: 140.911 }
+ PathCubic { control1X: 139.89; control1Y: 140.213; control2X: 139.603; control2Y: 139.134; x: 139.6; y: 138.201 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -26.6; y: 129.201 }
+ PathCubic { control1X: -26.6; control1Y: 129.201; control2X: -43.458; control2Y: 139.337; x: -29.4; y: 124.001 }
+ PathCubic { control1X: -20.6; control1Y: 114.401; control2X: -10.6; control2Y: 108.801; x: -10.6; y: 108.801 }
+ PathCubic { control1X: -10.6; control1Y: 108.801; control2X: -0.2; control2Y: 104.4; x: 3.4; y: 103.2 }
+ PathCubic { control1X: 7; control1Y: 102; control2X: 22.2; control2Y: 96.8; x: 25.4; y: 96.4 }
+ PathCubic { control1X: 28.6; control1Y: 96; control2X: 38.2; control2Y: 92; x: 45; y: 96 }
+ PathCubic { control1X: 51.8; control1Y: 100; control2X: 59.8; control2Y: 104.4; x: 59.8; y: 104.4 }
+ PathCubic { control1X: 59.8; control1Y: 104.4; control2X: 43.4; control2Y: 96; x: 39.8; y: 98.4 }
+ PathCubic { control1X: 36.2; control1Y: 100.8; control2X: 29; control2Y: 100.4; x: 23; y: 103.6 }
+ PathCubic { control1X: 23; control1Y: 103.6; control2X: 8.2; control2Y: 108.001; x: 5; y: 110.001 }
+ PathCubic { control1X: 1.8; control1Y: 112.001; control2X: -8.6; control2Y: 123.601; x: -10.2; y: 122.801 }
+ PathCubic { control1X: -11.8; control1Y: 122.001; control2X: -9.8; control2Y: 121.601; x: -8.6; y: 118.801 }
+ PathCubic { control1X: -7.4; control1Y: 116.001; control2X: -9.4; control2Y: 114.401; x: -17.4; y: 120.801 }
+ PathCubic { control1X: -25.4; control1Y: 127.201; control2X: -26.6; control2Y: 129.201; x: -26.6; y: 129.201 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -19.195; y: 123.234 }
+ PathCubic { control1X: -19.195; control1Y: 123.234; control2X: -17.785; control2Y: 110.194; x: -9.307; y: 111.859 }
+ PathCubic { control1X: -9.307; control1Y: 111.859; control2X: -1.081; control2Y: 107.689; x: 1.641; y: 105.721 }
+ PathCubic { control1X: 1.641; control1Y: 105.721; control2X: 9.78; control2Y: 104.019; x: 11.09; y: 103.402 }
+ PathCubic { control1X: 29.569; control1Y: 94.702; control2X: 44.288; control2Y: 99.221; x: 44.835; y: 98.101 }
+ PathCubic { control1X: 45.381; control1Y: 96.982; control2X: 65.006; control2Y: 104.099; x: 68.615; y: 108.185 }
+ PathCubic { control1X: 69.006; control1Y: 108.628; control2X: 58.384; control2Y: 102.588; x: 48.686; y: 100.697 }
+ PathCubic { control1X: 40.413; control1Y: 99.083; control2X: 18.811; control2Y: 100.944; x: 7.905; y: 106.48 }
+ PathCubic { control1X: 4.932; control1Y: 107.989; control2X: -4.013; control2Y: 113.773; x: -6.544; y: 113.662 }
+ PathCubic { control1X: -9.075; control1Y: 113.55; control2X: -19.195; control2Y: 123.234; x: -19.195; y: 123.234 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -23; y: 148.801 }
+ PathCubic { control1X: -23; control1Y: 148.801; control2X: -38.2; control2Y: 146.401; x: -21.4; y: 144.801 }
+ PathCubic { control1X: -21.4; control1Y: 144.801; control2X: -3.4; control2Y: 142.801; x: 0.6; y: 137.601 }
+ PathCubic { control1X: 0.6; control1Y: 137.601; control2X: 14.2; control2Y: 128.401; x: 17; y: 128.001 }
+ PathCubic { control1X: 19.8; control1Y: 127.601; control2X: 49.8; control2Y: 120.401; x: 50.2; y: 118.001 }
+ PathCubic { control1X: 50.6; control1Y: 115.601; control2X: 56.2; control2Y: 115.601; x: 57.8; y: 116.401 }
+ PathCubic { control1X: 59.4; control1Y: 117.201; control2X: 58.6; control2Y: 118.401; x: 55.8; y: 119.201 }
+ PathCubic { control1X: 53; control1Y: 120.001; control2X: 21.8; control2Y: 136.401; x: 15.4; y: 137.601 }
+ PathCubic { control1X: 9; control1Y: 138.801; control2X: -2.6; control2Y: 146.401; x: -7.4; y: 147.601 }
+ PathCubic { control1X: -12.2; control1Y: 148.801; control2X: -23; control2Y: 148.801; x: -23; y: 148.801 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -3.48; y: 141.403 }
+ PathCubic { control1X: -3.48; control1Y: 141.403; control2X: -12.062; control2Y: 140.574; x: -3.461; y: 139.755 }
+ PathCubic { control1X: -3.461; control1Y: 139.755; control2X: 5.355; control2Y: 136.331; x: 7.403; y: 133.668 }
+ PathCubic { control1X: 7.403; control1Y: 133.668; control2X: 14.367; control2Y: 128.957; x: 15.8; y: 128.753 }
+ PathCubic { control1X: 17.234; control1Y: 128.548; control2X: 31.194; control2Y: 124.861; x: 31.399; y: 123.633 }
+ PathCubic { control1X: 31.604; control1Y: 122.404; control2X: 65.67; control2Y: 109.823; x: 70.09; y: 113.013 }
+ PathCubic { control1X: 73.001; control1Y: 115.114; control2X: 63.1; control2Y: 113.437; x: 53.466; y: 117.847 }
+ PathCubic { control1X: 52.111; control1Y: 118.467; control2X: 18.258; control2Y: 133.054; x: 14.981; y: 133.668 }
+ PathCubic { control1X: 11.704; control1Y: 134.283; control2X: 5.765; control2Y: 138.174; x: 3.307; y: 138.788 }
+ PathCubic { control1X: 0.85; control1Y: 139.403; control2X: -3.48; control2Y: 141.403; x: -3.48; y: 141.403 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -11.4; y: 143.601 }
+ PathCubic { control1X: -11.4; control1Y: 143.601; control2X: -6.2; control2Y: 143.201; x: -7.4; y: 144.801 }
+ PathCubic { control1X: -8.6; control1Y: 146.401; control2X: -11; control2Y: 145.601; x: -11; y: 145.601 }
+ PathLine { x: -11.4; y: 143.601 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -18.6; y: 145.201 }
+ PathCubic { control1X: -18.6; control1Y: 145.201; control2X: -13.4; control2Y: 144.801; x: -14.6; y: 146.401 }
+ PathCubic { control1X: -15.8; control1Y: 148.001; control2X: -18.2; control2Y: 147.201; x: -18.2; y: 147.201 }
+ PathLine { x: -18.6; y: 145.201 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -29; y: 146.801 }
+ PathCubic { control1X: -29; control1Y: 146.801; control2X: -23.8; control2Y: 146.401; x: -25; y: 148.001 }
+ PathCubic { control1X: -26.2; control1Y: 149.601; control2X: -28.6; control2Y: 148.801; x: -28.6; y: 148.801 }
+ PathLine { x: -29; y: 146.801 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -36.6; y: 147.601 }
+ PathCubic { control1X: -36.6; control1Y: 147.601; control2X: -31.4; control2Y: 147.201; x: -32.6; y: 148.801 }
+ PathCubic { control1X: -33.8; control1Y: 150.401; control2X: -36.2; control2Y: 149.601; x: -36.2; y: 149.601 }
+ PathLine { x: -36.6; y: 147.601 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 1.8; y: 108.001 }
+ PathCubic { control1X: 1.8; control1Y: 108.001; control2X: 6.2; control2Y: 108.001; x: 5; y: 109.601 }
+ PathCubic { control1X: 3.8; control1Y: 111.201; control2X: 0.6; control2Y: 110.801; x: 0.6; y: 110.801 }
+ PathLine { x: 1.8; y: 108.001 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -8.2; y: 113.601 }
+ PathCubic { control1X: -8.2; control1Y: 113.601; control2X: -1.694; control2Y: 111.46; x: -4.2; y: 114.801 }
+ PathCubic { control1X: -5.4; control1Y: 116.401; control2X: -7.8; control2Y: 115.601; x: -7.8; y: 115.601 }
+ PathLine { x: -8.2; y: 113.601 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -19.4; y: 118.401 }
+ PathCubic { control1X: -19.4; control1Y: 118.401; control2X: -14.2; control2Y: 118.001; x: -15.4; y: 119.601 }
+ PathCubic { control1X: -16.6; control1Y: 121.201; control2X: -19; control2Y: 120.401; x: -19; y: 120.401 }
+ PathLine { x: -19.4; y: 118.401 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -27; y: 124.401 }
+ PathCubic { control1X: -27; control1Y: 124.401; control2X: -21.8; control2Y: 124.001; x: -23; y: 125.601 }
+ PathCubic { control1X: -24.2; control1Y: 127.201; control2X: -26.6; control2Y: 126.401; x: -26.6; y: 126.401 }
+ PathLine { x: -27; y: 124.401 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -33.8; y: 129.201 }
+ PathCubic { control1X: -33.8; control1Y: 129.201; control2X: -28.6; control2Y: 128.801; x: -29.8; y: 130.401 }
+ PathCubic { control1X: -31; control1Y: 132.001; control2X: -33.4; control2Y: 131.201; x: -33.4; y: 131.201 }
+ PathLine { x: -33.8; y: 129.201 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 5.282; y: 135.598 }
+ PathCubic { control1X: 5.282; control1Y: 135.598; control2X: 12.203; control2Y: 135.066; x: 10.606; y: 137.195 }
+ PathCubic { control1X: 9.009; control1Y: 139.325; control2X: 5.814; control2Y: 138.26; x: 5.814; y: 138.26 }
+ PathLine { x: 5.282; y: 135.598 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 15.682; y: 130.798 }
+ PathCubic { control1X: 15.682; control1Y: 130.798; control2X: 22.603; control2Y: 130.266; x: 21.006; y: 132.395 }
+ PathCubic { control1X: 19.409; control1Y: 134.525; control2X: 16.214; control2Y: 133.46; x: 16.214; y: 133.46 }
+ PathLine { x: 15.682; y: 130.798 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 26.482; y: 126.398 }
+ PathCubic { control1X: 26.482; control1Y: 126.398; control2X: 33.403; control2Y: 125.866; x: 31.806; y: 127.995 }
+ PathCubic { control1X: 30.209; control1Y: 130.125; control2X: 27.014; control2Y: 129.06; x: 27.014; y: 129.06 }
+ PathLine { x: 26.482; y: 126.398 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 36.882; y: 121.598 }
+ PathCubic { control1X: 36.882; control1Y: 121.598; control2X: 43.803; control2Y: 121.066; x: 42.206; y: 123.195 }
+ PathCubic { control1X: 40.609; control1Y: 125.325; control2X: 37.414; control2Y: 124.26; x: 37.414; y: 124.26 }
+ PathLine { x: 36.882; y: 121.598 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 9.282; y: 103.598 }
+ PathCubic { control1X: 9.282; control1Y: 103.598; control2X: 16.203; control2Y: 103.066; x: 14.606; y: 105.195 }
+ PathCubic { control1X: 13.009; control1Y: 107.325; control2X: 9.014; control2Y: 107.06; x: 9.014; y: 107.06 }
+ PathLine { x: 9.282; y: 103.598 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 19.282; y: 100.398 }
+ PathCubic { control1X: 19.282; control1Y: 100.398; control2X: 26.203; control2Y: 99.866; x: 24.606; y: 101.995 }
+ PathCubic { control1X: 23.009; control1Y: 104.125; control2X: 18.614; control2Y: 103.86; x: 18.614; y: 103.86 }
+ PathLine { x: 19.282; y: 100.398 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -3.4; y: 140.401 }
+ PathCubic { control1X: -3.4; control1Y: 140.401; control2X: 1.8; control2Y: 140.001; x: 0.6; y: 141.601 }
+ PathCubic { control1X: -0.6; control1Y: 143.201; control2X: -3; control2Y: 142.401; x: -3; y: 142.401 }
+ PathLine { x: -3.4; y: 140.401 }
+ }
+
+ ShapePath {
+ fillColor: "#992600"
+ strokeWidth: -1
+ PathMove { x: -76.6; y: 41.2 }
+ PathCubic { control1X: -76.6; control1Y: 41.2; control2X: -81; control2Y: 50; x: -81.4; y: 53.2 }
+ PathCubic { control1X: -81.4; control1Y: 53.2; control2X: -80.6; control2Y: 44.4; x: -79.4; y: 42.4 }
+ PathCubic { control1X: -78.2; control1Y: 40.4; control2X: -76.6; control2Y: 41.2; x: -76.6; y: 41.2 }
+ }
+
+ ShapePath {
+ fillColor: "#992600"
+ strokeWidth: -1
+ PathMove { x: -95; y: 55.2 }
+ PathCubic { control1X: -95; control1Y: 55.2; control2X: -98.2; control2Y: 69.6; x: -97.8; y: 72.4 }
+ PathCubic { control1X: -97.8; control1Y: 72.4; control2X: -99; control2Y: 60.8; x: -98.6; y: 59.6 }
+ PathCubic { control1X: -98.2; control1Y: 58.4; control2X: -95; control2Y: 55.2; x: -95; y: 55.2 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -74.2; y: -19.4 }
+ PathLine { x: -74.4; y: -16.2 }
+ PathLine { x: -76.6; y: -16 }
+ PathCubic { control1X: -76.6; control1Y: -16; control2X: -62.4; control2Y: -3.4; x: -61.8; y: 4.2 }
+ PathCubic { control1X: -61.8; control1Y: 4.2; control2X: -61; control2Y: -4; x: -74.2; y: -19.4 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -70.216; y: -18.135 }
+ PathCubic { control1X: -70.647; control1Y: -18.551; control2X: -70.428; control2Y: -19.296; x: -70.836; y: -19.556 }
+ PathCubic { control1X: -71.645; control1Y: -20.072; control2X: -69.538; control2Y: -20.129; x: -69.766; y: -20.845 }
+ PathCubic { control1X: -70.149; control1Y: -22.051; control2X: -69.962; control2Y: -22.072; x: -70.084; y: -23.348 }
+ PathCubic { control1X: -70.141; control1Y: -23.946; control2X: -69.553; control2Y: -25.486; x: -69.168; y: -25.926 }
+ PathCubic { control1X: -67.722; control1Y: -27.578; control2X: -69.046; control2Y: -30.51; x: -67.406; y: -32.061 }
+ PathCubic { control1X: -67.102; control1Y: -32.35; control2X: -66.726; control2Y: -32.902; x: -66.441; y: -33.32 }
+ PathCubic { control1X: -65.782; control1Y: -34.283; control2X: -64.598; control2Y: -34.771; x: -63.648; y: -35.599 }
+ PathCubic { control1X: -63.33; control1Y: -35.875; control2X: -63.531; control2Y: -36.702; x: -62.962; y: -36.61 }
+ PathCubic { control1X: -62.248; control1Y: -36.495; control2X: -61.007; control2Y: -36.625; x: -61.052; y: -35.784 }
+ PathCubic { control1X: -61.165; control1Y: -33.664; control2X: -62.494; control2Y: -31.944; x: -63.774; y: -30.276 }
+ PathCubic { control1X: -63.323; control1Y: -29.572; control2X: -63.781; control2Y: -28.937; x: -64.065; y: -28.38 }
+ PathCubic { control1X: -65.4; control1Y: -25.76; control2X: -65.211; control2Y: -22.919; x: -65.385; y: -20.079 }
+ PathCubic { control1X: -65.39; control1Y: -19.994; control2X: -65.697; control2Y: -19.916; x: -65.689; y: -19.863 }
+ PathCubic { control1X: -65.336; control1Y: -17.528; control2X: -64.752; control2Y: -15.329; x: -63.873; y: -13.1 }
+ PathCubic { control1X: -63.507; control1Y: -12.17; control2X: -63.036; control2Y: -11.275; x: -62.886; y: -10.348 }
+ PathCubic { control1X: -62.775; control1Y: -9.662; control2X: -62.672; control2Y: -8.829; x: -63.08; y: -8.124 }
+ PathCubic { control1X: -61.045; control1Y: -5.234; control2X: -62.354; control2Y: -2.583; x: -61.185; y: 0.948 }
+ PathCubic { control1X: -60.978; control1Y: 1.573; control2X: -59.286; control2Y: 3.487; x: -59.749; y: 3.326 }
+ PathCubic { control1X: -62.262; control1Y: 2.455; control2X: -62.374; control2Y: 2.057; x: -62.551; y: 1.304 }
+ PathCubic { control1X: -62.697; control1Y: 0.681; control2X: -63.027; control2Y: -0.696; x: -63.264; y: -1.298 }
+ PathCubic { control1X: -63.328; control1Y: -1.462; control2X: -63.499; control2Y: -3.346; x: -63.577; y: -3.468 }
+ PathCubic { control1X: -65.09; control1Y: -5.85; control2X: -63.732; control2Y: -5.674; x: -65.102; y: -8.032 }
+ PathCubic { control1X: -66.53; control1Y: -8.712; control2X: -67.496; control2Y: -9.816; x: -68.619; y: -10.978 }
+ PathCubic { control1X: -68.817; control1Y: -11.182; control2X: -67.674; control2Y: -11.906; x: -67.855; y: -12.119 }
+ PathCubic { control1X: -68.947; control1Y: -13.408; control2X: -70.1; control2Y: -14.175; x: -69.764; y: -15.668 }
+ PathCubic { control1X: -69.609; control1Y: -16.358; control2X: -69.472; control2Y: -17.415; x: -70.216; y: -18.135 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -73.8; y: -16.4 }
+ PathCubic { control1X: -73.8; control1Y: -16.4; control2X: -73.4; control2Y: -9.6; x: -71; y: -8 }
+ PathCubic { control1X: -68.6; control1Y: -6.4; control2X: -69.8; control2Y: -7.2; x: -73; y: -8.4 }
+ PathCubic { control1X: -76.2; control1Y: -9.6; control2X: -75; control2Y: -10.4; x: -75; y: -10.4 }
+ PathCubic { control1X: -75; control1Y: -10.4; control2X: -77.8; control2Y: -10; x: -75.4; y: -8 }
+ PathCubic { control1X: -73; control1Y: -6; control2X: -69.4; control2Y: -3.6; x: -71; y: -3.6 }
+ PathCubic { control1X: -72.6; control1Y: -3.6; control2X: -80.2; control2Y: -7.6; x: -80.2; y: -10.4 }
+ PathCubic { control1X: -80.2; control1Y: -13.2; control2X: -81.2; control2Y: -17.3; x: -81.2; y: -17.3 }
+ PathCubic { control1X: -81.2; control1Y: -17.3; control2X: -80.1; control2Y: -18.1; x: -75.3; y: -18 }
+ PathCubic { control1X: -75.3; control1Y: -18; control2X: -73.9; control2Y: -17.3; x: -73.8; y: -16.4 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: -74.6; y: 2.2 }
+ PathCubic { control1X: -74.6; control1Y: 2.2; control2X: -83.12; control2Y: -0.591; x: -101.6; y: 2.8 }
+ PathCubic { control1X: -101.6; control1Y: 2.8; control2X: -92.569; control2Y: 0.722; x: -73.8; y: 3 }
+ PathCubic { control1X: -63.5; control1Y: 4.25; control2X: -74.6; control2Y: 2.2; x: -74.6; y: 2.2 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: -72.502; y: 2.129 }
+ PathCubic { control1X: -72.502; control1Y: 2.129; control2X: -80.748; control2Y: -1.389; x: -99.453; y: 0.392 }
+ PathCubic { control1X: -99.453; control1Y: 0.392; control2X: -90.275; control2Y: -0.897; x: -71.774; y: 2.995 }
+ PathCubic { control1X: -61.62; control1Y: 5.131; control2X: -72.502; control2Y: 2.129; x: -72.502; y: 2.129 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: -70.714; y: 2.222 }
+ PathCubic { control1X: -70.714; control1Y: 2.222; control2X: -78.676; control2Y: -1.899; x: -97.461; y: -1.514 }
+ PathCubic { control1X: -97.461; control1Y: -1.514; control2X: -88.213; control2Y: -2.118; x: -70.052; y: 3.14 }
+ PathCubic { control1X: -60.086; control1Y: 6.025; control2X: -70.714; control2Y: 2.222; x: -70.714; y: 2.222 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: -69.444; y: 2.445 }
+ PathCubic { control1X: -69.444; control1Y: 2.445; control2X: -76.268; control2Y: -1.862; x: -93.142; y: -2.96 }
+ PathCubic { control1X: -93.142; control1Y: -2.96; control2X: -84.803; control2Y: -2.79; x: -68.922; y: 3.319 }
+ PathCubic { control1X: -60.206; control1Y: 6.672; control2X: -69.444; control2Y: 2.445; x: -69.444; y: 2.445 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 45.84; y: 12.961 }
+ PathCubic { control1X: 45.84; control1Y: 12.961; control2X: 44.91; control2Y: 13.605; x: 45.124; y: 12.424 }
+ PathCubic { control1X: 45.339; control1Y: 11.243; control2X: 73.547; control2Y: -1.927; x: 77.161; y: -1.677 }
+ PathCubic { control1X: 77.161; control1Y: -1.677; control2X: 46.913; control2Y: 11.529; x: 45.84; y: 12.961 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 42.446; y: 13.6 }
+ PathCubic { control1X: 42.446; control1Y: 13.6; control2X: 41.57; control2Y: 14.315; x: 41.691; y: 13.121 }
+ PathCubic { control1X: 41.812; control1Y: 11.927; control2X: 68.899; control2Y: -3.418; x: 72.521; y: -3.452 }
+ PathCubic { control1X: 72.521; control1Y: -3.452; control2X: 43.404; control2Y: 12.089; x: 42.446; y: 13.6 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 39.16; y: 14.975 }
+ PathCubic { control1X: 39.16; control1Y: 14.975; control2X: 38.332; control2Y: 15.747; x: 38.374; y: 14.547 }
+ PathCubic { control1X: 38.416; control1Y: 13.348; control2X: 58.233; control2Y: -2.149; x: 68.045; y: -4.023 }
+ PathCubic { control1X: 68.045; control1Y: -4.023; control2X: 50.015; control2Y: 4.104; x: 39.16; y: 14.975 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 36.284; y: 16.838 }
+ PathCubic { control1X: 36.284; control1Y: 16.838; control2X: 35.539; control2Y: 17.532; x: 35.577; y: 16.453 }
+ PathCubic { control1X: 35.615; control1Y: 15.373; control2X: 53.449; control2Y: 1.426; x: 62.28; y: -0.26 }
+ PathCubic { control1X: 62.28; control1Y: -0.26; control2X: 46.054; control2Y: 7.054; x: 36.284; y: 16.838 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: 4.6; y: 164.801 }
+ PathCubic { control1X: 4.6; control1Y: 164.801; control2X: -10.6; control2Y: 162.401; x: 6.2; y: 160.801 }
+ PathCubic { control1X: 6.2; control1Y: 160.801; control2X: 24.2; control2Y: 158.801; x: 28.2; y: 153.601 }
+ PathCubic { control1X: 28.2; control1Y: 153.601; control2X: 41.8; control2Y: 144.401; x: 44.6; y: 144.001 }
+ PathCubic { control1X: 47.4; control1Y: 143.601; control2X: 63.8; control2Y: 140.001; x: 64.2; y: 137.601 }
+ PathCubic { control1X: 64.6; control1Y: 135.201; control2X: 70.6; control2Y: 132.801; x: 72.2; y: 133.601 }
+ PathCubic { control1X: 73.8; control1Y: 134.401; control2X: 73.8; control2Y: 143.601; x: 71; y: 144.401 }
+ PathCubic { control1X: 68.2; control1Y: 145.201; control2X: 49.4; control2Y: 152.401; x: 43; y: 153.601 }
+ PathCubic { control1X: 36.6; control1Y: 154.801; control2X: 25; control2Y: 162.401; x: 20.2; y: 163.601 }
+ PathCubic { control1X: 15.4; control1Y: 164.801; control2X: 4.6; control2Y: 164.801; x: 4.6; y: 164.801 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 77.6; y: 127.401 }
+ PathCubic { control1X: 77.6; control1Y: 127.401; control2X: 74.6; control2Y: 129.001; x: 73.4; y: 131.601 }
+ PathCubic { control1X: 73.4; control1Y: 131.601; control2X: 67; control2Y: 142.201; x: 52.8; y: 145.401 }
+ PathCubic { control1X: 52.8; control1Y: 145.401; control2X: 29.8; control2Y: 154.401; x: 22; y: 156.401 }
+ PathCubic { control1X: 22; control1Y: 156.401; control2X: 8.6; control2Y: 161.401; x: 1.2; y: 160.601 }
+ PathCubic { control1X: 1.2; control1Y: 160.601; control2X: -5.8; control2Y: 160.801; x: 0.4; y: 162.401 }
+ PathCubic { control1X: 0.4; control1Y: 162.401; control2X: 20.6; control2Y: 160.401; x: 24; y: 158.601 }
+ PathCubic { control1X: 24; control1Y: 158.601; control2X: 39.6; control2Y: 153.401; x: 42.6; y: 150.801 }
+ PathCubic { control1X: 45.6; control1Y: 148.201; control2X: 63.8; control2Y: 143.201; x: 66; y: 141.201 }
+ PathCubic { control1X: 68.2; control1Y: 139.201; control2X: 78; control2Y: 130.801; x: 77.6; y: 127.401 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 18.882; y: 158.911 }
+ PathCubic { control1X: 18.882; control1Y: 158.911; control2X: 24.111; control2Y: 158.685; x: 22.958; y: 160.234 }
+ PathCubic { control1X: 21.805; control1Y: 161.784; control2X: 19.357; control2Y: 160.91; x: 19.357; y: 160.91 }
+ PathLine { x: 18.882; y: 158.911 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 11.68; y: 160.263 }
+ PathCubic { control1X: 11.68; control1Y: 160.263; control2X: 16.908; control2Y: 160.037; x: 15.756; y: 161.586 }
+ PathCubic { control1X: 14.603; control1Y: 163.136; control2X: 12.155; control2Y: 162.263; x: 12.155; y: 162.263 }
+ PathLine { x: 11.68; y: 160.263 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 1.251; y: 161.511 }
+ PathCubic { control1X: 1.251; control1Y: 161.511; control2X: 6.48; control2Y: 161.284; x: 5.327; y: 162.834 }
+ PathCubic { control1X: 4.174; control1Y: 164.383; control2X: 1.726; control2Y: 163.51; x: 1.726; y: 163.51 }
+ PathLine { x: 1.251; y: 161.511 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -6.383; y: 162.055 }
+ PathCubic { control1X: -6.383; control1Y: 162.055; control2X: -1.154; control2Y: 161.829; x: -2.307; y: 163.378 }
+ PathCubic { control1X: -3.46; control1Y: 164.928; control2X: -5.908; control2Y: 164.054; x: -5.908; y: 164.054 }
+ PathLine { x: -6.383; y: 162.055 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 35.415; y: 151.513 }
+ PathCubic { control1X: 35.415; control1Y: 151.513; control2X: 42.375; control2Y: 151.212; x: 40.84; y: 153.274 }
+ PathCubic { control1X: 39.306; control1Y: 155.336; control2X: 36.047; control2Y: 154.174; x: 36.047; y: 154.174 }
+ PathLine { x: 35.415; y: 151.513 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 45.73; y: 147.088 }
+ PathCubic { control1X: 45.73; control1Y: 147.088; control2X: 51.689; control2Y: 143.787; x: 51.155; y: 148.849 }
+ PathCubic { control1X: 50.885; control1Y: 151.405; control2X: 46.362; control2Y: 149.749; x: 46.362; y: 149.749 }
+ PathLine { x: 45.73; y: 147.088 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 54.862; y: 144.274 }
+ PathCubic { control1X: 54.862; control1Y: 144.274; control2X: 62.021; control2Y: 140.573; x: 60.287; y: 146.035 }
+ PathCubic { control1X: 59.509; control1Y: 148.485; control2X: 55.493; control2Y: 146.935; x: 55.493; y: 146.935 }
+ PathLine { x: 54.862; y: 144.274 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 64.376; y: 139.449 }
+ PathCubic { control1X: 64.376; control1Y: 139.449; control2X: 68.735; control2Y: 134.548; x: 69.801; y: 141.21 }
+ PathCubic { control1X: 70.207; control1Y: 143.748; control2X: 65.008; control2Y: 142.11; x: 65.008; y: 142.11 }
+ PathLine { x: 64.376; y: 139.449 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 26.834; y: 155.997 }
+ PathCubic { control1X: 26.834; control1Y: 155.997; control2X: 32.062; control2Y: 155.77; x: 30.91; y: 157.32 }
+ PathCubic { control1X: 29.757; control1Y: 158.869; control2X: 27.308; control2Y: 157.996; x: 27.308; y: 157.996 }
+ PathLine { x: 26.834; y: 155.997 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 62.434; y: 34.603 }
+ PathCubic { control1X: 62.434; control1Y: 34.603; control2X: 61.708; control2Y: 35.268; x: 61.707; y: 34.197 }
+ PathCubic { control1X: 61.707; control1Y: 33.127; control2X: 79.191; control2Y: 19.863; x: 88.034; y: 18.479 }
+ PathCubic { control1X: 88.034; control1Y: 18.479; control2X: 71.935; control2Y: 25.208; x: 62.434; y: 34.603 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: 65.4; y: 98.4 }
+ PathCubic { control1X: 65.4; control1Y: 98.4; control2X: 87.401; control2Y: 120.801; x: 96.601; y: 124.401 }
+ PathCubic { control1X: 96.601; control1Y: 124.401; control2X: 105.801; control2Y: 135.601; x: 101.801; y: 161.601 }
+ PathCubic { control1X: 101.801; control1Y: 161.601; control2X: 98.601; control2Y: 169.201; x: 95.401; y: 148.401 }
+ PathCubic { control1X: 95.401; control1Y: 148.401; control2X: 98.601; control2Y: 123.201; x: 87.401; y: 139.201 }
+ PathCubic { control1X: 87.401; control1Y: 139.201; control2X: 79; control2Y: 129.301; x: 85.4; y: 129.601 }
+ PathCubic { control1X: 85.4; control1Y: 129.601; control2X: 88.601; control2Y: 131.601; x: 89.001; y: 130.001 }
+ PathCubic { control1X: 89.401; control1Y: 128.401; control2X: 81.4; control2Y: 114.801; x: 64.2; y: 100.4 }
+ PathCubic { control1X: 47; control1Y: 86; control2X: 65.4; control2Y: 98.4; x: 65.4; y: 98.4 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 7; y: 137.201 }
+ PathCubic { control1X: 7; control1Y: 137.201; control2X: 6.8; control2Y: 135.401; x: 8.6; y: 136.201 }
+ PathCubic { control1X: 10.4; control1Y: 137.001; control2X: 104.601; control2Y: 143.201; x: 136.201; y: 167.201 }
+ PathCubic { control1X: 136.201; control1Y: 167.201; control2X: 91.001; control2Y: 144.001; x: 7; y: 137.201 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 17.4; y: 132.801 }
+ PathCubic { control1X: 17.4; control1Y: 132.801; control2X: 17.2; control2Y: 131.001; x: 19; y: 131.801 }
+ PathCubic { control1X: 20.8; control1Y: 132.601; control2X: 157.401; control2Y: 131.601; x: 181.001; y: 164.001 }
+ PathCubic { control1X: 181.001; control1Y: 164.001; control2X: 159.001; control2Y: 138.801; x: 17.4; y: 132.801 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 29; y: 128.801 }
+ PathCubic { control1X: 29; control1Y: 128.801; control2X: 28.8; control2Y: 127.001; x: 30.6; y: 127.801 }
+ PathCubic { control1X: 32.4; control1Y: 128.601; control2X: 205.801; control2Y: 115.601; x: 229.401; y: 148.001 }
+ PathCubic { control1X: 229.401; control1Y: 148.001; control2X: 219.801; control2Y: 122.401; x: 29; y: 128.801 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 39; y: 124.001 }
+ PathCubic { control1X: 39; control1Y: 124.001; control2X: 38.8; control2Y: 122.201; x: 40.6; y: 123.001 }
+ PathCubic { control1X: 42.4; control1Y: 123.801; control2X: 164.601; control2Y: 85.2; x: 188.201; y: 117.601 }
+ PathCubic { control1X: 188.201; control1Y: 117.601; control2X: 174.801; control2Y: 93; x: 39; y: 124.001 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: -19; y: 146.801 }
+ PathCubic { control1X: -19; control1Y: 146.801; control2X: -19.2; control2Y: 145.001; x: -17.4; y: 145.801 }
+ PathCubic { control1X: -15.6; control1Y: 146.601; control2X: 2.2; control2Y: 148.801; x: 4.2; y: 187.601 }
+ PathCubic { control1X: 4.2; control1Y: 187.601; control2X: -3; control2Y: 145.601; x: -19; y: 146.801 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: -27.8; y: 148.401 }
+ PathCubic { control1X: -27.8; control1Y: 148.401; control2X: -28; control2Y: 146.601; x: -26.2; y: 147.401 }
+ PathCubic { control1X: -24.4; control1Y: 148.201; control2X: -10.2; control2Y: 143.601; x: -13; y: 182.401 }
+ PathCubic { control1X: -13; control1Y: 182.401; control2X: -11.8; control2Y: 147.201; x: -27.8; y: 148.401 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: -35.8; y: 148.801 }
+ PathCubic { control1X: -35.8; control1Y: 148.801; control2X: -36; control2Y: 147.001; x: -34.2; y: 147.801 }
+ PathCubic { control1X: -32.4; control1Y: 148.601; control2X: -17; control2Y: 149.201; x: -29.4; y: 171.601 }
+ PathCubic { control1X: -29.4; control1Y: 171.601; control2X: -19.8; control2Y: 147.601; x: -35.8; y: 148.801 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 11.526; y: 104.465 }
+ PathCubic { control1X: 11.526; control1Y: 104.465; control2X: 11.082; control2Y: 106.464; x: 12.631; y: 105.247 }
+ PathCubic { control1X: 28.699; control1Y: 92.622; control2X: 61.141; control2Y: 33.72; x: 116.826; y: 28.086 }
+ PathCubic { control1X: 116.826; control1Y: 28.086; control2X: 78.518; control2Y: 15.976; x: 11.526; y: 104.465 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 22.726; y: 102.665 }
+ PathCubic { control1X: 22.726; control1Y: 102.665; control2X: 21.363; control2Y: 101.472; x: 23.231; y: 100.847 }
+ PathCubic { control1X: 25.099; control1Y: 100.222; control2X: 137.541; control2Y: 27.72; x: 176.826; y: 35.686 }
+ PathCubic { control1X: 176.826; control1Y: 35.686; control2X: 149.719; control2Y: 28.176; x: 22.726; y: 102.665 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 1.885; y: 108.767 }
+ PathCubic { control1X: 1.885; control1Y: 108.767; control2X: 1.376; control2Y: 110.366; x: 3.087; y: 109.39 }
+ PathCubic { control1X: 12.062; control1Y: 104.27; control2X: 15.677; control2Y: 47.059; x: 59.254; y: 45.804 }
+ PathCubic { control1X: 59.254; control1Y: 45.804; control2X: 26.843; control2Y: 31.09; x: 1.885; y: 108.767 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: -18.038; y: 119.793 }
+ PathCubic { control1X: -18.038; control1Y: 119.793; control2X: -19.115; control2Y: 121.079; x: -17.162; y: 120.825 }
+ PathCubic { control1X: -6.916; control1Y: 119.493; control2X: 14.489; control2Y: 78.222; x: 58.928; y: 83.301 }
+ PathCubic { control1X: 58.928; control1Y: 83.301; control2X: 26.962; control2Y: 68.955; x: -18.038; y: 119.793 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: -6.8; y: 113.667 }
+ PathCubic { control1X: -6.8; control1Y: 113.667; control2X: -7.611; control2Y: 115.136; x: -5.742; y: 114.511 }
+ PathCubic { control1X: 4.057; control1Y: 111.237; control2X: 17.141; control2Y: 66.625; x: 61.729; y: 63.078 }
+ PathCubic { control1X: 61.729; control1Y: 63.078; control2X: 27.603; control2Y: 55.135; x: -6.8; y: 113.667 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: -25.078; y: 124.912 }
+ PathCubic { control1X: -25.078; control1Y: 124.912; control2X: -25.951; control2Y: 125.954; x: -24.369; y: 125.748 }
+ PathCubic { control1X: -16.07; control1Y: 124.669; control2X: 1.268; control2Y: 91.24; x: 37.264; y: 95.354 }
+ PathCubic { control1X: 37.264; control1Y: 95.354; control2X: 11.371; control2Y: 83.734; x: -25.078; y: 124.912 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: -32.677; y: 130.821 }
+ PathCubic { control1X: -32.677; control1Y: 130.821; control2X: -33.682; control2Y: 131.866; x: -32.091; y: 131.748 }
+ PathCubic { control1X: -27.923; control1Y: 131.439; control2X: 2.715; control2Y: 98.36; x: 21.183; y: 113.862 }
+ PathCubic { control1X: 21.183; control1Y: 113.862; control2X: 9.168; control2Y: 95.139; x: -32.677; y: 130.821 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 36.855; y: 98.898 }
+ PathCubic { control1X: 36.855; control1Y: 98.898; control2X: 35.654; control2Y: 97.543; x: 37.586; y: 97.158 }
+ PathCubic { control1X: 39.518; control1Y: 96.774; control2X: 160.221; control2Y: 39.061; x: 198.184; y: 51.927 }
+ PathCubic { control1X: 198.184; control1Y: 51.927; control2X: 172.243; control2Y: 41.053; x: 36.855; y: 98.898 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 3.4; y: 163.201 }
+ PathCubic { control1X: 3.4; control1Y: 163.201; control2X: 3.2; control2Y: 161.401; x: 5; y: 162.201 }
+ PathCubic { control1X: 6.8; control1Y: 163.001; control2X: 22.2; control2Y: 163.601; x: 9.8; y: 186.001 }
+ PathCubic { control1X: 9.8; control1Y: 186.001; control2X: 19.4; control2Y: 162.001; x: 3.4; y: 163.201 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 13.8; y: 161.601 }
+ PathCubic { control1X: 13.8; control1Y: 161.601; control2X: 13.6; control2Y: 159.801; x: 15.4; y: 160.601 }
+ PathCubic { control1X: 17.2; control1Y: 161.401; control2X: 35; control2Y: 163.601; x: 37; y: 202.401 }
+ PathCubic { control1X: 37; control1Y: 202.401; control2X: 29.8; control2Y: 160.401; x: 13.8; y: 161.601 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 20.6; y: 160.001 }
+ PathCubic { control1X: 20.6; control1Y: 160.001; control2X: 20.4; control2Y: 158.201; x: 22.2; y: 159.001 }
+ PathCubic { control1X: 24; control1Y: 159.801; control2X: 48.6; control2Y: 163.201; x: 72.2; y: 195.601 }
+ PathCubic { control1X: 72.2; control1Y: 195.601; control2X: 36.6; control2Y: 158.801; x: 20.6; y: 160.001 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 28.225; y: 157.972 }
+ PathCubic { control1X: 28.225; control1Y: 157.972; control2X: 27.788; control2Y: 156.214; x: 29.678; y: 156.768 }
+ PathCubic { control1X: 31.568; control1Y: 157.322; control2X: 52.002; control2Y: 155.423; x: 90.099; y: 189.599 }
+ PathCubic { control1X: 90.099; control1Y: 189.599; control2X: 43.924; control2Y: 154.656; x: 28.225; y: 157.972 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 38.625; y: 153.572 }
+ PathCubic { control1X: 38.625; control1Y: 153.572; control2X: 38.188; control2Y: 151.814; x: 40.078; y: 152.368 }
+ PathCubic { control1X: 41.968; control1Y: 152.922; control2X: 76.802; control2Y: 157.423; x: 128.499; y: 192.399 }
+ PathCubic { control1X: 128.499; control1Y: 192.399; control2X: 54.324; control2Y: 150.256; x: 38.625; y: 153.572 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: -1.8; y: 142.001 }
+ PathCubic { control1X: -1.8; control1Y: 142.001; control2X: -2; control2Y: 140.201; x: -0.2; y: 141.001 }
+ PathCubic { control1X: 1.6; control1Y: 141.801; control2X: 55; control2Y: 144.401; x: 85.4; y: 171.201 }
+ PathCubic { control1X: 85.4; control1Y: 171.201; control2X: 50.499; control2Y: 146.426; x: -1.8; y: 142.001 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: -11.8; y: 146.001 }
+ PathCubic { control1X: -11.8; control1Y: 146.001; control2X: -12; control2Y: 144.201; x: -10.2; y: 145.001 }
+ PathCubic { control1X: -8.4; control1Y: 145.801; control2X: 16.2; control2Y: 149.201; x: 39.8; y: 181.601 }
+ PathCubic { control1X: 39.8; control1Y: 181.601; control2X: 4.2; control2Y: 144.801; x: -11.8; y: 146.001 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 49.503; y: 148.962 }
+ PathCubic { control1X: 49.503; control1Y: 148.962; control2X: 48.938; control2Y: 147.241; x: 50.864; y: 147.655 }
+ PathCubic { control1X: 52.79; control1Y: 148.068; control2X: 87.86; control2Y: 150.004; x: 141.981; y: 181.098 }
+ PathCubic { control1X: 141.981; control1Y: 181.098; control2X: 64.317; control2Y: 146.704; x: 49.503; y: 148.962 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 57.903; y: 146.562 }
+ PathCubic { control1X: 57.903; control1Y: 146.562; control2X: 57.338; control2Y: 144.841; x: 59.264; y: 145.255 }
+ PathCubic { control1X: 61.19; control1Y: 145.668; control2X: 96.26; control2Y: 147.604; x: 150.381; y: 178.698 }
+ PathCubic { control1X: 150.381; control1Y: 178.698; control2X: 73.317; control2Y: 143.904; x: 57.903; y: 146.562 }
+ }
+
+ ShapePath {
+ fillColor: "#ffffff"
+ strokeColor: "#000000"
+ strokeWidth: 0.1
+ PathMove { x: 67.503; y: 141.562 }
+ PathCubic { control1X: 67.503; control1Y: 141.562; control2X: 66.938; control2Y: 139.841; x: 68.864; y: 140.255 }
+ PathCubic { control1X: 70.79; control1Y: 140.668; control2X: 113.86; control2Y: 145.004; x: 203.582; y: 179.298 }
+ PathCubic { control1X: 203.582; control1Y: 179.298; control2X: 82.917; control2Y: 138.904; x: 67.503; y: 141.562 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -43.8; y: 148.401 }
+ PathCubic { control1X: -43.8; control1Y: 148.401; control2X: -38.6; control2Y: 148.001; x: -39.8; y: 149.601 }
+ PathCubic { control1X: -41; control1Y: 151.201; control2X: -43.4; control2Y: 150.401; x: -43.4; y: 150.401 }
+ PathLine { x: -43.8; y: 148.401 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -13; y: 162.401 }
+ PathCubic { control1X: -13; control1Y: 162.401; control2X: -7.8; control2Y: 162.001; x: -9; y: 163.601 }
+ PathCubic { control1X: -10.2; control1Y: 165.201; control2X: -12.6; control2Y: 164.401; x: -12.6; y: 164.401 }
+ PathLine { x: -13; y: 162.401 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -21.8; y: 162.001 }
+ PathCubic { control1X: -21.8; control1Y: 162.001; control2X: -16.6; control2Y: 161.601; x: -17.8; y: 163.201 }
+ PathCubic { control1X: -19; control1Y: 164.801; control2X: -21.4; control2Y: 164.001; x: -21.4; y: 164.001 }
+ PathLine { x: -21.8; y: 162.001 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -117.169; y: 150.182 }
+ PathCubic { control1X: -117.169; control1Y: 150.182; control2X: -112.124; control2Y: 151.505; x: -113.782; y: 152.624 }
+ PathCubic { control1X: -115.439; control1Y: 153.744; control2X: -117.446; control2Y: 152.202; x: -117.446; y: 152.202 }
+ PathLine { x: -117.169; y: 150.182 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -115.169; y: 140.582 }
+ PathCubic { control1X: -115.169; control1Y: 140.582; control2X: -110.124; control2Y: 141.905; x: -111.782; y: 143.024 }
+ PathCubic { control1X: -113.439; control1Y: 144.144; control2X: -115.446; control2Y: 142.602; x: -115.446; y: 142.602 }
+ PathLine { x: -115.169; y: 140.582 }
+ }
+
+ ShapePath {
+ fillColor: "#000000"
+ strokeWidth: -1
+ PathMove { x: -122.369; y: 136.182 }
+ PathCubic { control1X: -122.369; control1Y: 136.182; control2X: -117.324; control2Y: 137.505; x: -118.982; y: 138.624 }
+ PathCubic { control1X: -120.639; control1Y: 139.744; control2X: -122.646; control2Y: 138.202; x: -122.646; y: 138.202 }
+ PathLine { x: -122.369; y: 136.182 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -42.6; y: 211.201 }
+ PathCubic { control1X: -42.6; control1Y: 211.201; control2X: -44.2; control2Y: 211.201; x: -48.2; y: 213.201 }
+ PathCubic { control1X: -50.2; control1Y: 213.201; control2X: -61.4; control2Y: 216.801; x: -67; y: 226.801 }
+ PathCubic { control1X: -67; control1Y: 226.801; control2X: -54.6; control2Y: 217.201; x: -42.6; y: 211.201 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: 45.116; y: 303.847 }
+ PathCubic { control1X: 45.257; control1Y: 304.105; control2X: 45.312; control2Y: 304.525; x: 45.604; y: 304.542 }
+ PathCubic { control1X: 46.262; control1Y: 304.582; control2X: 47.495; control2Y: 304.883; x: 47.37; y: 304.247 }
+ PathCubic { control1X: 46.522; control1Y: 299.941; control2X: 45.648; control2Y: 295.004; x: 41.515; y: 293.197 }
+ PathCubic { control1X: 40.876; control1Y: 292.918; control2X: 39.434; control2Y: 293.331; x: 39.36; y: 294.215 }
+ PathCubic { control1X: 39.233; control1Y: 295.739; control2X: 39.116; control2Y: 297.088; x: 39.425; y: 298.554 }
+ PathCubic { control1X: 39.725; control1Y: 299.975; control2X: 41.883; control2Y: 299.985; x: 42.8; y: 298.601 }
+ PathCubic { control1X: 43.736; control1Y: 300.273; control2X: 44.168; control2Y: 302.116; x: 45.116; y: 303.847 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: 34.038; y: 308.581 }
+ PathCubic { control1X: 34.786; control1Y: 309.994; control2X: 34.659; control2Y: 311.853; x: 36.074; y: 312.416 }
+ PathCubic { control1X: 36.814; control1Y: 312.71; control2X: 38.664; control2Y: 311.735; x: 38.246; y: 310.661 }
+ PathCubic { control1X: 37.444; control1Y: 308.6; control2X: 37.056; control2Y: 306.361; x: 35.667; y: 304.55 }
+ PathCubic { control1X: 35.467; control1Y: 304.288; control2X: 35.707; control2Y: 303.755; x: 35.547; y: 303.427 }
+ PathCubic { control1X: 34.953; control1Y: 302.207; control2X: 33.808; control2Y: 301.472; x: 32.4; y: 301.801 }
+ PathCubic { control1X: 31.285; control1Y: 304.004; control2X: 32.433; control2Y: 306.133; x: 33.955; y: 307.842 }
+ PathCubic { control1X: 34.091; control1Y: 307.994; control2X: 33.925; control2Y: 308.37; x: 34.038; y: 308.581 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -5.564; y: 303.391 }
+ PathCubic { control1X: -5.672; control1Y: 303.014; control2X: -5.71; control2Y: 302.551; x: -5.545; y: 302.23 }
+ PathCubic { control1X: -5.014; control1Y: 301.197; control2X: -4.221; control2Y: 300.075; x: -4.558; y: 299.053 }
+ PathCubic { control1X: -4.906; control1Y: 297.997; control2X: -6.022; control2Y: 298.179; x: -6.672; y: 298.748 }
+ PathCubic { control1X: -7.807; control1Y: 299.742; control2X: -7.856; control2Y: 301.568; x: -8.547; y: 302.927 }
+ PathCubic { control1X: -8.743; control1Y: 303.313; control2X: -8.692; control2Y: 303.886; x: -9.133; y: 304.277 }
+ PathCubic { control1X: -9.607; control1Y: 304.698; control2X: -10.047; control2Y: 306.222; x: -9.951; y: 306.793 }
+ PathCubic { control1X: -9.898; control1Y: 307.106; control2X: -10.081; control2Y: 317.014; x: -9.859; y: 316.751 }
+ PathCubic { control1X: -9.24; control1Y: 316.018; control2X: -6.19; control2Y: 306.284; x: -6.121; y: 305.392 }
+ PathCubic { control1X: -6.064; control1Y: 304.661; control2X: -5.332; control2Y: 304.196; x: -5.564; y: 303.391 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -31.202; y: 296.599 }
+ PathCubic { control1X: -28.568; control1Y: 294.1; control2X: -25.778; control2Y: 291.139; x: -26.22; y: 287.427 }
+ PathCubic { control1X: -26.336; control1Y: 286.451; control2X: -28.111; control2Y: 286.978; x: -28.298; y: 287.824 }
+ PathCubic { control1X: -29.1; control1Y: 291.449; control2X: -31.139; control2Y: 294.11; x: -33.707; y: 296.502 }
+ PathCubic { control1X: -35.903; control1Y: 298.549; control2X: -37.765; control2Y: 304.893; x: -38; y: 305.401 }
+ PathCubic { control1X: -34.303; control1Y: 300.145; control2X: -32.046; control2Y: 297.399; x: -31.202; y: 296.599 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -44.776; y: 290.635 }
+ PathCubic { control1X: -44.253; control1Y: 290.265; control2X: -44.555; control2Y: 289.774; x: -44.338; y: 289.442 }
+ PathCubic { control1X: -43.385; control1Y: 287.984; control2X: -42.084; control2Y: 286.738; x: -42.066; y: 285 }
+ PathCubic { control1X: -42.063; control1Y: 284.723; control2X: -42.441; control2Y: 284.414; x: -42.776; y: 284.638 }
+ PathCubic { control1X: -43.053; control1Y: 284.822; control2X: -43.395; control2Y: 284.952; x: -43.503; y: 285.082 }
+ PathCubic { control1X: -45.533; control1Y: 287.531; control2X: -46.933; control2Y: 290.202; x: -48.376; y: 293.014 }
+ PathCubic { control1X: -48.559; control1Y: 293.371; control2X: -49.703; control2Y: 297.862; x: -49.39; y: 297.973 }
+ PathCubic { control1X: -49.151; control1Y: 298.058; control2X: -47.431; control2Y: 293.877; x: -47.221; y: 293.763 }
+ PathCubic { control1X: -45.958; control1Y: 293.077; control2X: -45.946; control2Y: 291.462; x: -44.776; y: 290.635 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -28.043; y: 310.179 }
+ PathCubic { control1X: -27.599; control1Y: 309.31; control2X: -26.023; control2Y: 308.108; x: -26.136; y: 307.219 }
+ PathCubic { control1X: -26.254; control1Y: 306.291; control2X: -25.786; control2Y: 304.848; x: -26.698; y: 305.536 }
+ PathCubic { control1X: -27.955; control1Y: 306.484; control2X: -31.404; control2Y: 307.833; x: -31.674; y: 313.641 }
+ PathCubic { control1X: -31.7; control1Y: 314.212; control2X: -28.726; control2Y: 311.519; x: -28.043; y: 310.179 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -13.6; y: 293.001 }
+ PathCubic { control1X: -13.2; control1Y: 292.333; control2X: -12.492; control2Y: 292.806; x: -12.033; y: 292.543 }
+ PathCubic { control1X: -11.385; control1Y: 292.171; control2X: -10.774; control2Y: 291.613; x: -10.482; y: 290.964 }
+ PathCubic { control1X: -9.512; control1Y: 288.815; control2X: -7.743; control2Y: 286.995; x: -7.6; y: 284.601 }
+ PathCubic { control1X: -9.091; control1Y: 283.196; control2X: -9.77; control2Y: 285.236; x: -10.4; y: 286.201 }
+ PathCubic { control1X: -11.723; control1Y: 284.554; control2X: -12.722; control2Y: 286.428; x: -14.022; y: 286.947 }
+ PathCubic { control1X: -14.092; control1Y: 286.975; control2X: -14.305; control2Y: 286.628; x: -14.38; y: 286.655 }
+ PathCubic { control1X: -15.557; control1Y: 287.095; control2X: -16.237; control2Y: 288.176; x: -17.235; y: 288.957 }
+ PathCubic { control1X: -17.406; control1Y: 289.091; control2X: -17.811; control2Y: 288.911; x: -17.958; y: 289.047 }
+ PathCubic { control1X: -18.61; control1Y: 289.65; control2X: -19.583; control2Y: 289.975; x: -19.863; y: 290.657 }
+ PathCubic { control1X: -20.973; control1Y: 293.364; control2X: -24.113; control2Y: 295.459; x: -26; y: 303.001 }
+ PathCubic { control1X: -25.619; control1Y: 303.91; control2X: -21.488; control2Y: 296.359; x: -21.001; y: 295.661 }
+ PathCubic { control1X: -20.165; control1Y: 294.465; control2X: -20.047; control2Y: 297.322; x: -18.771; y: 296.656 }
+ PathCubic { control1X: -18.72; control1Y: 296.629; control2X: -18.534; control2Y: 296.867; x: -18.4; y: 297.001 }
+ PathCubic { control1X: -18.206; control1Y: 296.721; control2X: -17.988; control2Y: 296.492; x: -17.6; y: 296.601 }
+ PathCubic { control1X: -17.6; control1Y: 296.201; control2X: -17.734; control2Y: 295.645; x: -17.533; y: 295.486 }
+ PathCubic { control1X: -16.296; control1Y: 294.509; control2X: -16.38; control2Y: 293.441; x: -15.6; y: 292.201 }
+ PathCubic { control1X: -15.142; control1Y: 292.99; control2X: -14.081; control2Y: 292.271; x: -13.6; y: 293.001 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: 46.2; y: 347.401 }
+ PathCubic { control1X: 46.2; control1Y: 347.401; control2X: 53.6; control2Y: 327.001; x: 49.2; y: 315.801 }
+ PathCubic { control1X: 49.2; control1Y: 315.801; control2X: 60.6; control2Y: 337.401; x: 56; y: 348.601 }
+ PathCubic { control1X: 56; control1Y: 348.601; control2X: 55.6; control2Y: 338.201; x: 51.6; y: 333.201 }
+ PathCubic { control1X: 51.6; control1Y: 333.201; control2X: 47.6; control2Y: 346.001; x: 46.2; y: 347.401 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: 31.4; y: 344.801 }
+ PathCubic { control1X: 31.4; control1Y: 344.801; control2X: 36.8; control2Y: 336.001; x: 28.8; y: 317.601 }
+ PathCubic { control1X: 28.8; control1Y: 317.601; control2X: 28; control2Y: 338.001; x: 21.2; y: 349.001 }
+ PathCubic { control1X: 21.2; control1Y: 349.001; control2X: 35.4; control2Y: 328.801; x: 31.4; y: 344.801 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: 21.4; y: 342.801 }
+ PathCubic { control1X: 21.4; control1Y: 342.801; control2X: 21.2; control2Y: 322.801; x: 21.6; y: 319.801 }
+ PathCubic { control1X: 21.6; control1Y: 319.801; control2X: 17.8; control2Y: 336.401; x: 7.6; y: 346.001 }
+ PathCubic { control1X: 7.6; control1Y: 346.001; control2X: 22; control2Y: 334.001; x: 21.4; y: 342.801 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: 11.8; y: 310.801 }
+ PathCubic { control1X: 11.8; control1Y: 310.801; control2X: 17.8; control2Y: 324.401; x: 7.8; y: 342.801 }
+ PathCubic { control1X: 7.8; control1Y: 342.801; control2X: 14.2; control2Y: 330.601; x: 9.4; y: 323.601 }
+ PathCubic { control1X: 9.4; control1Y: 323.601; control2X: 12; control2Y: 320.201; x: 11.8; y: 310.801 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -7.4; y: 342.401 }
+ PathCubic { control1X: -7.4; control1Y: 342.401; control2X: -8.4; control2Y: 326.801; x: -6.6; y: 324.601 }
+ PathCubic { control1X: -6.6; control1Y: 324.601; control2X: -6.4; control2Y: 318.201; x: -6.8; y: 317.201 }
+ PathCubic { control1X: -6.8; control1Y: 317.201; control2X: -2.8; control2Y: 311.001; x: -2.6; y: 318.401 }
+ PathCubic { control1X: -2.6; control1Y: 318.401; control2X: -1.2; control2Y: 326.201; x: 1.6; y: 330.801 }
+ PathCubic { control1X: 1.6; control1Y: 330.801; control2X: 5.2; control2Y: 336.201; x: 5; y: 342.601 }
+ PathCubic { control1X: 5; control1Y: 342.601; control2X: -5; control2Y: 312.401; x: -7.4; y: 342.401 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -11; y: 314.801 }
+ PathCubic { control1X: -11; control1Y: 314.801; control2X: -17.6; control2Y: 325.601; x: -19.4; y: 344.601 }
+ PathCubic { control1X: -19.4; control1Y: 344.601; control2X: -20.8; control2Y: 338.401; x: -17; y: 324.001 }
+ PathCubic { control1X: -17; control1Y: 324.001; control2X: -12.8; control2Y: 308.601; x: -11; y: 314.801 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -32.8; y: 334.601 }
+ PathCubic { control1X: -32.8; control1Y: 334.601; control2X: -27.8; control2Y: 329.201; x: -26.4; y: 324.201 }
+ PathCubic { control1X: -26.4; control1Y: 324.201; control2X: -22.8; control2Y: 308.401; x: -29.2; y: 317.001 }
+ PathCubic { control1X: -29.2; control1Y: 317.001; control2X: -29; control2Y: 325.001; x: -37.2; y: 332.401 }
+ PathCubic { control1X: -37.2; control1Y: 332.401; control2X: -32.4; control2Y: 330.001; x: -32.8; y: 334.601 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -38.6; y: 329.601 }
+ PathCubic { control1X: -38.6; control1Y: 329.601; control2X: -35.2; control2Y: 312.201; x: -34.4; y: 311.401 }
+ PathCubic { control1X: -34.4; control1Y: 311.401; control2X: -32.6; control2Y: 308.001; x: -35.4; y: 311.201 }
+ PathCubic { control1X: -35.4; control1Y: 311.201; control2X: -44.2; control2Y: 330.401; x: -48.2; y: 337.001 }
+ PathCubic { control1X: -48.2; control1Y: 337.001; control2X: -40.2; control2Y: 327.801; x: -38.6; y: 329.601 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -44.4; y: 313.001 }
+ PathCubic { control1X: -44.4; control1Y: 313.001; control2X: -32.8; control2Y: 290.601; x: -54.6; y: 316.401 }
+ PathCubic { control1X: -54.6; control1Y: 316.401; control2X: -43.6; control2Y: 306.601; x: -44.4; y: 313.001 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: -59.8; y: 298.401 }
+ PathCubic { control1X: -59.8; control1Y: 298.401; control2X: -55; control2Y: 279.601; x: -52.4; y: 279.801 }
+ PathCubic { control1X: -52.4; control1Y: 279.801; control2X: -44.2; control2Y: 270.801; x: -50.8; y: 281.401 }
+ PathCubic { control1X: -50.8; control1Y: 281.401; control2X: -56.8; control2Y: 291.001; x: -56.2; y: 300.801 }
+ PathCubic { control1X: -56.2; control1Y: 300.801; control2X: -56.8; control2Y: 291.201; x: -59.8; y: 298.401 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: 270.5; y: 287 }
+ PathCubic { control1X: 270.5; control1Y: 287; control2X: 258.5; control2Y: 277; x: 256; y: 273.5 }
+ PathCubic { control1X: 256; control1Y: 273.5; control2X: 269.5; control2Y: 292; x: 269.5; y: 299 }
+ PathCubic { control1X: 269.5; control1Y: 299; control2X: 272; control2Y: 291.5; x: 270.5; y: 287 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: 276; y: 265 }
+ PathCubic { control1X: 276; control1Y: 265; control2X: 255; control2Y: 250; x: 251.5; y: 242.5 }
+ PathCubic { control1X: 251.5; control1Y: 242.5; control2X: 278; control2Y: 272; x: 278; y: 276.5 }
+ PathCubic { control1X: 278; control1Y: 276.5; control2X: 278.5; control2Y: 267.5; x: 276; y: 265 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: 293; y: 111 }
+ PathCubic { control1X: 293; control1Y: 111; control2X: 281; control2Y: 103; x: 279.5; y: 105 }
+ PathCubic { control1X: 279.5; control1Y: 105; control2X: 290; control2Y: 111.5; x: 292.5; y: 120 }
+ PathCubic { control1X: 292.5; control1Y: 120; control2X: 291; control2Y: 111; x: 293; y: 111 }
+ }
+
+ ShapePath {
+ fillColor: "#cccccc"
+ strokeWidth: -1
+ PathMove { x: 301.5; y: 191.5 }
+ PathLine { x: 284; y: 179.5 }
+ PathCubic { control1X: 284; control1Y: 179.5; control2X: 303; control2Y: 196.5; x: 303.5; y: 200.5 }
+ PathLine { x: 301.5; y: 191.5 }
+ }
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: "#000000"
+ strokeWidth: 1
+ PathMove { x: -89.25; y: 169 }
+ PathLine { x: -67.25; y: 173.75 }
+ }
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: "#000000"
+ strokeWidth: 1
+ PathMove { x: -39; y: 331 }
+ PathCubic { control1X: -39; control1Y: 331; control2X: -39.5; control2Y: 327.5; x: -48.5; y: 338 }
+ }
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: "#000000"
+ strokeWidth: 1
+ PathMove { x: -33.5; y: 336 }
+ PathCubic { control1X: -33.5; control1Y: 336; control2X: -31.5; control2Y: 329.5; x: -38; y: 334 }
+ }
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: "#000000"
+ strokeWidth: 1
+ PathMove { x: 20.5; y: 344.5 }
+ PathCubic { control1X: 20.5; control1Y: 344.5; control2X: 22; control2Y: 333.5; x: 10.5; y: 346.5 }
+ }
+}
diff --git a/examples/quick/shapes/doc/images/qml-shapes-example.png b/examples/quick/shapes/doc/images/qml-shapes-example.png
new file mode 100644
index 0000000000..055fc244ea
--- /dev/null
+++ b/examples/quick/shapes/doc/images/qml-shapes-example.png
Binary files differ
diff --git a/examples/quick/shapes/doc/src/shapes.qdoc b/examples/quick/shapes/doc/src/shapes.qdoc
new file mode 100644
index 0000000000..6d0e5e7865
--- /dev/null
+++ b/examples/quick/shapes/doc/src/shapes.qdoc
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+/*!
+ \title Qt Quick Examples - Shapes
+ \example shapes
+ \image qml-shapes-example.png
+ \brief A Qt Quick example demonstrating the use of shape items.
+ \ingroup qtquickexamples
+
+ This example demonstrates the usage of the \l Shape type in Qt Quick. Shapes
+ allow efficiently rendering stroked and filled lines, curves, and arcs in Qt
+ Quick scenes.
+
+ \include examples-run.qdocinc
+*/
diff --git a/examples/quick/shapes/main.cpp b/examples/quick/shapes/main.cpp
new file mode 100644
index 0000000000..3a81c4da05
--- /dev/null
+++ b/examples/quick/shapes/main.cpp
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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 The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "../shared/shared.h"
+DECLARATIVE_EXAMPLE_MAIN(pathitem/pathitem)
diff --git a/examples/quick/shapes/shapes.pro b/examples/quick/shapes/shapes.pro
new file mode 100644
index 0000000000..1b953f56ca
--- /dev/null
+++ b/examples/quick/shapes/shapes.pro
@@ -0,0 +1,29 @@
+TEMPLATE = app
+
+QT += quick qml
+SOURCES += main.cpp
+RESOURCES += shapes.qrc
+OTHER_FILES += content/pathitem.qml \
+ content/pathitemgallery.qml \
+ content/pathiteminteract.qml \
+ content/pathitemsampling.qml \
+ content/pathitemtigers.qml \
+ content/tiger.qml \
+ content/item1.qml \
+ content/item2.qml \
+ content/item4.qml \
+ content/item5.qml \
+ content/item6.qml \
+ content/item7.qml \
+ content/item8.qml \
+ content/item9.qml \
+ content/item10.qml \
+ content/item11.qml \
+ content/item12.qml \
+ content/item13.qml \
+ content/item14.qml \
+ content/item15.qml \
+ content/item17.qml
+
+target.path = $$[QT_INSTALL_EXAMPLES]/quick/shapes
+INSTALLS += target
diff --git a/examples/quick/shapes/shapes.qrc b/examples/quick/shapes/shapes.qrc
new file mode 100644
index 0000000000..533ba090bc
--- /dev/null
+++ b/examples/quick/shapes/shapes.qrc
@@ -0,0 +1,31 @@
+<RCC>
+ <qresource prefix="/pathitem">
+ <file alias="LauncherList.qml">../shared/LauncherList.qml</file>
+ <file alias="SimpleLauncherDelegate.qml">../shared/SimpleLauncherDelegate.qml</file>
+ <file alias="images/next.png">../shared/images/next.png</file>
+ <file alias="images/back.png">../shared/images/back.png</file>
+ <file alias="images/slider_handle.png">../shared/images/slider_handle.png</file>
+ <file alias="Slider.qml">../shared/Slider.qml</file>
+ <file alias="pathitem.qml">content/pathitem.qml</file>
+ <file alias="pathitemgallery.qml">content/pathitemgallery.qml</file>
+ <file alias="pathiteminteract.qml">content/pathiteminteract.qml</file>
+ <file alias="pathitemsampling.qml">content/pathitemsampling.qml</file>
+ <file alias="pathitemtigers.qml">content/pathitemtigers.qml</file>
+ <file alias="tiger.qml">content/tiger.qml</file>
+ <file alias="item1.qml">content/item1.qml</file>
+ <file alias="item2.qml">content/item2.qml</file>
+ <file alias="item4.qml">content/item4.qml</file>
+ <file alias="item5.qml">content/item5.qml</file>
+ <file alias="item6.qml">content/item6.qml</file>
+ <file alias="item7.qml">content/item7.qml</file>
+ <file alias="item8.qml">content/item8.qml</file>
+ <file alias="item9.qml">content/item9.qml</file>
+ <file alias="item10.qml">content/item10.qml</file>
+ <file alias="item11.qml">content/item11.qml</file>
+ <file alias="item12.qml">content/item12.qml</file>
+ <file alias="item13.qml">content/item13.qml</file>
+ <file alias="item14.qml">content/item14.qml</file>
+ <file alias="item15.qml">content/item15.qml</file>
+ <file alias="item17.qml">content/item17.qml</file>
+ </qresource>
+</RCC>
diff --git a/examples/quick/shared/shared.h b/examples/quick/shared/shared.h
index 0eed618d9d..ae04667c8f 100644
--- a/examples/quick/shared/shared.h
+++ b/examples/quick/shared/shared.h
@@ -56,6 +56,11 @@
f.setVersion(4, 4);\
view.setFormat(f);\
}\
+ if (qgetenv("QT_QUICK_MULTISAMPLE").toInt()) {\
+ QSurfaceFormat f = view.format();\
+ f.setSamples(4);\
+ view.setFormat(f);\
+ }\
view.connect(view.engine(), &QQmlEngine::quit, &app, &QCoreApplication::quit);\
new QQmlFileSelector(view.engine(), &view);\
view.setSource(QUrl("qrc:///" #NAME ".qml")); \
diff --git a/examples/quick/window/CurrentScreen.qml b/examples/quick/window/CurrentScreen.qml
index 09fbce9a74..5a23cd7e29 100644
--- a/examples/quick/window/CurrentScreen.qml
+++ b/examples/quick/window/CurrentScreen.qml
@@ -39,7 +39,7 @@
****************************************************************************/
import QtQuick 2.3
-import QtQuick.Window 2.1
+import QtQuick.Window 2.10
import "../shared" as Shared
Item {
@@ -77,6 +77,15 @@ Item {
}
Item { width: 1; height: 1 } // spacer
+ Shared.Label { text: "manufacturer" }
+ Shared.Label { text: Screen.manufacturer ? Screen.manufacturer : "unknown" }
+
+ Shared.Label { text: "model" }
+ Shared.Label { text: Screen.model ? Screen.model : "unknown" }
+
+ Shared.Label { text: "serial number" }
+ Shared.Label { text: Screen.serialNumber ? Screen.serialNumber : "unknown" }
+
Shared.Label { text: "dimensions" }
Shared.Label { text: Screen.width + "x" + Screen.height }
diff --git a/src/3rdparty/masm/assembler/MacroAssemblerX86_64.h b/src/3rdparty/masm/assembler/MacroAssemblerX86_64.h
index 8ee134c2fa..c7c6aae637 100644
--- a/src/3rdparty/masm/assembler/MacroAssemblerX86_64.h
+++ b/src/3rdparty/masm/assembler/MacroAssemblerX86_64.h
@@ -328,14 +328,61 @@ public:
m_assembler.xorq_ir(imm.m_value, srcDest);
}
+ void lshift64(TrustedImm32 imm, RegisterID dest)
+ {
+ m_assembler.shlq_i8r(imm.m_value, dest);
+ }
+
+ void lshift64(RegisterID src, RegisterID dest)
+ {
+ if (src == X86Registers::ecx)
+ m_assembler.shlq_CLr(dest);
+ else {
+ ASSERT(src != dest);
+
+ // Can only shift by ecx, so we do some swapping if we see anything else.
+ swap(src, X86Registers::ecx);
+ m_assembler.shlq_CLr(dest == X86Registers::ecx ? src : dest);
+ swap(src, X86Registers::ecx);
+ }
+ }
+
+ void rshift64(TrustedImm32 imm, RegisterID dest)
+ {
+ m_assembler.sarq_i8r(imm.m_value, dest);
+ }
+
+ void rshift64(RegisterID src, RegisterID dest)
+ {
+ if (src == X86Registers::ecx)
+ m_assembler.sarq_CLr(dest);
+ else {
+ ASSERT(src != dest);
+
+ // Can only shift by ecx, so we do some swapping if we see anything else.
+ swap(src, X86Registers::ecx);
+ m_assembler.sarq_CLr(dest == X86Registers::ecx ? src : dest);
+ swap(src, X86Registers::ecx);
+ }
+ }
+
void urshift64(TrustedImm32 imm, RegisterID dest)
{
m_assembler.shrq_i8r(imm.m_value, dest);
}
- void lshift64(TrustedImm32 imm, RegisterID dest)
+ void urshift64(RegisterID src, RegisterID dest)
{
- m_assembler.shlq_i8r(imm.m_value, dest);
+ if (src == X86Registers::ecx)
+ m_assembler.shrq_CLr(dest);
+ else {
+ ASSERT(src != dest);
+
+ // Can only shift by ecx, so we do some swapping if we see anything else.
+ swap(src, X86Registers::ecx);
+ m_assembler.shrq_CLr(dest == X86Registers::ecx ? src : dest);
+ swap(src, X86Registers::ecx);
+ }
}
void load64(ImplicitAddress address, RegisterID dest)
diff --git a/src/3rdparty/masm/assembler/X86Assembler.h b/src/3rdparty/masm/assembler/X86Assembler.h
index 46f2cd714a..b71cf290f8 100644
--- a/src/3rdparty/masm/assembler/X86Assembler.h
+++ b/src/3rdparty/masm/assembler/X86Assembler.h
@@ -725,6 +725,21 @@ public:
}
}
+ void sarq_CLr(RegisterID dst)
+ {
+ m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst);
+ }
+
+ void sarq_i8r(int imm, RegisterID dst)
+ {
+ if (imm == 1)
+ m_formatter.oneByteOp64(OP_GROUP2_Ev1, GROUP2_OP_SAR, dst);
+ else {
+ m_formatter.oneByteOp64(OP_GROUP2_EvIb, GROUP2_OP_SAR, dst);
+ m_formatter.immediate8(imm);
+ }
+ }
+
void shrq_i8r(int imm, RegisterID dst)
{
// ### doesn't work when removing the "0 &&"
@@ -736,6 +751,11 @@ public:
}
}
+ void shrq_CLr(RegisterID dst)
+ {
+ m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_SHR, dst);
+ }
+
void shlq_i8r(int imm, RegisterID dst)
{
// ### doesn't work when removing the "0 &&"
@@ -747,7 +767,10 @@ public:
}
}
-
+ void shlq_CLr(RegisterID dst)
+ {
+ m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_SHL, dst);
+ }
#endif
void sarl_i8r(int imm, RegisterID dst)
@@ -795,23 +818,6 @@ public:
m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SHL, dst);
}
-#if CPU(X86_64)
- void sarq_CLr(RegisterID dst)
- {
- m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst);
- }
-
- void sarq_i8r(int imm, RegisterID dst)
- {
- if (imm == 1)
- m_formatter.oneByteOp64(OP_GROUP2_Ev1, GROUP2_OP_SAR, dst);
- else {
- m_formatter.oneByteOp64(OP_GROUP2_EvIb, GROUP2_OP_SAR, dst);
- m_formatter.immediate8(imm);
- }
- }
-#endif
-
void imull_rr(RegisterID src, RegisterID dst)
{
m_formatter.twoByteOp(OP2_IMUL_GvEv, dst, src);
diff --git a/src/imports/imports.pro b/src/imports/imports.pro
index c03224958c..3c7f96eff9 100644
--- a/src/imports/imports.pro
+++ b/src/imports/imports.pro
@@ -22,6 +22,8 @@ qtHaveModule(quick) {
qtConfig(systemsemaphore): SUBDIRS += sharedimage
qtConfig(quick-particles): \
SUBDIRS += particles
+
+ SUBDIRS += shapes
}
qtHaveModule(xmlpatterns) : SUBDIRS += xmllistmodel
diff --git a/src/imports/qtquick2/plugins.qmltypes b/src/imports/qtquick2/plugins.qmltypes
index 834b4bfac2..d23d6cc311 100644
--- a/src/imports/qtquick2/plugins.qmltypes
+++ b/src/imports/qtquick2/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable -noforceqtquick QtQuick 2.9'
+// 'qmlplugindump -nonrelocatable -noforceqtquick QtQuick 2.10'
Module {
dependencies: []
@@ -1517,8 +1517,12 @@ Module {
name: "QQuickFlickable"
defaultProperty: "flickableData"
prototype: "QQuickItem"
- exports: ["QtQuick/Flickable 2.0", "QtQuick/Flickable 2.9"]
- exportMetaObjectRevisions: [0, 9]
+ exports: [
+ "QtQuick/Flickable 2.0",
+ "QtQuick/Flickable 2.10",
+ "QtQuick/Flickable 2.9"
+ ]
+ exportMetaObjectRevisions: [0, 10, 9]
Enum {
name: "BoundsBehavior"
values: {
@@ -1529,6 +1533,12 @@ Module {
}
}
Enum {
+ name: "BoundsMovement"
+ values: {
+ "FollowBoundsBehavior": 1
+ }
+ }
+ Enum {
name: "FlickableDirection"
values: {
"AutoFlickDirection": 0,
@@ -1552,6 +1562,7 @@ Module {
Property { name: "horizontalVelocity"; type: "double"; isReadonly: true }
Property { name: "verticalVelocity"; type: "double"; isReadonly: true }
Property { name: "boundsBehavior"; type: "BoundsBehavior" }
+ Property { name: "boundsMovement"; revision: 10; type: "BoundsMovement" }
Property { name: "rebound"; type: "QQuickTransition"; isPointer: true }
Property { name: "maximumFlickVelocity"; type: "double" }
Property { name: "flickDeceleration"; type: "double" }
@@ -1583,6 +1594,7 @@ Module {
Property { name: "flickableData"; type: "QObject"; isList: true; isReadonly: true }
Property { name: "flickableChildren"; type: "QQuickItem"; isList: true; isReadonly: true }
Signal { name: "isAtBoundaryChanged" }
+ Signal { name: "boundsMovementChanged"; revision: 10 }
Signal { name: "movementStarted" }
Signal { name: "movementEnded" }
Signal { name: "flickStarted" }
@@ -1795,6 +1807,7 @@ Module {
Property { name: "letterSpacing"; type: "double" }
Property { name: "wordSpacing"; type: "double" }
Property { name: "hintingPreference"; type: "HintingPreference" }
+ Property { name: "kerning"; type: "bool" }
Method { name: "toString"; type: "string" }
}
Component {
@@ -2088,8 +2101,6 @@ Module {
prototype: "QQuickItem"
Property { name: "implicitWidth"; type: "double"; isReadonly: true }
Property { name: "implicitHeight"; type: "double"; isReadonly: true }
- Signal { name: "implicitWidthChanged2"; revision: 1 }
- Signal { name: "implicitHeightChanged2"; revision: 1 }
}
Component {
name: "QQuickIntValidator"
@@ -2300,6 +2311,7 @@ Module {
Property { name: "samplerName"; type: "QByteArray" }
Property { name: "effect"; type: "QQmlComponent"; isPointer: true }
Property { name: "textureMirroring"; type: "QQuickShaderEffectSource::TextureMirroring" }
+ Property { name: "samples"; type: "int" }
Signal {
name: "enabledChanged"
Parameter { name: "enabled"; type: "bool" }
@@ -2340,6 +2352,10 @@ Module {
name: "textureMirroringChanged"
Parameter { name: "mirroring"; type: "QQuickShaderEffectSource::TextureMirroring" }
}
+ Signal {
+ name: "samplesChanged"
+ Parameter { name: "count"; type: "int" }
+ }
}
Component {
name: "QQuickItemView"
@@ -3065,8 +3081,8 @@ Module {
Component {
name: "QQuickPathArc"
prototype: "QQuickCurve"
- exports: ["QtQuick/PathArc 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: ["QtQuick/PathArc 2.0", "QtQuick/PathArc 2.9"]
+ exportMetaObjectRevisions: [0, 2]
Enum {
name: "ArcDirection"
values: {
@@ -3078,6 +3094,8 @@ Module {
Property { name: "radiusY"; type: "double" }
Property { name: "useLargeArc"; type: "bool" }
Property { name: "direction"; type: "ArcDirection" }
+ Property { name: "xAxisRotation"; revision: 2; type: "double" }
+ Signal { name: "xAxisRotationChanged"; revision: 2 }
}
Component {
name: "QQuickPathAttribute"
@@ -3130,6 +3148,12 @@ Module {
exportMetaObjectRevisions: [0]
}
Component {
+ name: "QQuickPathMove"
+ prototype: "QQuickCurve"
+ exports: ["QtQuick/PathMove 2.9"]
+ exportMetaObjectRevisions: [0]
+ }
+ Component {
name: "QQuickPathPercent"
prototype: "QQuickPathElement"
exports: ["QtQuick/PathPercent 2.0"]
@@ -3594,9 +3618,10 @@ Module {
prototype: "QQuickItem"
exports: [
"QtQuick/ShaderEffectSource 2.0",
- "QtQuick/ShaderEffectSource 2.6"
+ "QtQuick/ShaderEffectSource 2.6",
+ "QtQuick/ShaderEffectSource 2.9"
]
- exportMetaObjectRevisions: [0, 1]
+ exportMetaObjectRevisions: [0, 1, 2]
Enum {
name: "WrapMode"
values: {
@@ -3632,6 +3657,7 @@ Module {
Property { name: "mipmap"; type: "bool" }
Property { name: "recursive"; type: "bool" }
Property { name: "textureMirroring"; revision: 1; type: "TextureMirroring" }
+ Property { name: "samples"; revision: 2; type: "int" }
Signal { name: "scheduledUpdateCompleted" }
Method { name: "scheduleUpdate" }
}
@@ -4084,6 +4110,7 @@ Module {
Property { name: "rightPadding"; revision: 6; type: "double" }
Property { name: "bottomPadding"; revision: 6; type: "double" }
Property { name: "fontInfo"; revision: 9; type: "QJSValue"; isReadonly: true }
+ Property { name: "advance"; revision: 10; type: "QSizeF"; isReadonly: true }
Signal {
name: "textChanged"
Parameter { name: "text"; type: "string" }
diff --git a/src/imports/shapes/plugin.cpp b/src/imports/shapes/plugin.cpp
new file mode 100644
index 0000000000..ae0d02da93
--- /dev/null
+++ b/src/imports/shapes/plugin.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtQml/qqmlextensionplugin.h>
+#include <QtQml/qqml.h>
+
+#include "qquickshape_p.h"
+
+static void initResources()
+{
+#ifdef QT_STATIC
+ Q_INIT_RESOURCE(qmake_QtQuick_Shapes);
+#endif
+}
+
+QT_BEGIN_NAMESPACE
+
+class QmlShapesPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
+
+public:
+ QmlShapesPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
+ void registerTypes(const char *uri) Q_DECL_OVERRIDE
+ {
+ Q_ASSERT(QByteArray(uri) == QByteArray("QtQuick.Shapes"));
+ qmlRegisterType<QQuickShape>(uri, 1, 0, "Shape");
+ qmlRegisterType<QQuickShapePath>(uri, 1, 0, "ShapePath");
+ qmlRegisterUncreatableType<QQuickShapeGradient>(uri, 1, 0, "ShapeGradient", QQuickShapeGradient::tr("ShapeGradient is an abstract base class"));
+ qmlRegisterType<QQuickShapeLinearGradient>(uri, 1, 0, "LinearGradient");
+ }
+};
+
+QT_END_NAMESPACE
+
+#include "plugin.moc"
diff --git a/src/imports/shapes/plugins.qmltypes b/src/imports/shapes/plugins.qmltypes
new file mode 100644
index 0000000000..b8a7c532e0
--- /dev/null
+++ b/src/imports/shapes/plugins.qmltypes
@@ -0,0 +1,117 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by:
+// 'qmlplugindump -nonrelocatable QtQuick.Shapes 1.0'
+
+Module {
+ dependencies: ["QtQuick 2.8"]
+ Component {
+ name: "QQuickShape"
+ defaultProperty: "data"
+ prototype: "QQuickItem"
+ exports: ["QtQuick.Shapes/Shape 1.0"]
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "RendererType"
+ values: {
+ "UnknownRenderer": 0,
+ "GeometryRenderer": 1,
+ "NvprRenderer": 2,
+ "SoftwareRenderer": 3
+ }
+ }
+ Enum {
+ name: "Status"
+ values: {
+ "Null": 0,
+ "Ready": 1,
+ "Processing": 2
+ }
+ }
+ Property { name: "rendererType"; type: "RendererType"; isReadonly: true }
+ Property { name: "asynchronous"; type: "bool" }
+ Property { name: "vendorExtensionsEnabled"; type: "bool" }
+ Property { name: "status"; type: "Status"; isReadonly: true }
+ Property { name: "data"; type: "QObject"; isList: true; isReadonly: true }
+ }
+ Component {
+ name: "QQuickShapeGradient"
+ defaultProperty: "stops"
+ prototype: "QQuickGradient"
+ exports: ["QtQuick.Shapes/ShapeGradient 1.0"]
+ isCreatable: false
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "SpreadMode"
+ values: {
+ "PadSpread": 0,
+ "RepeatSpread": 1,
+ "ReflectSpread": 2
+ }
+ }
+ Property { name: "spread"; type: "SpreadMode" }
+ }
+ Component {
+ name: "QQuickShapeLinearGradient"
+ defaultProperty: "stops"
+ prototype: "QQuickShapeGradient"
+ exports: ["QtQuick.Shapes/LinearGradient 1.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "x1"; type: "double" }
+ Property { name: "y1"; type: "double" }
+ Property { name: "x2"; type: "double" }
+ Property { name: "y2"; type: "double" }
+ }
+ Component {
+ name: "QQuickShapePath"
+ defaultProperty: "pathElements"
+ prototype: "QQuickPath"
+ exports: ["QtQuick.Shapes/ShapePath 1.0"]
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "FillRule"
+ values: {
+ "OddEvenFill": 0,
+ "WindingFill": 1
+ }
+ }
+ Enum {
+ name: "JoinStyle"
+ values: {
+ "MiterJoin": 0,
+ "BevelJoin": 64,
+ "RoundJoin": 128
+ }
+ }
+ Enum {
+ name: "CapStyle"
+ values: {
+ "FlatCap": 0,
+ "SquareCap": 16,
+ "RoundCap": 32
+ }
+ }
+ Enum {
+ name: "StrokeStyle"
+ values: {
+ "SolidLine": 1,
+ "DashLine": 2
+ }
+ }
+ Property { name: "strokeColor"; type: "QColor" }
+ Property { name: "strokeWidth"; type: "double" }
+ Property { name: "fillColor"; type: "QColor" }
+ Property { name: "fillRule"; type: "FillRule" }
+ Property { name: "joinStyle"; type: "JoinStyle" }
+ Property { name: "miterLimit"; type: "int" }
+ Property { name: "capStyle"; type: "CapStyle" }
+ Property { name: "strokeStyle"; type: "StrokeStyle" }
+ Property { name: "dashOffset"; type: "double" }
+ Property { name: "dashPattern"; type: "QVector<qreal>" }
+ Property { name: "fillGradient"; type: "QQuickShapeGradient"; isPointer: true }
+ Signal { name: "shapePathChanged" }
+ }
+}
diff --git a/src/imports/shapes/qmldir b/src/imports/shapes/qmldir
new file mode 100644
index 0000000000..306ad1ecd7
--- /dev/null
+++ b/src/imports/shapes/qmldir
@@ -0,0 +1,4 @@
+module QtQuick.Shapes
+plugin qmlshapesplugin
+classname QmlShapesPlugin
+typeinfo plugins.qmltypes
diff --git a/src/imports/shapes/qquicknvprfunctions.cpp b/src/imports/shapes/qquicknvprfunctions.cpp
new file mode 100644
index 0000000000..409a59be7f
--- /dev/null
+++ b/src/imports/shapes/qquicknvprfunctions.cpp
@@ -0,0 +1,281 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquicknvprfunctions_p.h"
+
+#if QT_CONFIG(opengl)
+
+#include <QOpenGLContext>
+#include <QOffscreenSurface>
+#include <QOpenGLExtraFunctions>
+#include "qquicknvprfunctions_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QQuickNvprFunctions
+
+ \brief Function resolvers and other helpers for GL_NV_path_rendering
+ for both desktop (GL 4.3+) and mobile/embedded (GLES 3.1+) in a manner
+ that does not distract builds that do not have NVPR support either at
+ compile or run time.
+
+ \internal
+ */
+
+QQuickNvprFunctions::QQuickNvprFunctions()
+ : d(new QQuickNvprFunctionsPrivate(this))
+{
+}
+
+QQuickNvprFunctions::~QQuickNvprFunctions()
+{
+ delete d;
+}
+
+/*!
+ \return a recommended QSurfaceFormat suitable for GL_NV_path_rendering on top
+ of OpenGL 4.3 or OpenGL ES 3.1.
+ */
+QSurfaceFormat QQuickNvprFunctions::format()
+{
+ QSurfaceFormat fmt;
+ fmt.setDepthBufferSize(24);
+ fmt.setStencilBufferSize(8);
+ if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
+ fmt.setVersion(4, 3);
+ fmt.setProfile(QSurfaceFormat::CompatibilityProfile);
+ } else if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) {
+ fmt.setVersion(3, 1);
+ }
+ return fmt;
+}
+
+#define PROC(type, name) reinterpret_cast<type>(ctx->getProcAddress(#name))
+
+/*!
+ \return true if GL_NV_path_rendering is supported with the current OpenGL
+ context.
+
+ When there is no current context, a temporary dummy one will be created and
+ made current.
+ */
+bool QQuickNvprFunctions::isSupported()
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ QScopedPointer<QOpenGLContext> tempContext;
+ QScopedPointer<QOffscreenSurface> tempSurface;
+ if (!ctx) {
+ tempContext.reset(new QOpenGLContext);
+ if (!tempContext->create())
+ return false;
+ ctx = tempContext.data();
+ tempSurface.reset(new QOffscreenSurface);
+ tempSurface->setFormat(ctx->format());
+ tempSurface->create();
+ if (!ctx->makeCurrent(tempSurface.data()))
+ return false;
+ }
+
+ if (!ctx->hasExtension(QByteArrayLiteral("GL_NV_path_rendering")))
+ return false;
+
+ // Check that GL_NV_Path_rendering extension is at least API revision 1.3
+ if (!PROC(PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC, glProgramPathFragmentInputGenNV))
+ return false;
+
+ // Do not check for DSA as the string may not be exposed on ES
+ // drivers, yet the functions we need are resolvable.
+#if 0
+ if (!ctx->hasExtension(QByteArrayLiteral("GL_EXT_direct_state_access"))) {
+ qWarning("QtQuickPath/NVPR: GL_EXT_direct_state_access not supported");
+ return false;
+ }
+#endif
+
+ return true;
+}
+
+/*!
+ Initializes using the current OpenGL context.
+
+ \return true when GL_NV_path_rendering is supported and initialization was
+ successful.
+ */
+bool QQuickNvprFunctions::create()
+{
+ return isSupported() && d->resolve();
+}
+
+/*!
+ Creates a program pipeline consisting of a separable fragment shader program.
+
+ This is essential for using NVPR with OpenGL ES 3.1+ since normal,
+ GLES2-style programs would not work without a vertex shader.
+
+ \note \a fragmentShaderSource should be a \c{version 310 es} shader since
+ this works both on desktop and embedded NVIDIA drivers, thus avoiding the
+ need to fight GLSL and GLSL ES differences.
+
+ The pipeline object is stored into \a pipeline, the fragment shader program
+ into \a program.
+
+ Use QOpenGLExtraFunctions to set uniforms, bind the pipeline, etc.
+
+ \return \c false on failure in which case the error log is printed on the
+ debug output. \c true on success.
+ */
+bool QQuickNvprFunctions::createFragmentOnlyPipeline(const char *fragmentShaderSource, GLuint *pipeline, GLuint *program)
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (!ctx)
+ return false;
+
+ QOpenGLExtraFunctions *f = ctx->extraFunctions();
+ *program = f->glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &fragmentShaderSource);
+ GLint status = 0;
+ f->glGetProgramiv(*program, GL_LINK_STATUS, &status);
+ if (!status) {
+ GLint len = 0;
+ f->glGetProgramiv(*program, GL_INFO_LOG_LENGTH, &len);
+ if (len) {
+ QByteArray s;
+ s.resize(len);
+ f->glGetProgramInfoLog(*program, s.count(), nullptr, s.data());
+ qWarning("Failed to create separable shader program:\n%s", s.constData());
+ }
+ return false;
+ }
+
+ f->glGenProgramPipelines(1, pipeline);
+ f->glUseProgramStages(*pipeline, GL_FRAGMENT_SHADER_BIT, *program);
+ f->glActiveShaderProgram(*pipeline, *program);
+
+ f->glValidateProgramPipeline(*pipeline);
+ status = 0;
+ f->glGetProgramPipelineiv(*pipeline, GL_VALIDATE_STATUS, &status);
+ if (!status) {
+ GLint len = 0;
+ f->glGetProgramPipelineiv(*pipeline, GL_INFO_LOG_LENGTH, &len);
+ if (len) {
+ QByteArray s;
+ s.resize(len);
+ f->glGetProgramPipelineInfoLog(*pipeline, s.count(), nullptr, s.data());
+ qWarning("Program pipeline validation failed:\n%s", s.constData());
+ }
+ return false;
+ }
+
+ return true;
+}
+
+bool QQuickNvprFunctionsPrivate::resolve()
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+
+ q->genPaths = PROC(PFNGLGENPATHSNVPROC, glGenPathsNV);
+ q->deletePaths = PROC(PFNGLDELETEPATHSNVPROC, glDeletePathsNV);
+ q->isPath = PROC(PFNGLISPATHNVPROC, glIsPathNV);
+ q->pathCommands = PROC(PFNGLPATHCOMMANDSNVPROC, glPathCommandsNV);
+ q->pathCoords = PROC(PFNGLPATHCOORDSNVPROC, glPathCoordsNV);
+ q->pathSubCommands = PROC(PFNGLPATHSUBCOMMANDSNVPROC, glPathSubCommandsNV);
+ q->pathSubCoords = PROC(PFNGLPATHSUBCOORDSNVPROC, glPathSubCoordsNV);
+ q->pathString = PROC(PFNGLPATHSTRINGNVPROC, glPathStringNV);
+ q->pathGlyphs = PROC(PFNGLPATHGLYPHSNVPROC, glPathGlyphsNV);
+ q->pathGlyphRange = PROC(PFNGLPATHGLYPHRANGENVPROC, glPathGlyphRangeNV);
+ q->weightPaths = PROC(PFNGLWEIGHTPATHSNVPROC, glWeightPathsNV);
+ q->copyPath = PROC(PFNGLCOPYPATHNVPROC, glCopyPathNV);
+ q->interpolatePaths = PROC(PFNGLINTERPOLATEPATHSNVPROC, glInterpolatePathsNV);
+ q->transformPath = PROC(PFNGLTRANSFORMPATHNVPROC, glTransformPathNV);
+ q->pathParameteriv = PROC(PFNGLPATHPARAMETERIVNVPROC, glPathParameterivNV);
+ q->pathParameteri = PROC(PFNGLPATHPARAMETERINVPROC, glPathParameteriNV);
+ q->pathParameterfv = PROC(PFNGLPATHPARAMETERFVNVPROC, glPathParameterfvNV);
+ q->pathParameterf = PROC(PFNGLPATHPARAMETERFNVPROC, glPathParameterfNV);
+ q->pathDashArray = PROC(PFNGLPATHDASHARRAYNVPROC, glPathDashArrayNV);
+ q->pathStencilFunc = PROC(PFNGLPATHSTENCILFUNCNVPROC, glPathStencilFuncNV);
+ q->pathStencilDepthOffset = PROC(PFNGLPATHSTENCILDEPTHOFFSETNVPROC, glPathStencilDepthOffsetNV);
+ q->stencilFillPath = PROC(PFNGLSTENCILFILLPATHNVPROC, glStencilFillPathNV);
+ q->stencilStrokePath = PROC(PFNGLSTENCILSTROKEPATHNVPROC, glStencilStrokePathNV);
+ q->stencilFillPathInstanced = PROC(PFNGLSTENCILFILLPATHINSTANCEDNVPROC, glStencilFillPathInstancedNV);
+ q->stencilStrokePathInstanced = PROC(PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC, glStencilStrokePathInstancedNV);
+ q->pathCoverDepthFunc = PROC(PFNGLPATHCOVERDEPTHFUNCNVPROC, glPathCoverDepthFuncNV);
+ q->coverFillPath = PROC(PFNGLCOVERFILLPATHNVPROC, glCoverFillPathNV);
+ q->coverStrokePath = PROC(PFNGLCOVERSTROKEPATHNVPROC, glCoverStrokePathNV);
+ q->coverFillPathInstanced = PROC(PFNGLCOVERFILLPATHINSTANCEDNVPROC, glCoverFillPathInstancedNV);
+ q->coverStrokePathInstanced = PROC(PFNGLCOVERSTROKEPATHINSTANCEDNVPROC, glCoverStrokePathInstancedNV);
+ q->getPathParameteriv = PROC(PFNGLGETPATHPARAMETERIVNVPROC, glGetPathParameterivNV);
+ q->getPathParameterfv = PROC(PFNGLGETPATHPARAMETERFVNVPROC, glGetPathParameterfvNV);
+ q->getPathCommands = PROC(PFNGLGETPATHCOMMANDSNVPROC, glGetPathCommandsNV);
+ q->getPathCoords = PROC(PFNGLGETPATHCOORDSNVPROC, glGetPathCoordsNV);
+ q->getPathDashArray = PROC(PFNGLGETPATHDASHARRAYNVPROC, glGetPathDashArrayNV);
+ q->getPathMetrics = PROC(PFNGLGETPATHMETRICSNVPROC, glGetPathMetricsNV);
+ q->getPathMetricRange = PROC(PFNGLGETPATHMETRICRANGENVPROC, glGetPathMetricRangeNV);
+ q->getPathSpacing = PROC(PFNGLGETPATHSPACINGNVPROC, glGetPathSpacingNV);
+ q->isPointInFillPath = PROC(PFNGLISPOINTINFILLPATHNVPROC, glIsPointInFillPathNV);
+ q->isPointInStrokePath = PROC(PFNGLISPOINTINSTROKEPATHNVPROC, glIsPointInStrokePathNV);
+ q->getPathLength = PROC(PFNGLGETPATHLENGTHNVPROC, glGetPathLengthNV);
+ q->getPointAlongPath = PROC(PFNGLPOINTALONGPATHNVPROC, glPointAlongPathNV);
+ q->matrixLoad3x2f = PROC(PFNGLMATRIXLOAD3X2FNVPROC, glMatrixLoad3x2fNV);
+ q->matrixLoad3x3f = PROC(PFNGLMATRIXLOAD3X3FNVPROC, glMatrixLoad3x3fNV);
+ q->matrixLoadTranspose3x3f = PROC(PFNGLMATRIXLOADTRANSPOSE3X3FNVPROC, glMatrixLoadTranspose3x3fNV);
+ q->matrixMult3x2f = PROC(PFNGLMATRIXMULT3X2FNVPROC, glMatrixMult3x2fNV);
+ q->matrixMult3x3f = PROC(PFNGLMATRIXMULT3X3FNVPROC, glMatrixMult3x3fNV);
+ q->matrixMultTranspose3x3f = PROC(PFNGLMATRIXMULTTRANSPOSE3X3FNVPROC, glMatrixMultTranspose3x3fNV);
+ q->stencilThenCoverFillPath = PROC(PFNGLSTENCILTHENCOVERFILLPATHNVPROC, glStencilThenCoverFillPathNV);
+ q->stencilThenCoverStrokePath = PROC(PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC, glStencilThenCoverStrokePathNV);
+ q->stencilThenCoverFillPathInstanced = PROC(PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC, glStencilThenCoverFillPathInstancedNV);
+ q->stencilThenCoverStrokePathInstanced = PROC(PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC, glStencilThenCoverStrokePathInstancedNV);
+ q->pathGlyphIndexRange = PROC(PFNGLPATHGLYPHINDEXRANGENVPROC, glPathGlyphIndexRangeNV);
+ q->pathGlyphIndexArray = PROC(PFNGLPATHGLYPHINDEXARRAYNVPROC, glPathGlyphIndexArrayNV);
+ q->pathMemoryGlyphIndexArray = PROC(PFNGLPATHMEMORYGLYPHINDEXARRAYNVPROC, glPathMemoryGlyphIndexArrayNV);
+ q->programPathFragmentInputGen = PROC(PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC, glProgramPathFragmentInputGenNV);
+ q->getProgramResourcefv = PROC(PFNGLGETPROGRAMRESOURCEFVNVPROC, glGetProgramResourcefvNV);
+
+ q->matrixLoadf = PROC(PFNGLMATRIXLOADFEXTPROC, glMatrixLoadfEXT);
+ q->matrixLoadIdentity = PROC(PFNGLMATRIXLOADIDENTITYEXTPROC, glMatrixLoadIdentityEXT);
+
+ return q->genPaths != nullptr // base path rendering ext
+ && q->programPathFragmentInputGen != nullptr // updated path rendering ext
+ && q->matrixLoadf != nullptr // direct state access ext
+ && q->matrixLoadIdentity != nullptr;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(opengl)
diff --git a/src/imports/shapes/qquicknvprfunctions_p.h b/src/imports/shapes/qquicknvprfunctions_p.h
new file mode 100644
index 0000000000..342e92cbc3
--- /dev/null
+++ b/src/imports/shapes/qquicknvprfunctions_p.h
@@ -0,0 +1,400 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKNVPRFUNCTIONS_P_H
+#define QQUICKNVPRFUNCTIONS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of a number of Qt sources files. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qopengl.h>
+#include <QtGui/qsurfaceformat.h>
+
+#if QT_CONFIG(opengl)
+
+QT_BEGIN_NAMESPACE
+
+// note: fixed pipeline specific functions are removed - modern ES ext
+// headers have all this, but not the fixed stuff
+
+#ifndef GL_NV_path_rendering
+#define GL_PATH_FORMAT_SVG_NV 0x9070
+#define GL_PATH_FORMAT_PS_NV 0x9071
+#define GL_STANDARD_FONT_NAME_NV 0x9072
+#define GL_SYSTEM_FONT_NAME_NV 0x9073
+#define GL_FILE_NAME_NV 0x9074
+#define GL_PATH_STROKE_WIDTH_NV 0x9075
+#define GL_PATH_END_CAPS_NV 0x9076
+#define GL_PATH_INITIAL_END_CAP_NV 0x9077
+#define GL_PATH_TERMINAL_END_CAP_NV 0x9078
+#define GL_PATH_JOIN_STYLE_NV 0x9079
+#define GL_PATH_MITER_LIMIT_NV 0x907A
+#define GL_PATH_DASH_CAPS_NV 0x907B
+#define GL_PATH_INITIAL_DASH_CAP_NV 0x907C
+#define GL_PATH_TERMINAL_DASH_CAP_NV 0x907D
+#define GL_PATH_DASH_OFFSET_NV 0x907E
+#define GL_PATH_CLIENT_LENGTH_NV 0x907F
+#define GL_PATH_FILL_MODE_NV 0x9080
+#define GL_PATH_FILL_MASK_NV 0x9081
+#define GL_PATH_FILL_COVER_MODE_NV 0x9082
+#define GL_PATH_STROKE_COVER_MODE_NV 0x9083
+#define GL_PATH_STROKE_MASK_NV 0x9084
+#define GL_COUNT_UP_NV 0x9088
+#define GL_COUNT_DOWN_NV 0x9089
+#define GL_PATH_OBJECT_BOUNDING_BOX_NV 0x908A
+#define GL_CONVEX_HULL_NV 0x908B
+#define GL_BOUNDING_BOX_NV 0x908D
+#define GL_TRANSLATE_X_NV 0x908E
+#define GL_TRANSLATE_Y_NV 0x908F
+#define GL_TRANSLATE_2D_NV 0x9090
+#define GL_TRANSLATE_3D_NV 0x9091
+#define GL_AFFINE_2D_NV 0x9092
+#define GL_AFFINE_3D_NV 0x9094
+#define GL_TRANSPOSE_AFFINE_2D_NV 0x9096
+#define GL_TRANSPOSE_AFFINE_3D_NV 0x9098
+#define GL_UTF8_NV 0x909A
+#define GL_UTF16_NV 0x909B
+#define GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV 0x909C
+#define GL_PATH_COMMAND_COUNT_NV 0x909D
+#define GL_PATH_COORD_COUNT_NV 0x909E
+#define GL_PATH_DASH_ARRAY_COUNT_NV 0x909F
+#define GL_PATH_COMPUTED_LENGTH_NV 0x90A0
+#define GL_PATH_FILL_BOUNDING_BOX_NV 0x90A1
+#define GL_PATH_STROKE_BOUNDING_BOX_NV 0x90A2
+#define GL_SQUARE_NV 0x90A3
+#define GL_ROUND_NV 0x90A4
+#define GL_TRIANGULAR_NV 0x90A5
+#define GL_BEVEL_NV 0x90A6
+#define GL_MITER_REVERT_NV 0x90A7
+#define GL_MITER_TRUNCATE_NV 0x90A8
+#define GL_SKIP_MISSING_GLYPH_NV 0x90A9
+#define GL_USE_MISSING_GLYPH_NV 0x90AA
+#define GL_PATH_ERROR_POSITION_NV 0x90AB
+#define GL_PATH_FOG_GEN_MODE_NV 0x90AC
+#define GL_ACCUM_ADJACENT_PAIRS_NV 0x90AD
+#define GL_ADJACENT_PAIRS_NV 0x90AE
+#define GL_FIRST_TO_REST_NV 0x90AF
+#define GL_PATH_GEN_MODE_NV 0x90B0
+#define GL_PATH_GEN_COEFF_NV 0x90B1
+#define GL_PATH_GEN_COLOR_FORMAT_NV 0x90B2
+#define GL_PATH_GEN_COMPONENTS_NV 0x90B3
+#define GL_PATH_STENCIL_FUNC_NV 0x90B7
+#define GL_PATH_STENCIL_REF_NV 0x90B8
+#define GL_PATH_STENCIL_VALUE_MASK_NV 0x90B9
+#define GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV 0x90BD
+#define GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV 0x90BE
+#define GL_PATH_COVER_DEPTH_FUNC_NV 0x90BF
+#define GL_PATH_DASH_OFFSET_RESET_NV 0x90B4
+#define GL_MOVE_TO_RESETS_NV 0x90B5
+#define GL_MOVE_TO_CONTINUES_NV 0x90B6
+#define GL_CLOSE_PATH_NV 0x00
+#define GL_MOVE_TO_NV 0x02
+#define GL_RELATIVE_MOVE_TO_NV 0x03
+#define GL_LINE_TO_NV 0x04
+#define GL_RELATIVE_LINE_TO_NV 0x05
+#define GL_HORIZONTAL_LINE_TO_NV 0x06
+#define GL_RELATIVE_HORIZONTAL_LINE_TO_NV 0x07
+#define GL_VERTICAL_LINE_TO_NV 0x08
+#define GL_RELATIVE_VERTICAL_LINE_TO_NV 0x09
+#define GL_QUADRATIC_CURVE_TO_NV 0x0A
+#define GL_RELATIVE_QUADRATIC_CURVE_TO_NV 0x0B
+#define GL_CUBIC_CURVE_TO_NV 0x0C
+#define GL_RELATIVE_CUBIC_CURVE_TO_NV 0x0D
+#define GL_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0E
+#define GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0F
+#define GL_SMOOTH_CUBIC_CURVE_TO_NV 0x10
+#define GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV 0x11
+#define GL_SMALL_CCW_ARC_TO_NV 0x12
+#define GL_RELATIVE_SMALL_CCW_ARC_TO_NV 0x13
+#define GL_SMALL_CW_ARC_TO_NV 0x14
+#define GL_RELATIVE_SMALL_CW_ARC_TO_NV 0x15
+#define GL_LARGE_CCW_ARC_TO_NV 0x16
+#define GL_RELATIVE_LARGE_CCW_ARC_TO_NV 0x17
+#define GL_LARGE_CW_ARC_TO_NV 0x18
+#define GL_RELATIVE_LARGE_CW_ARC_TO_NV 0x19
+#define GL_RESTART_PATH_NV 0xF0
+#define GL_DUP_FIRST_CUBIC_CURVE_TO_NV 0xF2
+#define GL_DUP_LAST_CUBIC_CURVE_TO_NV 0xF4
+#define GL_RECT_NV 0xF6
+#define GL_CIRCULAR_CCW_ARC_TO_NV 0xF8
+#define GL_CIRCULAR_CW_ARC_TO_NV 0xFA
+#define GL_CIRCULAR_TANGENT_ARC_TO_NV 0xFC
+#define GL_ARC_TO_NV 0xFE
+#define GL_RELATIVE_ARC_TO_NV 0xFF
+#define GL_BOLD_BIT_NV 0x01
+#define GL_ITALIC_BIT_NV 0x02
+#define GL_GLYPH_WIDTH_BIT_NV 0x01
+#define GL_GLYPH_HEIGHT_BIT_NV 0x02
+#define GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV 0x04
+#define GL_GLYPH_HORIZONTAL_BEARING_Y_BIT_NV 0x08
+#define GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV 0x10
+#define GL_GLYPH_VERTICAL_BEARING_X_BIT_NV 0x20
+#define GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV 0x40
+#define GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV 0x80
+#define GL_GLYPH_HAS_KERNING_BIT_NV 0x100
+#define GL_FONT_X_MIN_BOUNDS_BIT_NV 0x00010000
+#define GL_FONT_Y_MIN_BOUNDS_BIT_NV 0x00020000
+#define GL_FONT_X_MAX_BOUNDS_BIT_NV 0x00040000
+#define GL_FONT_Y_MAX_BOUNDS_BIT_NV 0x00080000
+#define GL_FONT_UNITS_PER_EM_BIT_NV 0x00100000
+#define GL_FONT_ASCENDER_BIT_NV 0x00200000
+#define GL_FONT_DESCENDER_BIT_NV 0x00400000
+#define GL_FONT_HEIGHT_BIT_NV 0x00800000
+#define GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV 0x01000000
+#define GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV 0x02000000
+#define GL_FONT_UNDERLINE_POSITION_BIT_NV 0x04000000
+#define GL_FONT_UNDERLINE_THICKNESS_BIT_NV 0x08000000
+#define GL_FONT_HAS_KERNING_BIT_NV 0x10000000
+#define GL_PRIMARY_COLOR_NV 0x852C
+#define GL_SECONDARY_COLOR_NV 0x852D
+#define GL_ROUNDED_RECT_NV 0xE8
+#define GL_RELATIVE_ROUNDED_RECT_NV 0xE9
+#define GL_ROUNDED_RECT2_NV 0xEA
+#define GL_RELATIVE_ROUNDED_RECT2_NV 0xEB
+#define GL_ROUNDED_RECT4_NV 0xEC
+#define GL_RELATIVE_ROUNDED_RECT4_NV 0xED
+#define GL_ROUNDED_RECT8_NV 0xEE
+#define GL_RELATIVE_ROUNDED_RECT8_NV 0xEF
+#define GL_RELATIVE_RECT_NV 0xF7
+#define GL_FONT_GLYPHS_AVAILABLE_NV 0x9368
+#define GL_FONT_TARGET_UNAVAILABLE_NV 0x9369
+#define GL_FONT_UNAVAILABLE_NV 0x936A
+#define GL_FONT_UNINTELLIGIBLE_NV 0x936B
+#define GL_CONIC_CURVE_TO_NV 0x1A
+#define GL_RELATIVE_CONIC_CURVE_TO_NV 0x1B
+#define GL_FONT_NUM_GLYPH_INDICES_BIT_NV 0x20000000
+#define GL_STANDARD_FONT_FORMAT_NV 0x936C
+#define GL_2_BYTES_NV 0x1407
+#define GL_3_BYTES_NV 0x1408
+#define GL_4_BYTES_NV 0x1409
+#define GL_EYE_LINEAR_NV 0x2400
+#define GL_OBJECT_LINEAR_NV 0x2401
+#define GL_CONSTANT_NV 0x8576
+#define GL_PATH_PROJECTION_NV 0x1701
+#define GL_PATH_MODELVIEW_NV 0x1700
+#define GL_PATH_MODELVIEW_STACK_DEPTH_NV 0x0BA3
+#define GL_PATH_MODELVIEW_MATRIX_NV 0x0BA6
+#define GL_PATH_MAX_MODELVIEW_STACK_DEPTH_NV 0x0D36
+#define GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV 0x84E3
+#define GL_PATH_PROJECTION_STACK_DEPTH_NV 0x0BA4
+#define GL_PATH_PROJECTION_MATRIX_NV 0x0BA7
+#define GL_PATH_MAX_PROJECTION_STACK_DEPTH_NV 0x0D38
+#define GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV 0x84E4
+#define GL_FRAGMENT_INPUT_NV 0x936D
+
+typedef GLuint (QOPENGLF_APIENTRYP PFNGLGENPATHSNVPROC) (GLsizei range);
+typedef void (QOPENGLF_APIENTRYP PFNGLDELETEPATHSNVPROC) (GLuint path, GLsizei range);
+typedef GLboolean (QOPENGLF_APIENTRYP PFNGLISPATHNVPROC) (GLuint path);
+typedef void (QOPENGLF_APIENTRYP PFNGLPATHCOMMANDSNVPROC) (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (QOPENGLF_APIENTRYP PFNGLPATHCOORDSNVPROC) (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (QOPENGLF_APIENTRYP PFNGLPATHSUBCOMMANDSNVPROC) (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (QOPENGLF_APIENTRYP PFNGLPATHSUBCOORDSNVPROC) (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (QOPENGLF_APIENTRYP PFNGLPATHSTRINGNVPROC) (GLuint path, GLenum format, GLsizei length, const void *pathString);
+typedef void (QOPENGLF_APIENTRYP PFNGLPATHGLYPHSNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (QOPENGLF_APIENTRYP PFNGLPATHGLYPHRANGENVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (QOPENGLF_APIENTRYP PFNGLWEIGHTPATHSNVPROC) (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights);
+typedef void (QOPENGLF_APIENTRYP PFNGLCOPYPATHNVPROC) (GLuint resultPath, GLuint srcPath);
+typedef void (QOPENGLF_APIENTRYP PFNGLINTERPOLATEPATHSNVPROC) (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight);
+typedef void (QOPENGLF_APIENTRYP PFNGLTRANSFORMPATHNVPROC) (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues);
+typedef void (QOPENGLF_APIENTRYP PFNGLPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, const GLint *value);
+typedef void (QOPENGLF_APIENTRYP PFNGLPATHPARAMETERINVPROC) (GLuint path, GLenum pname, GLint value);
+typedef void (QOPENGLF_APIENTRYP PFNGLPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, const GLfloat *value);
+typedef void (QOPENGLF_APIENTRYP PFNGLPATHPARAMETERFNVPROC) (GLuint path, GLenum pname, GLfloat value);
+typedef void (QOPENGLF_APIENTRYP PFNGLPATHDASHARRAYNVPROC) (GLuint path, GLsizei dashCount, const GLfloat *dashArray);
+typedef void (QOPENGLF_APIENTRYP PFNGLPATHSTENCILFUNCNVPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (QOPENGLF_APIENTRYP PFNGLPATHSTENCILDEPTHOFFSETNVPROC) (GLfloat factor, GLfloat units);
+typedef void (QOPENGLF_APIENTRYP PFNGLSTENCILFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask);
+typedef void (QOPENGLF_APIENTRYP PFNGLSTENCILSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask);
+typedef void (QOPENGLF_APIENTRYP PFNGLSTENCILFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+typedef void (QOPENGLF_APIENTRYP PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+typedef void (QOPENGLF_APIENTRYP PFNGLPATHCOVERDEPTHFUNCNVPROC) (GLenum func);
+typedef void (QOPENGLF_APIENTRYP PFNGLCOVERFILLPATHNVPROC) (GLuint path, GLenum coverMode);
+typedef void (QOPENGLF_APIENTRYP PFNGLCOVERSTROKEPATHNVPROC) (GLuint path, GLenum coverMode);
+typedef void (QOPENGLF_APIENTRYP PFNGLCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (QOPENGLF_APIENTRYP PFNGLCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (QOPENGLF_APIENTRYP PFNGLGETPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, GLint *value);
+typedef void (QOPENGLF_APIENTRYP PFNGLGETPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, GLfloat *value);
+typedef void (QOPENGLF_APIENTRYP PFNGLGETPATHCOMMANDSNVPROC) (GLuint path, GLubyte *commands);
+typedef void (QOPENGLF_APIENTRYP PFNGLGETPATHCOORDSNVPROC) (GLuint path, GLfloat *coords);
+typedef void (QOPENGLF_APIENTRYP PFNGLGETPATHDASHARRAYNVPROC) (GLuint path, GLfloat *dashArray);
+typedef void (QOPENGLF_APIENTRYP PFNGLGETPATHMETRICSNVPROC) (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics);
+typedef void (QOPENGLF_APIENTRYP PFNGLGETPATHMETRICRANGENVPROC) (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics);
+typedef void (QOPENGLF_APIENTRYP PFNGLGETPATHSPACINGNVPROC) (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing);
+typedef GLboolean (QOPENGLF_APIENTRYP PFNGLISPOINTINFILLPATHNVPROC) (GLuint path, GLuint mask, GLfloat x, GLfloat y);
+typedef GLboolean (QOPENGLF_APIENTRYP PFNGLISPOINTINSTROKEPATHNVPROC) (GLuint path, GLfloat x, GLfloat y);
+typedef GLfloat (QOPENGLF_APIENTRYP PFNGLGETPATHLENGTHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments);
+typedef GLboolean (QOPENGLF_APIENTRYP PFNGLPOINTALONGPATHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY);
+typedef void (QOPENGLF_APIENTRYP PFNGLMATRIXLOAD3X2FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (QOPENGLF_APIENTRYP PFNGLMATRIXLOAD3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (QOPENGLF_APIENTRYP PFNGLMATRIXLOADTRANSPOSE3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (QOPENGLF_APIENTRYP PFNGLMATRIXMULT3X2FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (QOPENGLF_APIENTRYP PFNGLMATRIXMULT3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (QOPENGLF_APIENTRYP PFNGLMATRIXMULTTRANSPOSE3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (QOPENGLF_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode);
+typedef void (QOPENGLF_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask, GLenum coverMode);
+typedef void (QOPENGLF_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (QOPENGLF_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef GLenum (QOPENGLF_APIENTRYP PFNGLPATHGLYPHINDEXRANGENVPROC) (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]);
+typedef GLenum (QOPENGLF_APIENTRYP PFNGLPATHGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef GLenum (QOPENGLF_APIENTRYP PFNGLPATHMEMORYGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (QOPENGLF_APIENTRYP PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC) (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs);
+typedef void (QOPENGLF_APIENTRYP PFNGLGETPROGRAMRESOURCEFVNVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params);
+#endif
+
+#ifndef GL_FLAT
+#define GL_FLAT 0x1D00
+#endif
+
+#ifndef GL_INVERT
+#define GL_INVERT 0x150A
+#endif
+
+// this one originates from fixed pipeline so may not be in GLES ext headers, but we need it still
+#ifndef GL_OBJECT_LINEAR_NV
+#define GL_OBJECT_LINEAR_NV 0x2401
+#endif
+
+#ifndef GL_EXT_direct_state_access
+typedef void (QOPENGLF_APIENTRYP PFNGLMATRIXLOADFEXTPROC) (GLenum mode, const GLfloat *m);
+typedef void (QOPENGLF_APIENTRYP PFNGLMATRIXLOADIDENTITYEXTPROC) (GLenum mode);
+#endif
+
+// When building on a system with GLES 2.0 or 3.0, we may still compile the NVPR
+// code path even though it's never used. Keep it compiling by defining the
+// necessary ES 3.1 separable program constants.
+#ifndef GL_FRAGMENT_SHADER_BIT
+#define GL_FRAGMENT_SHADER_BIT 0x00000002
+#endif
+#ifndef GL_UNIFORM
+#define GL_UNIFORM 0x92E1
+#endif
+
+class QQuickNvprFunctionsPrivate;
+
+class QQuickNvprFunctions
+{
+public:
+ QQuickNvprFunctions();
+ ~QQuickNvprFunctions();
+
+ static QSurfaceFormat format();
+ static bool isSupported();
+
+ bool create();
+
+ bool createFragmentOnlyPipeline(const char *fragmentShaderSource, GLuint *pipeline, GLuint *program);
+
+ PFNGLGENPATHSNVPROC genPaths = nullptr;
+ PFNGLDELETEPATHSNVPROC deletePaths = nullptr;
+ PFNGLISPATHNVPROC isPath = nullptr;
+ PFNGLPATHCOMMANDSNVPROC pathCommands = nullptr;
+ PFNGLPATHCOORDSNVPROC pathCoords = nullptr;
+ PFNGLPATHSUBCOMMANDSNVPROC pathSubCommands = nullptr;
+ PFNGLPATHSUBCOORDSNVPROC pathSubCoords = nullptr;
+ PFNGLPATHSTRINGNVPROC pathString = nullptr;
+ PFNGLPATHGLYPHSNVPROC pathGlyphs = nullptr;
+ PFNGLPATHGLYPHRANGENVPROC pathGlyphRange = nullptr;
+ PFNGLWEIGHTPATHSNVPROC weightPaths = nullptr;
+ PFNGLCOPYPATHNVPROC copyPath = nullptr;
+ PFNGLINTERPOLATEPATHSNVPROC interpolatePaths = nullptr;
+ PFNGLTRANSFORMPATHNVPROC transformPath = nullptr;
+ PFNGLPATHPARAMETERIVNVPROC pathParameteriv = nullptr;
+ PFNGLPATHPARAMETERINVPROC pathParameteri = nullptr;
+ PFNGLPATHPARAMETERFVNVPROC pathParameterfv = nullptr;
+ PFNGLPATHPARAMETERFNVPROC pathParameterf = nullptr;
+ PFNGLPATHDASHARRAYNVPROC pathDashArray = nullptr;
+ PFNGLPATHSTENCILFUNCNVPROC pathStencilFunc = nullptr;
+ PFNGLPATHSTENCILDEPTHOFFSETNVPROC pathStencilDepthOffset = nullptr;
+ PFNGLSTENCILFILLPATHNVPROC stencilFillPath = nullptr;
+ PFNGLSTENCILSTROKEPATHNVPROC stencilStrokePath = nullptr;
+ PFNGLSTENCILFILLPATHINSTANCEDNVPROC stencilFillPathInstanced = nullptr;
+ PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC stencilStrokePathInstanced = nullptr;
+ PFNGLPATHCOVERDEPTHFUNCNVPROC pathCoverDepthFunc = nullptr;
+ PFNGLCOVERFILLPATHNVPROC coverFillPath = nullptr;
+ PFNGLCOVERSTROKEPATHNVPROC coverStrokePath = nullptr;
+ PFNGLCOVERFILLPATHINSTANCEDNVPROC coverFillPathInstanced = nullptr;
+ PFNGLCOVERSTROKEPATHINSTANCEDNVPROC coverStrokePathInstanced = nullptr;
+ PFNGLGETPATHPARAMETERIVNVPROC getPathParameteriv = nullptr;
+ PFNGLGETPATHPARAMETERFVNVPROC getPathParameterfv = nullptr;
+ PFNGLGETPATHCOMMANDSNVPROC getPathCommands = nullptr;
+ PFNGLGETPATHCOORDSNVPROC getPathCoords = nullptr;
+ PFNGLGETPATHDASHARRAYNVPROC getPathDashArray = nullptr;
+ PFNGLGETPATHMETRICSNVPROC getPathMetrics = nullptr;
+ PFNGLGETPATHMETRICRANGENVPROC getPathMetricRange = nullptr;
+ PFNGLGETPATHSPACINGNVPROC getPathSpacing = nullptr;
+ PFNGLISPOINTINFILLPATHNVPROC isPointInFillPath = nullptr;
+ PFNGLISPOINTINSTROKEPATHNVPROC isPointInStrokePath = nullptr;
+ PFNGLGETPATHLENGTHNVPROC getPathLength = nullptr;
+ PFNGLPOINTALONGPATHNVPROC getPointAlongPath = nullptr;
+ PFNGLMATRIXLOAD3X2FNVPROC matrixLoad3x2f = nullptr;
+ PFNGLMATRIXLOAD3X3FNVPROC matrixLoad3x3f = nullptr;
+ PFNGLMATRIXLOADTRANSPOSE3X3FNVPROC matrixLoadTranspose3x3f = nullptr;
+ PFNGLMATRIXMULT3X2FNVPROC matrixMult3x2f = nullptr;
+ PFNGLMATRIXMULT3X3FNVPROC matrixMult3x3f = nullptr;
+ PFNGLMATRIXMULTTRANSPOSE3X3FNVPROC matrixMultTranspose3x3f = nullptr;
+ PFNGLSTENCILTHENCOVERFILLPATHNVPROC stencilThenCoverFillPath = nullptr;
+ PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC stencilThenCoverStrokePath = nullptr;
+ PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC stencilThenCoverFillPathInstanced = nullptr;
+ PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC stencilThenCoverStrokePathInstanced = nullptr;
+ PFNGLPATHGLYPHINDEXRANGENVPROC pathGlyphIndexRange = nullptr;
+ PFNGLPATHGLYPHINDEXARRAYNVPROC pathGlyphIndexArray = nullptr;
+ PFNGLPATHMEMORYGLYPHINDEXARRAYNVPROC pathMemoryGlyphIndexArray = nullptr;
+ PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC programPathFragmentInputGen = nullptr;
+ PFNGLGETPROGRAMRESOURCEFVNVPROC getProgramResourcefv = nullptr;
+
+ PFNGLMATRIXLOADFEXTPROC matrixLoadf = nullptr;
+ PFNGLMATRIXLOADIDENTITYEXTPROC matrixLoadIdentity = nullptr;
+
+private:
+ QQuickNvprFunctionsPrivate *d;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(opengl)
+
+#endif // QQUICKNVPRFUNCTIONS_P_H
diff --git a/src/quick/scenegraph/util/qsgdistancefieldutil_p.h b/src/imports/shapes/qquicknvprfunctions_p_p.h
index 354a48a81e..6df20566af 100644
--- a/src/quick/scenegraph/util/qsgdistancefieldutil_p.h
+++ b/src/imports/shapes/qquicknvprfunctions_p_p.h
@@ -37,57 +37,34 @@
**
****************************************************************************/
-#ifndef QSGDISTANCEFIELDUTIL_H
-#define QSGDISTANCEFIELDUTIL_H
+#ifndef QQUICKNVPRFUNCTIONS_P_P_H
+#define QQUICKNVPRFUNCTIONS_P_P_H
//
// W A R N I N G
// -------------
//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
+// This file is not part of the Qt API. It exists for the convenience
+// of a number of Qt sources files. This header file may change from
+// version to version without notice, or even be removed.
//
// We mean it.
//
-#include <qrawfont.h>
-#include <private/qfontengine_p.h>
-#include <private/qsgadaptationlayer_p.h>
+#include "qquicknvprfunctions_p.h"
QT_BEGIN_NAMESPACE
-typedef float (*ThresholdFunc)(float glyphScale);
-typedef float (*AntialiasingSpreadFunc)(float glyphScale);
-
-class QOpenGLShaderProgram;
-class QSGDistanceFieldGlyphCache;
-class QSGContext;
-
-class Q_QUICK_PRIVATE_EXPORT QSGDistanceFieldGlyphCacheManager
+class QQuickNvprFunctionsPrivate
{
public:
- QSGDistanceFieldGlyphCacheManager();
- ~QSGDistanceFieldGlyphCacheManager();
-
- QSGDistanceFieldGlyphCache *cache(const QRawFont &font);
- void insertCache(const QRawFont &font, QSGDistanceFieldGlyphCache *cache);
-
- ThresholdFunc thresholdFunc() const { return m_threshold_func; }
- void setThresholdFunc(ThresholdFunc func) { m_threshold_func = func; }
-
- AntialiasingSpreadFunc antialiasingSpreadFunc() const { return m_antialiasingSpread_func; }
- void setAntialiasingSpreadFunc(AntialiasingSpreadFunc func) { m_antialiasingSpread_func = func; }
-
-private:
- static QString fontKey(const QRawFont &font);
+ QQuickNvprFunctionsPrivate(QQuickNvprFunctions *q_ptr) : q(q_ptr) { }
- QHash<QString, QSGDistanceFieldGlyphCache *> m_caches;
+ bool resolve();
- ThresholdFunc m_threshold_func;
- AntialiasingSpreadFunc m_antialiasingSpread_func;
+ QQuickNvprFunctions *q;
};
QT_END_NAMESPACE
-#endif // QSGDISTANCEFIELDUTIL_H
+#endif // QQUICKNVPRFUNCTIONS_P_P_H
diff --git a/src/imports/shapes/qquickshape.cpp b/src/imports/shapes/qquickshape.cpp
new file mode 100644
index 0000000000..3d90ca0c1f
--- /dev/null
+++ b/src/imports/shapes/qquickshape.cpp
@@ -0,0 +1,1347 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickshape_p.h"
+#include "qquickshape_p_p.h"
+#include "qquickshapegenericrenderer_p.h"
+#include "qquickshapenvprrenderer_p.h"
+#include "qquickshapesoftwarerenderer_p.h"
+#include <private/qsgtexture_p.h>
+#include <private/qquicksvgparser_p.h>
+#include <QtGui/private/qdrawhelper_p.h>
+#include <QOpenGLFunctions>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlmodule QtQuick.Shapes 1.0
+ \title Qt Quick Shapes QML Types
+ \ingroup qmlmodules
+ \brief Provides QML types for drawing stroked and filled shapes
+
+ To use the types in this module, import the module with the following line:
+
+ \code
+ import QtQuick.Shapes 1.0
+ \endcode
+*/
+
+QQuickShapeStrokeFillParams::QQuickShapeStrokeFillParams()
+ : strokeColor(Qt::white),
+ strokeWidth(1),
+ fillColor(Qt::white),
+ fillRule(QQuickShapePath::OddEvenFill),
+ joinStyle(QQuickShapePath::BevelJoin),
+ miterLimit(2),
+ capStyle(QQuickShapePath::SquareCap),
+ strokeStyle(QQuickShapePath::SolidLine),
+ dashOffset(0),
+ fillGradient(nullptr)
+{
+ dashPattern << 4 << 2; // 4 * strokeWidth dash followed by 2 * strokeWidth space
+}
+
+QPainterPath QQuickShapePathCommands::toPainterPath() const
+{
+ QPainterPath p;
+ int coordIdx = 0;
+ for (int i = 0; i < cmd.count(); ++i) {
+ switch (cmd[i]) {
+ case QQuickShapePathCommands::MoveTo:
+ p.moveTo(coords[coordIdx], coords[coordIdx + 1]);
+ coordIdx += 2;
+ break;
+ case QQuickShapePathCommands::LineTo:
+ p.lineTo(coords[coordIdx], coords[coordIdx + 1]);
+ coordIdx += 2;
+ break;
+ case QQuickShapePathCommands::QuadTo:
+ p.quadTo(coords[coordIdx], coords[coordIdx + 1],
+ coords[coordIdx + 2], coords[coordIdx + 3]);
+ coordIdx += 4;
+ break;
+ case QQuickShapePathCommands::CubicTo:
+ p.cubicTo(coords[coordIdx], coords[coordIdx + 1],
+ coords[coordIdx + 2], coords[coordIdx + 3],
+ coords[coordIdx + 4], coords[coordIdx + 5]);
+ coordIdx += 6;
+ break;
+ case QQuickShapePathCommands::ArcTo:
+ // does not map to the QPainterPath API; reuse the helper code from QQuickSvgParser
+ QQuickSvgParser::pathArc(p,
+ coords[coordIdx], coords[coordIdx + 1], // radius
+ coords[coordIdx + 2], // xAxisRotation
+ !qFuzzyIsNull(coords[coordIdx + 6]), // useLargeArc
+ !qFuzzyIsNull(coords[coordIdx + 5]), // sweep flag
+ coords[coordIdx + 3], coords[coordIdx + 4], // end
+ p.currentPosition().x(), p.currentPosition().y());
+ coordIdx += 7;
+ break;
+ default:
+ qWarning("Unknown JS path command: %d", cmd[i]);
+ break;
+ }
+ }
+ return p;
+}
+
+/*!
+ \qmltype ShapePath
+ \instantiates QQuickShapePath
+ \inqmlmodule QtQuick.Shapes
+ \ingroup qtquick-paths
+ \ingroup qtquick-views
+ \inherits Path
+ \brief Describes a Path and associated properties for stroking and filling
+ \since 5.10
+
+ A \l Shape contains one or more ShapePath elements. At least one ShapePath is
+ necessary in order to have a Shape output anything visible. A ShapePath
+ itself is a \l Path with additional properties describing the stroking and
+ filling parameters, such as the stroke width and color, the fill color or
+ gradient, join and cap styles, and so on. As with ordinary \l Path objects,
+ ShapePath also contains a list of path elements like \l PathMove, \l PathLine,
+ \l PathCubic, \l PathQuad, \l PathArc, together with a starting position.
+
+ Any property changes in these data sets will be bubble up and change the
+ output of the Shape. This means that it is simple and easy to change, or
+ even animate, the starting and ending position, control points, or any
+ stroke or fill parameters using the usual QML bindings and animation types
+ like NumberAnimation.
+
+ In the following example the line join style changes automatically based on
+ the value of joinStyleIndex:
+
+ \code
+ ShapePath {
+ strokeColor: "black"
+ strokeWidth: 16
+ fillColor: "transparent"
+ capStyle: ShapePath.RoundCap
+
+ property int joinStyleIndex: 0
+ property variant styles: [ ShapePath.BevelJoin, ShapePath.MiterJoin, ShapePath.RoundJoin ]
+
+ joinStyle: styles[joinStyleIndex]
+
+ startX: 30
+ startY: 30
+ PathLine { x: 100; y: 100 }
+ PathLine { x: 30; y: 100 }
+ }
+ \endcode
+
+ Once associated with a Shape, here is the output with a joinStyleIndex
+ of 2 (ShapePath.RoundJoin):
+
+ \image visualpath-code-example.png
+
+ \sa {Qt Quick Examples - Shapes}, Shape
+ */
+
+QQuickShapePathPrivate::QQuickShapePathPrivate()
+ : dirty(DirtyAll)
+{
+}
+
+QQuickShapePath::QQuickShapePath(QObject *parent)
+ : QQuickPath(*(new QQuickShapePathPrivate), parent)
+{
+ // The inherited changed() and the shapePathChanged() signals remain
+ // distinct, and this is intentional. Combining the two is not possible due
+ // to the difference in semantics and the need to act (see dirty flag
+ // below) differently on QQuickPath-related changes.
+
+ connect(this, &QQuickPath::changed, [this]() {
+ Q_D(QQuickShapePath);
+ d->dirty |= QQuickShapePathPrivate::DirtyPath;
+ emit shapePathChanged();
+ });
+}
+
+QQuickShapePath::~QQuickShapePath()
+{
+}
+
+/*!
+ \qmlproperty color QtQuick.Shapes::ShapePath::strokeColor
+
+ This property holds the stroking color.
+
+ When set to \c transparent, no stroking occurs.
+
+ The default value is \c white.
+ */
+
+QColor QQuickShapePath::strokeColor() const
+{
+ Q_D(const QQuickShapePath);
+ return d->sfp.strokeColor;
+}
+
+void QQuickShapePath::setStrokeColor(const QColor &color)
+{
+ Q_D(QQuickShapePath);
+ if (d->sfp.strokeColor != color) {
+ d->sfp.strokeColor = color;
+ d->dirty |= QQuickShapePathPrivate::DirtyStrokeColor;
+ emit strokeColorChanged();
+ emit shapePathChanged();
+ }
+}
+
+/*!
+ \qmlproperty color QtQuick.Shapes::ShapePath::strokeWidth
+
+ This property holds the stroke width.
+
+ When set to a negative value, no stroking occurs.
+
+ The default value is 1.
+ */
+
+qreal QQuickShapePath::strokeWidth() const
+{
+ Q_D(const QQuickShapePath);
+ return d->sfp.strokeWidth;
+}
+
+void QQuickShapePath::setStrokeWidth(qreal w)
+{
+ Q_D(QQuickShapePath);
+ if (d->sfp.strokeWidth != w) {
+ d->sfp.strokeWidth = w;
+ d->dirty |= QQuickShapePathPrivate::DirtyStrokeWidth;
+ emit strokeWidthChanged();
+ emit shapePathChanged();
+ }
+}
+
+/*!
+ \qmlproperty color QtQuick.Shapes::ShapePath::fillColor
+
+ This property holds the fill color.
+
+ When set to \c transparent, no filling occurs.
+
+ The default value is \c white.
+ */
+
+QColor QQuickShapePath::fillColor() const
+{
+ Q_D(const QQuickShapePath);
+ return d->sfp.fillColor;
+}
+
+void QQuickShapePath::setFillColor(const QColor &color)
+{
+ Q_D(QQuickShapePath);
+ if (d->sfp.fillColor != color) {
+ d->sfp.fillColor = color;
+ d->dirty |= QQuickShapePathPrivate::DirtyFillColor;
+ emit fillColorChanged();
+ emit shapePathChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration QtQuick.Shapes::ShapePath::fillRule
+
+ This property holds the fill rule. The default value is
+ ShapePath.OddEvenFill. For an example on fill rules, see
+ QPainterPath::setFillRule().
+
+ \list
+ \li ShapePath.OddEvenFill
+ \li ShapePath.WindingFill
+ \endlist
+ */
+
+QQuickShapePath::FillRule QQuickShapePath::fillRule() const
+{
+ Q_D(const QQuickShapePath);
+ return d->sfp.fillRule;
+}
+
+void QQuickShapePath::setFillRule(FillRule fillRule)
+{
+ Q_D(QQuickShapePath);
+ if (d->sfp.fillRule != fillRule) {
+ d->sfp.fillRule = fillRule;
+ d->dirty |= QQuickShapePathPrivate::DirtyFillRule;
+ emit fillRuleChanged();
+ emit shapePathChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration QtQuick.Shapes::ShapePath::joinStyle
+
+ This property defines how joins between two connected lines are drawn. The
+ default value is ShapePath.BevelJoin.
+
+ \list
+ \li ShapePath.MiterJoin - The outer edges of the lines are extended to meet at an angle, and this area is filled.
+ \li ShapePath.BevelJoin - The triangular notch between the two lines is filled.
+ \li ShapePath.RoundJoin - A circular arc between the two lines is filled.
+ \endlist
+ */
+
+QQuickShapePath::JoinStyle QQuickShapePath::joinStyle() const
+{
+ Q_D(const QQuickShapePath);
+ return d->sfp.joinStyle;
+}
+
+void QQuickShapePath::setJoinStyle(JoinStyle style)
+{
+ Q_D(QQuickShapePath);
+ if (d->sfp.joinStyle != style) {
+ d->sfp.joinStyle = style;
+ d->dirty |= QQuickShapePathPrivate::DirtyStyle;
+ emit joinStyleChanged();
+ emit shapePathChanged();
+ }
+}
+
+/*!
+ \qmlproperty int QtQuick.Shapes::ShapePath::miterLimit
+
+ When ShapePath.joinStyle is set to ShapePath.MiterJoin, this property
+ specifies how far the miter join can extend from the join point.
+
+ The default value is 2.
+ */
+
+int QQuickShapePath::miterLimit() const
+{
+ Q_D(const QQuickShapePath);
+ return d->sfp.miterLimit;
+}
+
+void QQuickShapePath::setMiterLimit(int limit)
+{
+ Q_D(QQuickShapePath);
+ if (d->sfp.miterLimit != limit) {
+ d->sfp.miterLimit = limit;
+ d->dirty |= QQuickShapePathPrivate::DirtyStyle;
+ emit miterLimitChanged();
+ emit shapePathChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration QtQuick.Shapes::ShapePath::capStyle
+
+ This property defines how the end points of lines are drawn. The
+ default value is ShapePath.SquareCap.
+
+ \list
+ \li ShapePath.FlatCap - A square line end that does not cover the end point of the line.
+ \li ShapePath.SquareCap - A square line end that covers the end point and extends beyond it by half the line width.
+ \li ShapePath.RoundCap - A rounded line end.
+ \endlist
+ */
+
+QQuickShapePath::CapStyle QQuickShapePath::capStyle() const
+{
+ Q_D(const QQuickShapePath);
+ return d->sfp.capStyle;
+}
+
+void QQuickShapePath::setCapStyle(CapStyle style)
+{
+ Q_D(QQuickShapePath);
+ if (d->sfp.capStyle != style) {
+ d->sfp.capStyle = style;
+ d->dirty |= QQuickShapePathPrivate::DirtyStyle;
+ emit capStyleChanged();
+ emit shapePathChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration QtQuick.Shapes::ShapePath::strokeStyle
+
+ This property defines the style of stroking. The default value is
+ ShapePath.SolidLine.
+
+ \list
+ \li ShapePath.SolidLine - A plain line.
+ \li ShapePath.DashLine - Dashes separated by a few pixels.
+ \endlist
+ */
+
+QQuickShapePath::StrokeStyle QQuickShapePath::strokeStyle() const
+{
+ Q_D(const QQuickShapePath);
+ return d->sfp.strokeStyle;
+}
+
+void QQuickShapePath::setStrokeStyle(StrokeStyle style)
+{
+ Q_D(QQuickShapePath);
+ if (d->sfp.strokeStyle != style) {
+ d->sfp.strokeStyle = style;
+ d->dirty |= QQuickShapePathPrivate::DirtyDash;
+ emit strokeStyleChanged();
+ emit shapePathChanged();
+ }
+}
+
+/*!
+ \qmlproperty real QtQuick.Shapes::ShapePath::dashOffset
+
+ This property defines the starting point on the dash pattern, measured in
+ units used to specify the dash pattern.
+
+ The default value is 0.
+
+ \sa QPen::setDashOffset()
+ */
+
+qreal QQuickShapePath::dashOffset() const
+{
+ Q_D(const QQuickShapePath);
+ return d->sfp.dashOffset;
+}
+
+void QQuickShapePath::setDashOffset(qreal offset)
+{
+ Q_D(QQuickShapePath);
+ if (d->sfp.dashOffset != offset) {
+ d->sfp.dashOffset = offset;
+ d->dirty |= QQuickShapePathPrivate::DirtyDash;
+ emit dashOffsetChanged();
+ emit shapePathChanged();
+ }
+}
+
+/*!
+ \qmlproperty list<real> QtQuick.Shapes::ShapePath::dashPattern
+
+ This property defines the dash pattern when ShapePath.strokeStyle is set
+ to ShapePath.DashLine. The pattern must be specified as an even number of
+ positive entries where the entries 1, 3, 5... are the dashes and 2, 4, 6...
+ are the spaces. The pattern is specified in units of the pen's width.
+
+ The default value is (4, 2), meaning a dash of 4 * ShapePath.strokeWidth
+ pixels followed by a space of 2 * ShapePath.strokeWidth pixels.
+
+ \sa QPen::setDashPattern()
+ */
+
+QVector<qreal> QQuickShapePath::dashPattern() const
+{
+ Q_D(const QQuickShapePath);
+ return d->sfp.dashPattern;
+}
+
+void QQuickShapePath::setDashPattern(const QVector<qreal> &array)
+{
+ Q_D(QQuickShapePath);
+ if (d->sfp.dashPattern != array) {
+ d->sfp.dashPattern = array;
+ d->dirty |= QQuickShapePathPrivate::DirtyDash;
+ emit dashPatternChanged();
+ emit shapePathChanged();
+ }
+}
+
+/*!
+ \qmlproperty ShapeGradient QtQuick.Shapes::ShapePath::fillGradient
+
+ This property defines the fill gradient. By default no gradient is enabled
+ and the value is \c null. In this case the fill uses a solid color based on
+ the value of ShapePath.fillColor.
+
+ When set, ShapePath.fillColor is ignored and filling is done using one of
+ the ShapeGradient subtypes.
+
+ \note The Gradient type cannot be used here. Rather, prefer using one of the
+ advanced subtypes, like LinearGradient.
+ */
+
+QQuickShapeGradient *QQuickShapePath::fillGradient() const
+{
+ Q_D(const QQuickShapePath);
+ return d->sfp.fillGradient;
+}
+
+void QQuickShapePath::setFillGradient(QQuickShapeGradient *gradient)
+{
+ Q_D(QQuickShapePath);
+ if (d->sfp.fillGradient != gradient) {
+ if (d->sfp.fillGradient)
+ qmlobject_disconnect(d->sfp.fillGradient, QQuickShapeGradient, SIGNAL(updated()),
+ this, QQuickShapePath, SLOT(_q_fillGradientChanged()));
+ d->sfp.fillGradient = gradient;
+ if (d->sfp.fillGradient)
+ qmlobject_connect(d->sfp.fillGradient, QQuickShapeGradient, SIGNAL(updated()),
+ this, QQuickShapePath, SLOT(_q_fillGradientChanged()));
+ d->dirty |= QQuickShapePathPrivate::DirtyFillGradient;
+ emit shapePathChanged();
+ }
+}
+
+void QQuickShapePathPrivate::_q_fillGradientChanged()
+{
+ Q_Q(QQuickShapePath);
+ dirty |= DirtyFillGradient;
+ emit q->shapePathChanged();
+}
+
+void QQuickShapePath::resetFillGradient()
+{
+ setFillGradient(nullptr);
+}
+
+/*!
+ \qmltype Shape
+ \instantiates QQuickShape
+ \inqmlmodule QtQuick.Shapes
+ \ingroup qtquick-paths
+ \ingroup qtquick-views
+ \inherits Item
+ \brief Renders a path
+ \since 5.10
+
+ Renders a path either by generating geometry via QPainterPath and manual
+ triangulation or by using a GPU vendor extension like \c{GL_NV_path_rendering}.
+
+ This approach is different from rendering shapes via QQuickPaintedItem or
+ the 2D Canvas because the path never gets rasterized in software. Therefore
+ Shape is suitable for creating shapes spreading over larger areas of the
+ screen, avoiding the performance penalty for texture uploads or framebuffer
+ blits. In addition, the declarative API allows manipulating, binding to,
+ and even animating the path element properties like starting and ending
+ position, the control points, etc.
+
+ The types for specifying path elements are shared between \l PathView and
+ Shape. However, not all Shape implementations support all path
+ element types, while some may not make sense for PathView. Shape's
+ currently supported subset is: PathMove, PathLine, PathQuad, PathCubic,
+ PathArc, PathSvg.
+
+ See \l Path for a detailed overview of the supported path elements.
+
+ \code
+ Shape {
+ width: 200
+ height: 150
+ anchors.centerIn: parent
+ ShapePath {
+ strokeWidth: 4
+ strokeColor: "red"
+ fillGradient: LinearGradient {
+ x1: 20; y1: 20
+ x2: 180; y2: 130
+ GradientStop { position: 0; color: "blue" }
+ GradientStop { position: 0.2; color: "green" }
+ GradientStop { position: 0.4; color: "red" }
+ GradientStop { position: 0.6; color: "yellow" }
+ GradientStop { position: 1; color: "cyan" }
+ }
+ strokeStyle: ShapePath.DashLine
+ dashPattern: [ 1, 4 ]
+ startX: 20; startY: 20
+ PathLine { x: 180; y: 130 }
+ PathLine { x: 20; y: 130 }
+ PathLine { x: 20; y: 20 }
+ }
+ }
+ \endcode
+
+ \image pathitem-code-example.png
+
+ Like \l Item, Shape also allows any visual or non-visual objects to be
+ declared as children. ShapePath objects are handled specially. This is
+ useful since it allows adding visual items, like \l Rectangle or \l Image,
+ and non-visual objects, like \l Timer directly as children of Shape.
+
+ The following list summarizes the available Shape rendering approaches:
+
+ \list
+
+ \li When running with the default, OpenGL backend of Qt Quick, both the
+ generic, triangulation-based and the NVIDIA-specific
+ \c{GL_NV_path_rendering} methods are available. The choice is made at
+ runtime, depending on the graphics driver's capabilities. When this is not
+ desired, applications can force using the generic method by setting the
+ Shape.vendorExtensionsEnabled property to \c false.
+
+ \li The \c software backend is fully supported. The path is rendered via
+ QPainter::strokePath() and QPainter::fillPath() in this case.
+
+ \li The Direct 3D 12 backend is not currently supported.
+
+ \li The OpenVG backend is not currently supported.
+
+ \endlist
+
+ When using Shape, it is important to be aware of potential performance
+ implications:
+
+ \li When the application is running with the generic, triangulation-based
+ Shape implementation, the geometry generation happens entirely on the
+ CPU. This is potentially expensive. Changing the set of path elements,
+ changing the properties of these elements, or changing certain properties of
+ the Shape itself all lead to retriangulation of the affected paths on every
+ change. Therefore, applying animation to such properties can affect
+ performance on less powerful systems.
+
+ \li However, the data-driven, declarative nature of the Shape API often
+ means better cacheability for the underlying CPU and GPU resources. A
+ property change in one ShapePath will only lead to reprocessing the affected
+ ShapePath, leaving other parts of the Shape unchanged. Therefore, a
+ frequently changing property can still result in a lower overall system load
+ than with imperative painting approaches (for example, QPainter).
+
+ \li If animating properties other than stroke and fill colors is a must, it
+ is recommended to target systems providing \c{GL_NV_path_rendering} where
+ the cost of property changes is smaller.
+
+ \li At the same time, attention must be paid to the number of Shape elements
+ in the scene, in particular when using this special accelerated approach for
+ \c{GL_NV_path_rendering}. The way such a Shape item is represented in the
+ scene graph is different from an ordinary geometry-based item, and incurs a
+ certain cost when it comes to OpenGL state changes.
+
+ \li As a general rule, scenes should avoid using separate Shape items when
+ it is not absolutely necessary. Prefer using one Shape item with multiple
+ ShapePath elements over multiple Shape items. Scenes that cannot avoid using
+ a large number of individual Shape items should consider setting
+ Shape.vendorExtensionsEnabled to \c false.
+
+ \endlist
+
+ \sa {Qt Quick Examples - Shapes}, Path, PathMove, PathLine, PathQuad, PathCubic, PathArc, PathSvg
+*/
+
+QQuickShapePrivate::QQuickShapePrivate()
+ : spChanged(false),
+ rendererType(QQuickShape::UnknownRenderer),
+ async(false),
+ status(QQuickShape::Null),
+ renderer(nullptr),
+ enableVendorExts(true)
+{
+}
+
+QQuickShapePrivate::~QQuickShapePrivate()
+{
+ delete renderer;
+}
+
+void QQuickShapePrivate::_q_shapePathChanged()
+{
+ Q_Q(QQuickShape);
+ spChanged = true;
+ q->polish();
+}
+
+void QQuickShapePrivate::setStatus(QQuickShape::Status newStatus)
+{
+ Q_Q(QQuickShape);
+ if (status != newStatus) {
+ status = newStatus;
+ emit q->statusChanged();
+ }
+}
+
+QQuickShape::QQuickShape(QQuickItem *parent)
+ : QQuickItem(*(new QQuickShapePrivate), parent)
+{
+ setFlag(ItemHasContents);
+}
+
+QQuickShape::~QQuickShape()
+{
+}
+
+/*!
+ \qmlproperty enumeration QtQuick.Shapes::Shape::rendererType
+
+ This property determines which path rendering backend is active.
+
+ \list
+
+ \li Shape.UnknownRenderer - The renderer is unknown.
+
+ \li Shape.GeometryRenderer - The generic, driver independent solution
+ for OpenGL. Uses the same CPU-based triangulation approach as QPainter's
+ OpenGL 2 paint engine. This is the default on non-NVIDIA hardware when the
+ default, OpenGL Qt Quick scenegraph backend is in use.
+
+ \li Shape.NvprRenderer - Path items are rendered by performing OpenGL
+ calls using the \c{GL_NV_path_rendering} extension. This is the default on
+ NVIDIA hardware when the default, OpenGL Qt Quick scenegraph backend is in
+ use.
+
+ \li Shape.SoftwareRenderer - Pure QPainter drawing using the raster
+ paint engine. This is the default, and only, option when the Qt Quick
+ scenegraph is running with the \c software backend.
+
+ \endlist
+*/
+
+QQuickShape::RendererType QQuickShape::rendererType() const
+{
+ Q_D(const QQuickShape);
+ return d->rendererType;
+}
+
+/*!
+ \qmlproperty bool QtQuick.Shapes::Shape::asynchronous
+
+ When Shape.rendererType is Shape.GeometryRenderer, the input path is
+ triangulated on the CPU during the polishing phase of the Shape. This is
+ potentially expensive. To offload this work to separate worker threads, set
+ this property to \c true.
+
+ When enabled, making a Shape visible will not wait for the content to
+ become available. Instead, the gui/main thread is not blocked and the
+ results of the path rendering are shown only when all the asynchronous work
+ has been finished.
+
+ The default value is \c false.
+ */
+
+bool QQuickShape::asynchronous() const
+{
+ Q_D(const QQuickShape);
+ return d->async;
+}
+
+void QQuickShape::setAsynchronous(bool async)
+{
+ Q_D(QQuickShape);
+ if (d->async != async) {
+ d->async = async;
+ emit asynchronousChanged();
+ if (d->componentComplete)
+ d->_q_shapePathChanged();
+ }
+}
+
+/*!
+ \qmlproperty bool QtQuick.Shapes::Shape::vendorExtensionsEnabled
+
+ This property controls the usage of non-standard OpenGL extensions like
+ GL_NV_path_rendering. To disable Shape.NvprRenderer and force a uniform
+ behavior regardless of the graphics card and drivers, set this property to
+ \c false.
+
+ The default value is \c true.
+ */
+
+bool QQuickShape::vendorExtensionsEnabled() const
+{
+ Q_D(const QQuickShape);
+ return d->enableVendorExts;
+}
+
+void QQuickShape::setVendorExtensionsEnabled(bool enable)
+{
+ Q_D(QQuickShape);
+ if (d->enableVendorExts != enable) {
+ d->enableVendorExts = enable;
+ emit vendorExtensionsEnabledChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration QtQuick.Shapes::Shape::status
+
+ This property determines the status of the Shape and is relevant when
+ Shape.asynchronous is set to \c true.
+
+ \list
+
+ \li Shape.Null - Not yet initialized.
+
+ \li Shape.Ready - The Shape has finished processing.
+
+ \li Shape.Processing - The path is being processed.
+
+ \endlist
+ */
+
+QQuickShape::Status QQuickShape::status() const
+{
+ Q_D(const QQuickShape);
+ return d->status;
+}
+
+static void vpe_append(QQmlListProperty<QObject> *property, QObject *obj)
+{
+ QQuickShape *item = static_cast<QQuickShape *>(property->object);
+ QQuickShapePrivate *d = QQuickShapePrivate::get(item);
+ QQuickShapePath *path = qobject_cast<QQuickShapePath *>(obj);
+ if (path)
+ d->qmlData.sp.append(path);
+
+ QQuickItemPrivate::data_append(property, obj);
+
+ if (path && d->componentComplete) {
+ QObject::connect(path, SIGNAL(shapePathChanged()), item, SLOT(_q_shapePathChanged()));
+ d->_q_shapePathChanged();
+ }
+}
+
+static void vpe_clear(QQmlListProperty<QObject> *property)
+{
+ QQuickShape *item = static_cast<QQuickShape *>(property->object);
+ QQuickShapePrivate *d = QQuickShapePrivate::get(item);
+
+ for (QQuickShapePath *p : d->qmlData.sp)
+ QObject::disconnect(p, SIGNAL(shapePathChanged()), item, SLOT(_q_shapePathChanged()));
+
+ d->qmlData.sp.clear();
+
+ QQuickItemPrivate::data_clear(property);
+
+ if (d->componentComplete)
+ d->_q_shapePathChanged();
+}
+
+/*!
+ \qmlproperty list<Object> QtQuick.Shapes::Shape::data
+
+ This property holds the ShapePath objects that define the contents of the
+ Shape. It can also contain any other type of objects, since Shape, like Item,
+ allows adding any visual or non-visual objects as children.
+
+ \default
+ */
+
+QQmlListProperty<QObject> QQuickShape::data()
+{
+ return QQmlListProperty<QObject>(this,
+ nullptr,
+ vpe_append,
+ QQuickItemPrivate::data_count,
+ QQuickItemPrivate::data_at,
+ vpe_clear);
+}
+
+void QQuickShape::classBegin()
+{
+ QQuickItem::classBegin();
+}
+
+void QQuickShape::componentComplete()
+{
+ Q_D(QQuickShape);
+
+ QQuickItem::componentComplete();
+
+ for (QQuickShapePath *p : d->qmlData.sp)
+ connect(p, SIGNAL(shapePathChanged()), this, SLOT(_q_shapePathChanged()));
+
+ d->_q_shapePathChanged();
+}
+
+void QQuickShape::updatePolish()
+{
+ Q_D(QQuickShape);
+
+ if (!d->spChanged)
+ return;
+
+ d->spChanged = false;
+
+ if (!d->renderer) {
+ d->createRenderer();
+ if (!d->renderer)
+ return;
+ emit rendererChanged();
+ }
+
+ // endSync() is where expensive calculations may happen (or get kicked off
+ // on worker threads), depending on the backend. Therefore do this only
+ // when the item is visible.
+ if (isVisible())
+ d->sync();
+
+ update();
+}
+
+void QQuickShape::itemChange(ItemChange change, const ItemChangeData &data)
+{
+ Q_D(QQuickShape);
+
+ // sync may have been deferred; do it now if the item became visible
+ if (change == ItemVisibleHasChanged && data.boolValue)
+ d->_q_shapePathChanged();
+
+ QQuickItem::itemChange(change, data);
+}
+
+QSGNode *QQuickShape::updatePaintNode(QSGNode *node, UpdatePaintNodeData *)
+{
+ // Called on the render thread, with the gui thread blocked. We can now
+ // safely access gui thread data.
+
+ Q_D(QQuickShape);
+ if (d->renderer) {
+ if (!node)
+ node = d->createNode();
+ d->renderer->updateNode();
+ }
+ return node;
+}
+
+// the renderer object lives on the gui thread
+void QQuickShapePrivate::createRenderer()
+{
+ Q_Q(QQuickShape);
+ QSGRendererInterface *ri = q->window()->rendererInterface();
+ if (!ri)
+ return;
+
+ switch (ri->graphicsApi()) {
+#if QT_CONFIG(opengl)
+ case QSGRendererInterface::OpenGL:
+ if (enableVendorExts && QQuickShapeNvprRenderNode::isSupported()) {
+ rendererType = QQuickShape::NvprRenderer;
+ renderer = new QQuickShapeNvprRenderer;
+ } else {
+ rendererType = QQuickShape::GeometryRenderer;
+ renderer = new QQuickShapeGenericRenderer(q);
+ }
+ break;
+#endif
+ case QSGRendererInterface::Software:
+ rendererType = QQuickShape::SoftwareRenderer;
+ renderer = new QQuickShapeSoftwareRenderer;
+ break;
+ default:
+ qWarning("No path backend for this graphics API yet");
+ break;
+ }
+}
+
+// the node lives on the render thread
+QSGNode *QQuickShapePrivate::createNode()
+{
+ Q_Q(QQuickShape);
+ QSGNode *node = nullptr;
+ if (!q->window())
+ return node;
+ QSGRendererInterface *ri = q->window()->rendererInterface();
+ if (!ri)
+ return node;
+
+ switch (ri->graphicsApi()) {
+#if QT_CONFIG(opengl)
+ case QSGRendererInterface::OpenGL:
+ if (enableVendorExts && QQuickShapeNvprRenderNode::isSupported()) {
+ node = new QQuickShapeNvprRenderNode;
+ static_cast<QQuickShapeNvprRenderer *>(renderer)->setNode(
+ static_cast<QQuickShapeNvprRenderNode *>(node));
+ } else {
+ node = new QQuickShapeGenericNode;
+ static_cast<QQuickShapeGenericRenderer *>(renderer)->setRootNode(
+ static_cast<QQuickShapeGenericNode *>(node));
+ }
+ break;
+#endif
+ case QSGRendererInterface::Software:
+ node = new QQuickShapeSoftwareRenderNode(q);
+ static_cast<QQuickShapeSoftwareRenderer *>(renderer)->setNode(
+ static_cast<QQuickShapeSoftwareRenderNode *>(node));
+ break;
+ default:
+ qWarning("No path backend for this graphics API yet");
+ break;
+ }
+
+ return node;
+}
+
+static void q_asyncShapeReady(void *data)
+{
+ QQuickShapePrivate *self = static_cast<QQuickShapePrivate *>(data);
+ self->setStatus(QQuickShape::Ready);
+}
+
+void QQuickShapePrivate::sync()
+{
+ const bool useAsync = async && renderer->flags().testFlag(QQuickAbstractPathRenderer::SupportsAsync);
+ if (useAsync) {
+ setStatus(QQuickShape::Processing);
+ renderer->setAsyncCallback(q_asyncShapeReady, this);
+ }
+
+ if (!jsData.isValid()) {
+ // Standard route: The path and stroke/fill parameters are provided via
+ // QML elements.
+ const int count = qmlData.sp.count();
+ renderer->beginSync(count);
+
+ for (int i = 0; i < count; ++i) {
+ QQuickShapePath *p = qmlData.sp[i];
+ int &dirty(QQuickShapePathPrivate::get(p)->dirty);
+
+ if (dirty & QQuickShapePathPrivate::DirtyPath)
+ renderer->setPath(i, p);
+ if (dirty & QQuickShapePathPrivate::DirtyStrokeColor)
+ renderer->setStrokeColor(i, p->strokeColor());
+ if (dirty & QQuickShapePathPrivate::DirtyStrokeWidth)
+ renderer->setStrokeWidth(i, p->strokeWidth());
+ if (dirty & QQuickShapePathPrivate::DirtyFillColor)
+ renderer->setFillColor(i, p->fillColor());
+ if (dirty & QQuickShapePathPrivate::DirtyFillRule)
+ renderer->setFillRule(i, p->fillRule());
+ if (dirty & QQuickShapePathPrivate::DirtyStyle) {
+ renderer->setJoinStyle(i, p->joinStyle(), p->miterLimit());
+ renderer->setCapStyle(i, p->capStyle());
+ }
+ if (dirty & QQuickShapePathPrivate::DirtyDash)
+ renderer->setStrokeStyle(i, p->strokeStyle(), p->dashOffset(), p->dashPattern());
+ if (dirty & QQuickShapePathPrivate::DirtyFillGradient)
+ renderer->setFillGradient(i, p->fillGradient());
+
+ dirty = 0;
+ }
+
+ renderer->endSync(useAsync);
+ } else {
+
+ // ### there is no public API to reach this code path atm
+ Q_UNREACHABLE();
+
+ // Path and stroke/fill params provided from JavaScript. This avoids
+ // QObjects at the expense of not supporting changes afterwards.
+ const int count = jsData.paths.count();
+ renderer->beginSync(count);
+
+ for (int i = 0; i < count; ++i) {
+ renderer->setJSPath(i, jsData.paths[i]);
+ const QQuickShapeStrokeFillParams sfp(jsData.sfp[i]);
+ renderer->setStrokeColor(i, sfp.strokeColor);
+ renderer->setStrokeWidth(i, sfp.strokeWidth);
+ renderer->setFillColor(i, sfp.fillColor);
+ renderer->setFillRule(i, sfp.fillRule);
+ renderer->setJoinStyle(i, sfp.joinStyle, sfp.miterLimit);
+ renderer->setCapStyle(i, sfp.capStyle);
+ renderer->setStrokeStyle(i, sfp.strokeStyle, sfp.dashOffset, sfp.dashPattern);
+ renderer->setFillGradient(i, sfp.fillGradient);
+ }
+
+ renderer->endSync(useAsync);
+ }
+
+ if (!useAsync)
+ setStatus(QQuickShape::Ready);
+}
+
+// ***** gradient support *****
+
+/*!
+ \qmltype ShapeGradient
+ \instantiates QQuickShapeGradient
+ \inqmlmodule QtQuick.Shapes
+ \ingroup qtquick-paths
+ \ingroup qtquick-views
+ \inherits Gradient
+ \brief Base type of Shape fill gradients
+ \since 5.10
+
+ This is an abstract base class for gradients like LinearGradient and
+ cannot be created directly. It extends \l Gradient with properties like the
+ spread mode.
+ */
+
+QQuickShapeGradient::QQuickShapeGradient(QObject *parent)
+ : QQuickGradient(parent),
+ m_spread(PadSpread)
+{
+}
+
+/*!
+ \qmlproperty enumeration QtQuick.Shapes::ShapeGradient::spread
+
+ Specifies how the area outside the gradient area should be filled. The
+ default value is ShapeGradient.PadSpread.
+
+ \list
+ \li ShapeGradient.PadSpread - The area is filled with the closest stop color.
+ \li ShapeGradient.RepeatSpread - The gradient is repeated outside the gradient area.
+ \li ShapeGradient.ReflectSpread - The gradient is reflected outside the gradient area.
+ \endlist
+ */
+
+QQuickShapeGradient::SpreadMode QQuickShapeGradient::spread() const
+{
+ return m_spread;
+}
+
+void QQuickShapeGradient::setSpread(SpreadMode mode)
+{
+ if (m_spread != mode) {
+ m_spread = mode;
+ emit spreadChanged();
+ emit updated();
+ }
+}
+
+/*!
+ \qmltype LinearGradient
+ \instantiates QQuickShapeLinearGradient
+ \inqmlmodule QtQuick.Shapes
+ \ingroup qtquick-paths
+ \ingroup qtquick-views
+ \inherits ShapeGradient
+ \brief Linear gradient
+ \since 5.10
+
+ Linear gradients interpolate colors between start and end points. Outside
+ these points the gradient is either padded, reflected or repeated depending
+ on the spread type.
+
+ \note LinearGradient is not compatible with Rectangle items that only
+ support Gradient. This type is to be used with Shape.
+
+ \sa QLinearGradient
+ */
+
+QQuickShapeLinearGradient::QQuickShapeLinearGradient(QObject *parent)
+ : QQuickShapeGradient(parent)
+{
+}
+
+/*!
+ \qmlproperty real QtQuick.Shapes::LinearGradient::x1
+ \qmlproperty real QtQuick.Shapes::LinearGradient::y1
+ \qmlproperty real QtQuick.Shapes::LinearGradient::x2
+ \qmlproperty real QtQuick.Shapes::LinearGradient::y2
+
+ These properties define the start and end points between which color
+ interpolation occurs. By default both the stard and end points are set to
+ (0, 0).
+ */
+
+qreal QQuickShapeLinearGradient::x1() const
+{
+ return m_start.x();
+}
+
+void QQuickShapeLinearGradient::setX1(qreal v)
+{
+ if (m_start.x() != v) {
+ m_start.setX(v);
+ emit x1Changed();
+ emit updated();
+ }
+}
+
+qreal QQuickShapeLinearGradient::y1() const
+{
+ return m_start.y();
+}
+
+void QQuickShapeLinearGradient::setY1(qreal v)
+{
+ if (m_start.y() != v) {
+ m_start.setY(v);
+ emit y1Changed();
+ emit updated();
+ }
+}
+
+qreal QQuickShapeLinearGradient::x2() const
+{
+ return m_end.x();
+}
+
+void QQuickShapeLinearGradient::setX2(qreal v)
+{
+ if (m_end.x() != v) {
+ m_end.setX(v);
+ emit x2Changed();
+ emit updated();
+ }
+}
+
+qreal QQuickShapeLinearGradient::y2() const
+{
+ return m_end.y();
+}
+
+void QQuickShapeLinearGradient::setY2(qreal v)
+{
+ if (m_end.y() != v) {
+ m_end.setY(v);
+ emit y2Changed();
+ emit updated();
+ }
+}
+
+#if QT_CONFIG(opengl)
+
+// contexts sharing with each other get the same cache instance
+class QQuickShapeGradientCacheWrapper
+{
+public:
+ QQuickShapeGradientCache *get(QOpenGLContext *context)
+ {
+ return m_resource.value<QQuickShapeGradientCache>(context);
+ }
+
+private:
+ QOpenGLMultiGroupSharedResource m_resource;
+};
+
+QQuickShapeGradientCache *QQuickShapeGradientCache::currentCache()
+{
+ static QQuickShapeGradientCacheWrapper qt_path_gradient_caches;
+ return qt_path_gradient_caches.get(QOpenGLContext::currentContext());
+}
+
+// let QOpenGLContext manage the lifetime of the cached textures
+QQuickShapeGradientCache::~QQuickShapeGradientCache()
+{
+ m_cache.clear();
+}
+
+void QQuickShapeGradientCache::invalidateResource()
+{
+ m_cache.clear();
+}
+
+void QQuickShapeGradientCache::freeResource(QOpenGLContext *)
+{
+ qDeleteAll(m_cache);
+ m_cache.clear();
+}
+
+static void generateGradientColorTable(const QQuickShapeGradientCache::GradientDesc &gradient,
+ uint *colorTable, int size, float opacity)
+{
+ int pos = 0;
+ const QGradientStops &s = gradient.stops;
+ const bool colorInterpolation = true;
+
+ uint alpha = qRound(opacity * 256);
+ uint current_color = ARGB_COMBINE_ALPHA(s[0].second.rgba(), alpha);
+ qreal incr = 1.0 / qreal(size);
+ qreal fpos = 1.5 * incr;
+ colorTable[pos++] = ARGB2RGBA(qPremultiply(current_color));
+
+ while (fpos <= s.first().first) {
+ colorTable[pos] = colorTable[pos - 1];
+ pos++;
+ fpos += incr;
+ }
+
+ if (colorInterpolation)
+ current_color = qPremultiply(current_color);
+
+ const int sLast = s.size() - 1;
+ for (int i = 0; i < sLast; ++i) {
+ qreal delta = 1/(s[i+1].first - s[i].first);
+ uint next_color = ARGB_COMBINE_ALPHA(s[i + 1].second.rgba(), alpha);
+ if (colorInterpolation)
+ next_color = qPremultiply(next_color);
+
+ while (fpos < s[i+1].first && pos < size) {
+ int dist = int(256 * ((fpos - s[i].first) * delta));
+ int idist = 256 - dist;
+ if (colorInterpolation)
+ colorTable[pos] = ARGB2RGBA(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist));
+ else
+ colorTable[pos] = ARGB2RGBA(qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)));
+ ++pos;
+ fpos += incr;
+ }
+ current_color = next_color;
+ }
+
+ Q_ASSERT(s.size() > 0);
+
+ uint last_color = ARGB2RGBA(qPremultiply(ARGB_COMBINE_ALPHA(s[sLast].second.rgba(), alpha)));
+ for ( ; pos < size; ++pos)
+ colorTable[pos] = last_color;
+
+ colorTable[size-1] = last_color;
+}
+
+QSGTexture *QQuickShapeGradientCache::get(const GradientDesc &grad)
+{
+ QSGPlainTexture *tx = m_cache[grad];
+ if (!tx) {
+ QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
+ GLuint id;
+ f->glGenTextures(1, &id);
+ f->glBindTexture(GL_TEXTURE_2D, id);
+ static const uint W = 1024; // texture size is 1024x1
+ uint buf[W];
+ generateGradientColorTable(grad, buf, W, 1.0f);
+ f->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, W, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
+ tx = new QSGPlainTexture;
+ tx->setTextureId(id);
+ switch (grad.spread) {
+ case QQuickShapeGradient::PadSpread:
+ tx->setHorizontalWrapMode(QSGTexture::ClampToEdge);
+ tx->setVerticalWrapMode(QSGTexture::ClampToEdge);
+ break;
+ case QQuickShapeGradient::RepeatSpread:
+ tx->setHorizontalWrapMode(QSGTexture::Repeat);
+ tx->setVerticalWrapMode(QSGTexture::Repeat);
+ break;
+ case QQuickShapeGradient::ReflectSpread:
+ tx->setHorizontalWrapMode(QSGTexture::MirroredRepeat);
+ tx->setVerticalWrapMode(QSGTexture::MirroredRepeat);
+ break;
+ default:
+ qWarning("Unknown gradient spread mode %d", grad.spread);
+ break;
+ }
+ m_cache[grad] = tx;
+ }
+ return tx;
+}
+
+#endif // QT_CONFIG(opengl)
+
+QT_END_NAMESPACE
+
+#include "moc_qquickshape_p.cpp"
diff --git a/src/imports/shapes/qquickshape_p.h b/src/imports/shapes/qquickshape_p.h
new file mode 100644
index 0000000000..3a630aacbc
--- /dev/null
+++ b/src/imports/shapes/qquickshape_p.h
@@ -0,0 +1,287 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKSHAPE_P_H
+#define QQUICKSHAPE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qquickitem.h"
+
+#include <private/qtquickglobal_p.h>
+#include <private/qquickpath_p_p.h>
+#include <private/qquickrectangle_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickShapePathPrivate;
+class QQuickShapePrivate;
+
+class QQuickShapeGradient : public QQuickGradient
+{
+ Q_OBJECT
+ Q_PROPERTY(SpreadMode spread READ spread WRITE setSpread NOTIFY spreadChanged)
+ Q_CLASSINFO("DefaultProperty", "stops")
+
+public:
+ enum SpreadMode {
+ PadSpread,
+ RepeatSpread,
+ ReflectSpread
+ };
+ Q_ENUM(SpreadMode)
+
+ QQuickShapeGradient(QObject *parent = nullptr);
+
+ SpreadMode spread() const;
+ void setSpread(SpreadMode mode);
+
+signals:
+ void spreadChanged();
+
+private:
+ SpreadMode m_spread;
+};
+
+class QQuickShapeLinearGradient : public QQuickShapeGradient
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal x1 READ x1 WRITE setX1 NOTIFY x1Changed)
+ Q_PROPERTY(qreal y1 READ y1 WRITE setY1 NOTIFY y1Changed)
+ Q_PROPERTY(qreal x2 READ x2 WRITE setX2 NOTIFY x2Changed)
+ Q_PROPERTY(qreal y2 READ y2 WRITE setY2 NOTIFY y2Changed)
+ Q_CLASSINFO("DefaultProperty", "stops")
+
+public:
+ QQuickShapeLinearGradient(QObject *parent = nullptr);
+
+ qreal x1() const;
+ void setX1(qreal v);
+ qreal y1() const;
+ void setY1(qreal v);
+ qreal x2() const;
+ void setX2(qreal v);
+ qreal y2() const;
+ void setY2(qreal v);
+
+signals:
+ void x1Changed();
+ void y1Changed();
+ void x2Changed();
+ void y2Changed();
+
+private:
+ QPointF m_start;
+ QPointF m_end;
+};
+
+class QQuickShapePath : public QQuickPath
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QColor strokeColor READ strokeColor WRITE setStrokeColor NOTIFY strokeColorChanged)
+ Q_PROPERTY(qreal strokeWidth READ strokeWidth WRITE setStrokeWidth NOTIFY strokeWidthChanged)
+ Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor NOTIFY fillColorChanged)
+ Q_PROPERTY(FillRule fillRule READ fillRule WRITE setFillRule NOTIFY fillRuleChanged)
+ Q_PROPERTY(JoinStyle joinStyle READ joinStyle WRITE setJoinStyle NOTIFY joinStyleChanged)
+ Q_PROPERTY(int miterLimit READ miterLimit WRITE setMiterLimit NOTIFY miterLimitChanged)
+ Q_PROPERTY(CapStyle capStyle READ capStyle WRITE setCapStyle NOTIFY capStyleChanged)
+ Q_PROPERTY(StrokeStyle strokeStyle READ strokeStyle WRITE setStrokeStyle NOTIFY strokeStyleChanged)
+ Q_PROPERTY(qreal dashOffset READ dashOffset WRITE setDashOffset NOTIFY dashOffsetChanged)
+ Q_PROPERTY(QVector<qreal> dashPattern READ dashPattern WRITE setDashPattern NOTIFY dashPatternChanged)
+ Q_PROPERTY(QQuickShapeGradient *fillGradient READ fillGradient WRITE setFillGradient RESET resetFillGradient)
+
+public:
+ enum FillRule {
+ OddEvenFill = Qt::OddEvenFill,
+ WindingFill = Qt::WindingFill
+ };
+ Q_ENUM(FillRule)
+
+ enum JoinStyle {
+ MiterJoin = Qt::MiterJoin,
+ BevelJoin = Qt::BevelJoin,
+ RoundJoin = Qt::RoundJoin
+ };
+ Q_ENUM(JoinStyle)
+
+ enum CapStyle {
+ FlatCap = Qt::FlatCap,
+ SquareCap = Qt::SquareCap,
+ RoundCap = Qt::RoundCap
+ };
+ Q_ENUM(CapStyle)
+
+ enum StrokeStyle {
+ SolidLine = Qt::SolidLine,
+ DashLine = Qt::DashLine
+ };
+ Q_ENUM(StrokeStyle)
+
+ QQuickShapePath(QObject *parent = nullptr);
+ ~QQuickShapePath();
+
+ QColor strokeColor() const;
+ void setStrokeColor(const QColor &color);
+
+ qreal strokeWidth() const;
+ void setStrokeWidth(qreal w);
+
+ QColor fillColor() const;
+ void setFillColor(const QColor &color);
+
+ FillRule fillRule() const;
+ void setFillRule(FillRule fillRule);
+
+ JoinStyle joinStyle() const;
+ void setJoinStyle(JoinStyle style);
+
+ int miterLimit() const;
+ void setMiterLimit(int limit);
+
+ CapStyle capStyle() const;
+ void setCapStyle(CapStyle style);
+
+ StrokeStyle strokeStyle() const;
+ void setStrokeStyle(StrokeStyle style);
+
+ qreal dashOffset() const;
+ void setDashOffset(qreal offset);
+
+ QVector<qreal> dashPattern() const;
+ void setDashPattern(const QVector<qreal> &array);
+
+ QQuickShapeGradient *fillGradient() const;
+ void setFillGradient(QQuickShapeGradient *gradient);
+ void resetFillGradient();
+
+Q_SIGNALS:
+ void shapePathChanged();
+ void strokeColorChanged();
+ void strokeWidthChanged();
+ void fillColorChanged();
+ void fillRuleChanged();
+ void joinStyleChanged();
+ void miterLimitChanged();
+ void capStyleChanged();
+ void strokeStyleChanged();
+ void dashOffsetChanged();
+ void dashPatternChanged();
+ void fillGradientChanged();
+
+private:
+ Q_DISABLE_COPY(QQuickShapePath)
+ Q_DECLARE_PRIVATE(QQuickShapePath)
+ Q_PRIVATE_SLOT(d_func(), void _q_fillGradientChanged())
+};
+
+class QQuickShape : public QQuickItem
+{
+ Q_OBJECT
+ Q_PROPERTY(RendererType rendererType READ rendererType NOTIFY rendererChanged)
+ Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged)
+ Q_PROPERTY(bool vendorExtensionsEnabled READ vendorExtensionsEnabled WRITE setVendorExtensionsEnabled NOTIFY vendorExtensionsEnabledChanged)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(QQmlListProperty<QObject> data READ data)
+ Q_CLASSINFO("DefaultProperty", "data")
+
+public:
+ enum RendererType {
+ UnknownRenderer,
+ GeometryRenderer,
+ NvprRenderer,
+ SoftwareRenderer
+ };
+ Q_ENUM(RendererType)
+
+ enum Status {
+ Null,
+ Ready,
+ Processing
+ };
+ Q_ENUM(Status)
+
+ QQuickShape(QQuickItem *parent = nullptr);
+ ~QQuickShape();
+
+ RendererType rendererType() const;
+
+ bool asynchronous() const;
+ void setAsynchronous(bool async);
+
+ bool vendorExtensionsEnabled() const;
+ void setVendorExtensionsEnabled(bool enable);
+
+ Status status() const;
+
+ QQmlListProperty<QObject> data();
+
+protected:
+ QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *) override;
+ void updatePolish() override;
+ void itemChange(ItemChange change, const ItemChangeData &data) override;
+ void componentComplete() override;
+ void classBegin() override;
+
+Q_SIGNALS:
+ void rendererChanged();
+ void asynchronousChanged();
+ void vendorExtensionsEnabledChanged();
+ void statusChanged();
+
+private:
+ Q_DISABLE_COPY(QQuickShape)
+ Q_DECLARE_PRIVATE(QQuickShape)
+ Q_PRIVATE_SLOT(d_func(), void _q_shapePathChanged())
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickShape)
+
+#endif // QQUICKSHAPE_P_H
diff --git a/src/imports/shapes/qquickshape_p_p.h b/src/imports/shapes/qquickshape_p_p.h
new file mode 100644
index 0000000000..dc62994af2
--- /dev/null
+++ b/src/imports/shapes/qquickshape_p_p.h
@@ -0,0 +1,280 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKSHAPE_P_P_H
+#define QQUICKSHAPE_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qquickshape_p.h"
+#include <QtQuick/private/qquickitem_p.h>
+#include <QPainterPath>
+#include <QColor>
+#include <QBrush>
+#include <private/qopenglcontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSGPlainTexture;
+
+struct QQuickShapePathCommands
+{
+ enum Command {
+ MoveTo,
+ LineTo,
+ QuadTo,
+ CubicTo,
+ ArcTo
+ };
+
+ QVector<Command> cmd;
+ QVector<float> coords;
+
+ QPainterPath toPainterPath() const;
+};
+
+struct QQuickShapeStrokeFillParams
+{
+ QQuickShapeStrokeFillParams();
+
+ QColor strokeColor;
+ qreal strokeWidth;
+ QColor fillColor;
+ QQuickShapePath::FillRule fillRule;
+ QQuickShapePath::JoinStyle joinStyle;
+ int miterLimit;
+ QQuickShapePath::CapStyle capStyle;
+ QQuickShapePath::StrokeStyle strokeStyle;
+ qreal dashOffset;
+ QVector<qreal> dashPattern;
+ QQuickShapeGradient *fillGradient;
+};
+
+class QQuickAbstractPathRenderer
+{
+public:
+ enum Flag {
+ SupportsAsync = 0x01
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ virtual ~QQuickAbstractPathRenderer() { }
+
+ // Gui thread
+ virtual void beginSync(int totalCount) = 0;
+ virtual void endSync(bool async) = 0;
+ virtual void setAsyncCallback(void (*)(void *), void *) { }
+ virtual Flags flags() const { return 0; }
+ // - QML API
+ virtual void setPath(int index, const QQuickPath *path) = 0;
+ // - JS API
+ virtual void setJSPath(int index, const QQuickShapePathCommands &path) = 0;
+ // - stroke/fill parameters
+ virtual void setStrokeColor(int index, const QColor &color) = 0;
+ virtual void setStrokeWidth(int index, qreal w) = 0;
+ virtual void setFillColor(int index, const QColor &color) = 0;
+ virtual void setFillRule(int index, QQuickShapePath::FillRule fillRule) = 0;
+ virtual void setJoinStyle(int index, QQuickShapePath::JoinStyle joinStyle, int miterLimit) = 0;
+ virtual void setCapStyle(int index, QQuickShapePath::CapStyle capStyle) = 0;
+ virtual void setStrokeStyle(int index, QQuickShapePath::StrokeStyle strokeStyle,
+ qreal dashOffset, const QVector<qreal> &dashPattern) = 0;
+ virtual void setFillGradient(int index, QQuickShapeGradient *gradient) = 0;
+
+ // Render thread, with gui blocked
+ virtual void updateNode() = 0;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickAbstractPathRenderer::Flags)
+
+class QQuickShapePathPrivate : public QQuickPathPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickShapePath)
+
+public:
+ enum Dirty {
+ DirtyPath = 0x01,
+ DirtyStrokeColor = 0x02,
+ DirtyStrokeWidth = 0x04,
+ DirtyFillColor = 0x08,
+ DirtyFillRule = 0x10,
+ DirtyStyle = 0x20,
+ DirtyDash = 0x40,
+ DirtyFillGradient = 0x80,
+
+ DirtyAll = 0xFF
+ };
+
+ QQuickShapePathPrivate();
+
+ void _q_pathChanged();
+ void _q_fillGradientChanged();
+
+ static QQuickShapePathPrivate *get(QQuickShapePath *p) { return p->d_func(); }
+
+ int dirty;
+ QQuickShapeStrokeFillParams sfp;
+};
+
+class QQuickShapePrivate : public QQuickItemPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickShape)
+
+public:
+ QQuickShapePrivate();
+ ~QQuickShapePrivate();
+
+ void createRenderer();
+ QSGNode *createNode();
+ void sync();
+
+ void _q_shapePathChanged();
+ void setStatus(QQuickShape::Status newStatus);
+
+ static QQuickShapePrivate *get(QQuickShape *item) { return item->d_func(); }
+
+ bool spChanged;
+ QQuickShape::RendererType rendererType;
+ bool async;
+ QQuickShape::Status status;
+ QQuickAbstractPathRenderer *renderer;
+
+ struct {
+ QVector<QQuickShapePath *> sp;
+ } qmlData;
+
+ struct {
+ bool isValid() const { Q_ASSERT(paths.count() == sfp.count()); return !paths.isEmpty(); }
+ QVector<QQuickShapePathCommands> paths;
+ QVector<QQuickShapeStrokeFillParams> sfp;
+ } jsData;
+
+ bool enableVendorExts;
+};
+
+class QQuickShapePathObject : public QObject
+{
+ Q_OBJECT
+
+public:
+ QQuickShapePathObject(QObject *parent = nullptr) : QObject(parent) { }
+
+ void setV4Engine(QV4::ExecutionEngine *engine);
+ QV4::ReturnedValue v4value() const { return m_v4value.value(); }
+
+ QQuickShapePath path;
+
+ void clear();
+
+private:
+ QV4::PersistentValue m_v4value;
+};
+
+class QQuickShapeStrokeFillParamsObject : public QObject
+{
+ Q_OBJECT
+
+public:
+ QQuickShapeStrokeFillParamsObject(QObject *parent = nullptr) : QObject(parent) { }
+
+ void setV4Engine(QV4::ExecutionEngine *engine);
+ QV4::ReturnedValue v4value() const { return m_v4value.value(); }
+
+ QQuickShapeStrokeFillParams sfp;
+ QV4::PersistentValue v4fillGradient;
+
+ void clear();
+
+private:
+ QV4::PersistentValue m_v4value;
+};
+
+#if QT_CONFIG(opengl)
+
+class QQuickShapeGradientCache : public QOpenGLSharedResource
+{
+public:
+ struct GradientDesc {
+ QGradientStops stops;
+ QPointF start;
+ QPointF end;
+ QQuickShapeGradient::SpreadMode spread;
+ bool operator==(const GradientDesc &other) const
+ {
+ return start == other.start && end == other.end && spread == other.spread
+ && stops == other.stops;
+ }
+ };
+
+ QQuickShapeGradientCache(QOpenGLContext *context) : QOpenGLSharedResource(context->shareGroup()) { }
+ ~QQuickShapeGradientCache();
+
+ void invalidateResource() override;
+ void freeResource(QOpenGLContext *) override;
+
+ QSGTexture *get(const GradientDesc &grad);
+
+ static QQuickShapeGradientCache *currentCache();
+
+private:
+ QHash<GradientDesc, QSGPlainTexture *> m_cache;
+};
+
+inline uint qHash(const QQuickShapeGradientCache::GradientDesc &v, uint seed = 0)
+{
+ uint h = seed;
+ h += v.start.x() + v.end.y() + v.spread;
+ for (int i = 0; i < 3 && i < v.stops.count(); ++i)
+ h += v.stops[i].second.rgba();
+ return h;
+}
+
+#endif // QT_CONFIG(opengl)
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/imports/shapes/qquickshapegenericrenderer.cpp b/src/imports/shapes/qquickshapegenericrenderer.cpp
new file mode 100644
index 0000000000..ca5f2a0e91
--- /dev/null
+++ b/src/imports/shapes/qquickshapegenericrenderer.cpp
@@ -0,0 +1,784 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickshapegenericrenderer_p.h"
+#include <QtGui/private/qtriangulator_p.h>
+#include <QtGui/private/qtriangulatingstroker_p.h>
+#include <QThreadPool>
+
+#if QT_CONFIG(opengl)
+#include <QSGVertexColorMaterial>
+#include <QOpenGLContext>
+#include <QOffscreenSurface>
+#include <QtGui/private/qopenglextensions_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+static const qreal TRI_SCALE = 1;
+
+struct ColoredVertex // must match QSGGeometry::ColoredPoint2D
+{
+ float x, y;
+ QQuickShapeGenericRenderer::Color4ub color;
+ void set(float nx, float ny, QQuickShapeGenericRenderer::Color4ub ncolor)
+ {
+ x = nx; y = ny; color = ncolor;
+ }
+};
+
+static inline QQuickShapeGenericRenderer::Color4ub colorToColor4ub(const QColor &c)
+{
+ QQuickShapeGenericRenderer::Color4ub color = {
+ uchar(qRound(c.redF() * c.alphaF() * 255)),
+ uchar(qRound(c.greenF() * c.alphaF() * 255)),
+ uchar(qRound(c.blueF() * c.alphaF() * 255)),
+ uchar(qRound(c.alphaF() * 255))
+ };
+ return color;
+}
+
+QQuickShapeGenericStrokeFillNode::QQuickShapeGenericStrokeFillNode(QQuickWindow *window)
+ : m_geometry(new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), 0, 0)),
+ m_window(window),
+ m_material(nullptr)
+{
+ setGeometry(m_geometry);
+ activateMaterial(MatSolidColor);
+#ifdef QSG_RUNTIME_DESCRIPTION
+ qsgnode_set_description(this, QLatin1String("stroke-fill"));
+#endif
+}
+
+QQuickShapeGenericStrokeFillNode::~QQuickShapeGenericStrokeFillNode()
+{
+ delete m_geometry;
+}
+
+void QQuickShapeGenericStrokeFillNode::activateMaterial(Material m)
+{
+ switch (m) {
+ case MatSolidColor:
+ // Use vertexcolor material. Items with different colors remain batchable
+ // this way, at the expense of having to provide per-vertex color values.
+ if (!m_solidColorMaterial)
+ m_solidColorMaterial.reset(QQuickShapeGenericMaterialFactory::createVertexColor(m_window));
+ m_material = m_solidColorMaterial.data();
+ break;
+ case MatLinearGradient:
+ if (!m_linearGradientMaterial)
+ m_linearGradientMaterial.reset(QQuickShapeGenericMaterialFactory::createLinearGradient(m_window, this));
+ m_material = m_linearGradientMaterial.data();
+ break;
+ default:
+ qWarning("Unknown material %d", m);
+ return;
+ }
+
+ if (material() != m_material)
+ setMaterial(m_material);
+}
+
+static bool q_supportsElementIndexUint(QSGRendererInterface::GraphicsApi api)
+{
+ static bool elementIndexUint = true;
+#if QT_CONFIG(opengl)
+ if (api == QSGRendererInterface::OpenGL) {
+ static bool elementIndexUintChecked = false;
+ if (!elementIndexUintChecked) {
+ elementIndexUintChecked = true;
+ QOpenGLContext *context = QOpenGLContext::currentContext();
+ QScopedPointer<QOpenGLContext> dummyContext;
+ QScopedPointer<QOffscreenSurface> dummySurface;
+ bool ok = true;
+ if (!context) {
+ dummyContext.reset(new QOpenGLContext);
+ dummyContext->create();
+ context = dummyContext.data();
+ dummySurface.reset(new QOffscreenSurface);
+ dummySurface->setFormat(context->format());
+ dummySurface->create();
+ ok = context->makeCurrent(dummySurface.data());
+ }
+ if (ok) {
+ elementIndexUint = static_cast<QOpenGLExtensions *>(context->functions())->hasOpenGLExtension(
+ QOpenGLExtensions::ElementIndexUint);
+ }
+ }
+ }
+#else
+ Q_UNUSED(api);
+#endif
+ return elementIndexUint;
+}
+
+QQuickShapeGenericRenderer::~QQuickShapeGenericRenderer()
+{
+ for (ShapePathData &d : m_sp) {
+ if (d.pendingFill)
+ d.pendingFill->orphaned = true;
+ if (d.pendingStroke)
+ d.pendingStroke->orphaned = true;
+ }
+}
+
+// sync, and so triangulation too, happens on the gui thread
+// - except when async is set, in which case triangulation is moved to worker threads
+
+void QQuickShapeGenericRenderer::beginSync(int totalCount)
+{
+ if (m_sp.count() != totalCount) {
+ m_sp.resize(totalCount);
+ m_accDirty |= DirtyList;
+ }
+ for (ShapePathData &d : m_sp)
+ d.syncDirty = 0;
+}
+
+void QQuickShapeGenericRenderer::setPath(int index, const QQuickPath *path)
+{
+ ShapePathData &d(m_sp[index]);
+ d.path = path ? path->path() : QPainterPath();
+ d.syncDirty |= DirtyFillGeom | DirtyStrokeGeom;
+}
+
+void QQuickShapeGenericRenderer::setJSPath(int index, const QQuickShapePathCommands &path)
+{
+ ShapePathData &d(m_sp[index]);
+ d.path = path.toPainterPath();
+ d.syncDirty |= DirtyFillGeom | DirtyStrokeGeom;
+}
+
+void QQuickShapeGenericRenderer::setStrokeColor(int index, const QColor &color)
+{
+ ShapePathData &d(m_sp[index]);
+ d.strokeColor = colorToColor4ub(color);
+ d.syncDirty |= DirtyColor;
+}
+
+void QQuickShapeGenericRenderer::setStrokeWidth(int index, qreal w)
+{
+ ShapePathData &d(m_sp[index]);
+ d.strokeWidth = w;
+ if (w >= 0.0f)
+ d.pen.setWidthF(w);
+ d.syncDirty |= DirtyStrokeGeom;
+}
+
+void QQuickShapeGenericRenderer::setFillColor(int index, const QColor &color)
+{
+ ShapePathData &d(m_sp[index]);
+ d.fillColor = colorToColor4ub(color);
+ d.syncDirty |= DirtyColor;
+}
+
+void QQuickShapeGenericRenderer::setFillRule(int index, QQuickShapePath::FillRule fillRule)
+{
+ ShapePathData &d(m_sp[index]);
+ d.fillRule = Qt::FillRule(fillRule);
+ d.syncDirty |= DirtyFillGeom;
+}
+
+void QQuickShapeGenericRenderer::setJoinStyle(int index, QQuickShapePath::JoinStyle joinStyle, int miterLimit)
+{
+ ShapePathData &d(m_sp[index]);
+ d.pen.setJoinStyle(Qt::PenJoinStyle(joinStyle));
+ d.pen.setMiterLimit(miterLimit);
+ d.syncDirty |= DirtyStrokeGeom;
+}
+
+void QQuickShapeGenericRenderer::setCapStyle(int index, QQuickShapePath::CapStyle capStyle)
+{
+ ShapePathData &d(m_sp[index]);
+ d.pen.setCapStyle(Qt::PenCapStyle(capStyle));
+ d.syncDirty |= DirtyStrokeGeom;
+}
+
+void QQuickShapeGenericRenderer::setStrokeStyle(int index, QQuickShapePath::StrokeStyle strokeStyle,
+ qreal dashOffset, const QVector<qreal> &dashPattern)
+{
+ ShapePathData &d(m_sp[index]);
+ d.pen.setStyle(Qt::PenStyle(strokeStyle));
+ if (strokeStyle == QQuickShapePath::DashLine) {
+ d.pen.setDashPattern(dashPattern);
+ d.pen.setDashOffset(dashOffset);
+ }
+ d.syncDirty |= DirtyStrokeGeom;
+}
+
+void QQuickShapeGenericRenderer::setFillGradient(int index, QQuickShapeGradient *gradient)
+{
+ ShapePathData &d(m_sp[index]);
+ d.fillGradientActive = gradient != nullptr;
+#if QT_CONFIG(opengl)
+ if (gradient) {
+ d.fillGradient.stops = gradient->gradientStops(); // sorted
+ d.fillGradient.spread = gradient->spread();
+ if (QQuickShapeLinearGradient *g = qobject_cast<QQuickShapeLinearGradient *>(gradient)) {
+ d.fillGradient.start = QPointF(g->x1(), g->y1());
+ d.fillGradient.end = QPointF(g->x2(), g->y2());
+ } else {
+ Q_UNREACHABLE();
+ }
+ }
+#endif
+ d.syncDirty |= DirtyFillGradient;
+}
+
+void QQuickShapeFillRunnable::run()
+{
+ QQuickShapeGenericRenderer::triangulateFill(path, fillColor, &fillVertices, &fillIndices, &indexType, supportsElementIndexUint);
+ emit done(this);
+}
+
+void QQuickShapeStrokeRunnable::run()
+{
+ QQuickShapeGenericRenderer::triangulateStroke(path, pen, strokeColor, &strokeVertices, clipSize);
+ emit done(this);
+}
+
+void QQuickShapeGenericRenderer::setAsyncCallback(void (*callback)(void *), void *data)
+{
+ m_asyncCallback = callback;
+ m_asyncCallbackData = data;
+}
+
+static QThreadPool *pathWorkThreadPool = nullptr;
+
+static void deletePathWorkThreadPool()
+{
+ delete pathWorkThreadPool;
+ pathWorkThreadPool = nullptr;
+}
+
+void QQuickShapeGenericRenderer::endSync(bool async)
+{
+ bool didKickOffAsync = false;
+
+ for (int i = 0; i < m_sp.count(); ++i) {
+ ShapePathData &d(m_sp[i]);
+ if (!d.syncDirty)
+ continue;
+
+ m_accDirty |= d.syncDirty;
+
+ // Use a shadow dirty flag in order to avoid losing state in case there are
+ // multiple syncs with different dirty flags before we get to updateNode()
+ // on the render thread (with the gui thread blocked). For our purposes
+ // here syncDirty is still required since geometry regeneration must only
+ // happen when there was an actual change in this particular sync round.
+ d.effectiveDirty |= d.syncDirty;
+
+ if (d.path.isEmpty()) {
+ d.fillVertices.clear();
+ d.fillIndices.clear();
+ d.strokeVertices.clear();
+ continue;
+ }
+
+ if (async && !pathWorkThreadPool) {
+ qAddPostRoutine(deletePathWorkThreadPool);
+ pathWorkThreadPool = new QThreadPool;
+ const int idealCount = QThread::idealThreadCount();
+ pathWorkThreadPool->setMaxThreadCount(idealCount > 0 ? idealCount * 2 : 4);
+ }
+
+ if ((d.syncDirty & DirtyFillGeom) && d.fillColor.a) {
+ d.path.setFillRule(d.fillRule);
+ if (m_api == QSGRendererInterface::Unknown)
+ m_api = m_item->window()->rendererInterface()->graphicsApi();
+ if (async) {
+ QQuickShapeFillRunnable *r = new QQuickShapeFillRunnable;
+ r->setAutoDelete(false);
+ if (d.pendingFill)
+ d.pendingFill->orphaned = true;
+ d.pendingFill = r;
+ r->path = d.path;
+ r->fillColor = d.fillColor;
+ r->supportsElementIndexUint = q_supportsElementIndexUint(m_api);
+ // Unlikely in practice but in theory m_sp could be
+ // resized. Therefore, capture 'i' instead of 'd'.
+ QObject::connect(r, &QQuickShapeFillRunnable::done, qApp, [this, i](QQuickShapeFillRunnable *r) {
+ // Bail out when orphaned (meaning either another run was
+ // started after this one, or the renderer got destroyed).
+ if (!r->orphaned && i < m_sp.count()) {
+ ShapePathData &d(m_sp[i]);
+ d.fillVertices = r->fillVertices;
+ d.fillIndices = r->fillIndices;
+ d.indexType = r->indexType;
+ d.pendingFill = nullptr;
+ d.effectiveDirty |= DirtyFillGeom;
+ maybeUpdateAsyncItem();
+ }
+ r->deleteLater();
+ });
+ didKickOffAsync = true;
+ pathWorkThreadPool->start(r);
+ } else {
+ triangulateFill(d.path, d.fillColor, &d.fillVertices, &d.fillIndices, &d.indexType, q_supportsElementIndexUint(m_api));
+ }
+ }
+
+ if ((d.syncDirty & DirtyStrokeGeom) && d.strokeWidth >= 0.0f && d.strokeColor.a) {
+ if (async) {
+ QQuickShapeStrokeRunnable *r = new QQuickShapeStrokeRunnable;
+ r->setAutoDelete(false);
+ if (d.pendingStroke)
+ d.pendingStroke->orphaned = true;
+ d.pendingStroke = r;
+ r->path = d.path;
+ r->pen = d.pen;
+ r->strokeColor = d.strokeColor;
+ r->clipSize = QSize(m_item->width(), m_item->height());
+ QObject::connect(r, &QQuickShapeStrokeRunnable::done, qApp, [this, i](QQuickShapeStrokeRunnable *r) {
+ if (!r->orphaned && i < m_sp.count()) {
+ ShapePathData &d(m_sp[i]);
+ d.strokeVertices = r->strokeVertices;
+ d.pendingStroke = nullptr;
+ d.effectiveDirty |= DirtyStrokeGeom;
+ maybeUpdateAsyncItem();
+ }
+ r->deleteLater();
+ });
+ didKickOffAsync = true;
+ pathWorkThreadPool->start(r);
+ } else {
+ triangulateStroke(d.path, d.pen, d.strokeColor, &d.strokeVertices,
+ QSize(m_item->width(), m_item->height()));
+ }
+ }
+ }
+
+ if (!didKickOffAsync && async && m_asyncCallback)
+ m_asyncCallback(m_asyncCallbackData);
+}
+
+void QQuickShapeGenericRenderer::maybeUpdateAsyncItem()
+{
+ for (const ShapePathData &d : qAsConst(m_sp)) {
+ if (d.pendingFill || d.pendingStroke)
+ return;
+ }
+ m_accDirty |= DirtyFillGeom | DirtyStrokeGeom;
+ m_item->update();
+ if (m_asyncCallback)
+ m_asyncCallback(m_asyncCallbackData);
+}
+
+// the stroke/fill triangulation functions may be invoked either on the gui
+// thread or some worker thread and must thus be self-contained.
+void QQuickShapeGenericRenderer::triangulateFill(const QPainterPath &path,
+ const Color4ub &fillColor,
+ VertexContainerType *fillVertices,
+ IndexContainerType *fillIndices,
+ QSGGeometry::Type *indexType,
+ bool supportsElementIndexUint)
+{
+ const QVectorPath &vp = qtVectorPathForPath(path);
+
+ QTriangleSet ts = qTriangulate(vp, QTransform::fromScale(TRI_SCALE, TRI_SCALE), 1, supportsElementIndexUint);
+ const int vertexCount = ts.vertices.count() / 2; // just a qreal vector with x,y hence the / 2
+ fillVertices->resize(vertexCount);
+ ColoredVertex *vdst = reinterpret_cast<ColoredVertex *>(fillVertices->data());
+ const qreal *vsrc = ts.vertices.constData();
+ for (int i = 0; i < vertexCount; ++i)
+ vdst[i].set(vsrc[i * 2] / TRI_SCALE, vsrc[i * 2 + 1] / TRI_SCALE, fillColor);
+
+ size_t indexByteSize;
+ if (ts.indices.type() == QVertexIndexVector::UnsignedShort) {
+ *indexType = QSGGeometry::UnsignedShortType;
+ // fillIndices is still QVector<quint32>. Just resize to N/2 and pack
+ // the N quint16s into it.
+ fillIndices->resize(ts.indices.size() / 2);
+ indexByteSize = ts.indices.size() * sizeof(quint16);
+ } else {
+ *indexType = QSGGeometry::UnsignedIntType;
+ fillIndices->resize(ts.indices.size());
+ indexByteSize = ts.indices.size() * sizeof(quint32);
+ }
+ memcpy(fillIndices->data(), ts.indices.data(), indexByteSize);
+}
+
+void QQuickShapeGenericRenderer::triangulateStroke(const QPainterPath &path,
+ const QPen &pen,
+ const Color4ub &strokeColor,
+ VertexContainerType *strokeVertices,
+ const QSize &clipSize)
+{
+ const QVectorPath &vp = qtVectorPathForPath(path);
+ const QRectF clip(QPointF(0, 0), clipSize);
+ const qreal inverseScale = 1.0 / TRI_SCALE;
+
+ QTriangulatingStroker stroker;
+ stroker.setInvScale(inverseScale);
+
+ if (pen.style() == Qt::SolidLine) {
+ stroker.process(vp, pen, clip, 0);
+ } else {
+ QDashedStrokeProcessor dashStroker;
+ dashStroker.setInvScale(inverseScale);
+ dashStroker.process(vp, pen, clip, 0);
+ QVectorPath dashStroke(dashStroker.points(), dashStroker.elementCount(),
+ dashStroker.elementTypes(), 0);
+ stroker.process(dashStroke, pen, clip, 0);
+ }
+
+ if (!stroker.vertexCount()) {
+ strokeVertices->clear();
+ return;
+ }
+
+ const int vertexCount = stroker.vertexCount() / 2; // just a float vector with x,y hence the / 2
+ strokeVertices->resize(vertexCount);
+ ColoredVertex *vdst = reinterpret_cast<ColoredVertex *>(strokeVertices->data());
+ const float *vsrc = stroker.vertices();
+ for (int i = 0; i < vertexCount; ++i)
+ vdst[i].set(vsrc[i * 2], vsrc[i * 2 + 1], strokeColor);
+}
+
+void QQuickShapeGenericRenderer::setRootNode(QQuickShapeGenericNode *node)
+{
+ if (m_rootNode != node) {
+ m_rootNode = node;
+ m_accDirty |= DirtyList;
+ }
+}
+
+// on the render thread with gui blocked
+void QQuickShapeGenericRenderer::updateNode()
+{
+ if (!m_rootNode || !m_accDirty)
+ return;
+
+// [ m_rootNode ]
+// / / /
+// #0 [ fill ] [ stroke ] [ next ]
+// / / |
+// #1 [ fill ] [ stroke ] [ next ]
+// / / |
+// #2 [ fill ] [ stroke ] [ next ]
+// ...
+// ...
+
+ QQuickShapeGenericNode **nodePtr = &m_rootNode;
+ QQuickShapeGenericNode *prevNode = nullptr;
+
+ for (ShapePathData &d : m_sp) {
+ if (!*nodePtr) {
+ Q_ASSERT(prevNode);
+ *nodePtr = new QQuickShapeGenericNode;
+ prevNode->m_next = *nodePtr;
+ prevNode->appendChildNode(*nodePtr);
+ }
+
+ QQuickShapeGenericNode *node = *nodePtr;
+
+ if (m_accDirty & DirtyList)
+ d.effectiveDirty |= DirtyFillGeom | DirtyStrokeGeom | DirtyColor | DirtyFillGradient;
+
+ if (!d.effectiveDirty) {
+ prevNode = node;
+ nodePtr = &node->m_next;
+ continue;
+ }
+
+ if (d.fillColor.a == 0) {
+ delete node->m_fillNode;
+ node->m_fillNode = nullptr;
+ } else if (!node->m_fillNode) {
+ node->m_fillNode = new QQuickShapeGenericStrokeFillNode(m_item->window());
+ if (node->m_strokeNode)
+ node->removeChildNode(node->m_strokeNode);
+ node->appendChildNode(node->m_fillNode);
+ if (node->m_strokeNode)
+ node->appendChildNode(node->m_strokeNode);
+ d.effectiveDirty |= DirtyFillGeom;
+ }
+
+ if (d.strokeWidth < 0.0f || d.strokeColor.a == 0) {
+ delete node->m_strokeNode;
+ node->m_strokeNode = nullptr;
+ } else if (!node->m_strokeNode) {
+ node->m_strokeNode = new QQuickShapeGenericStrokeFillNode(m_item->window());
+ node->appendChildNode(node->m_strokeNode);
+ d.effectiveDirty |= DirtyStrokeGeom;
+ }
+
+ updateFillNode(&d, node);
+ updateStrokeNode(&d, node);
+
+ d.effectiveDirty = 0;
+
+ prevNode = node;
+ nodePtr = &node->m_next;
+ }
+
+ if (*nodePtr && prevNode) {
+ prevNode->removeChildNode(*nodePtr);
+ delete *nodePtr;
+ *nodePtr = nullptr;
+ }
+
+ m_accDirty = 0;
+}
+
+void QQuickShapeGenericRenderer::updateShadowDataInNode(ShapePathData *d, QQuickShapeGenericStrokeFillNode *n)
+{
+ if (d->fillGradientActive) {
+#if QT_CONFIG(opengl)
+ if (d->effectiveDirty & DirtyFillGradient)
+ n->m_fillGradient = d->fillGradient;
+#else
+ Q_UNUSED(n);
+#endif
+ }
+}
+
+void QQuickShapeGenericRenderer::updateFillNode(ShapePathData *d, QQuickShapeGenericNode *node)
+{
+ if (!node->m_fillNode)
+ return;
+ if (!(d->effectiveDirty & (DirtyFillGeom | DirtyColor | DirtyFillGradient)))
+ return;
+
+ // Make a copy of the data that will be accessed by the material on
+ // the render thread. This must be done even when we bail out below.
+ QQuickShapeGenericStrokeFillNode *n = node->m_fillNode;
+ updateShadowDataInNode(d, n);
+
+ QSGGeometry *g = n->m_geometry;
+ if (d->fillVertices.isEmpty()) {
+ if (g->vertexCount() || g->indexCount()) {
+ g->allocate(0, 0);
+ n->markDirty(QSGNode::DirtyGeometry);
+ }
+ return;
+ }
+
+ if (d->fillGradientActive) {
+ n->activateMaterial(QQuickShapeGenericStrokeFillNode::MatLinearGradient);
+ if (d->effectiveDirty & DirtyFillGradient) {
+ // Gradients are implemented via a texture-based material.
+ n->markDirty(QSGNode::DirtyMaterial);
+ // stop here if only the gradient changed; no need to touch the geometry
+ if (!(d->effectiveDirty & DirtyFillGeom))
+ return;
+ }
+ } else {
+ n->activateMaterial(QQuickShapeGenericStrokeFillNode::MatSolidColor);
+ // fast path for updating only color values when no change in vertex positions
+ if ((d->effectiveDirty & DirtyColor) && !(d->effectiveDirty & DirtyFillGeom)) {
+ ColoredVertex *vdst = reinterpret_cast<ColoredVertex *>(g->vertexData());
+ for (int i = 0; i < g->vertexCount(); ++i)
+ vdst[i].set(vdst[i].x, vdst[i].y, d->fillColor);
+ n->markDirty(QSGNode::DirtyGeometry);
+ return;
+ }
+ }
+
+ const int indexCount = d->indexType == QSGGeometry::UnsignedShortType
+ ? d->fillIndices.count() * 2 : d->fillIndices.count();
+ if (g->indexType() != d->indexType) {
+ g = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(),
+ d->fillVertices.count(), indexCount, d->indexType);
+ n->setGeometry(g);
+ delete n->m_geometry;
+ n->m_geometry = g;
+ } else {
+ g->allocate(d->fillVertices.count(), indexCount);
+ }
+ g->setDrawingMode(QSGGeometry::DrawTriangles);
+ memcpy(g->vertexData(), d->fillVertices.constData(), g->vertexCount() * g->sizeOfVertex());
+ memcpy(g->indexData(), d->fillIndices.constData(), g->indexCount() * g->sizeOfIndex());
+
+ n->markDirty(QSGNode::DirtyGeometry);
+}
+
+void QQuickShapeGenericRenderer::updateStrokeNode(ShapePathData *d, QQuickShapeGenericNode *node)
+{
+ if (!node->m_strokeNode)
+ return;
+ if (!(d->effectiveDirty & (DirtyStrokeGeom | DirtyColor)))
+ return;
+
+ QQuickShapeGenericStrokeFillNode *n = node->m_strokeNode;
+ QSGGeometry *g = n->m_geometry;
+ if (d->strokeVertices.isEmpty()) {
+ if (g->vertexCount() || g->indexCount()) {
+ g->allocate(0, 0);
+ n->markDirty(QSGNode::DirtyGeometry);
+ }
+ return;
+ }
+
+ n->markDirty(QSGNode::DirtyGeometry);
+
+ // Async loading runs update once, bails out above, then updates again once
+ // ready. Set the material dirty then. This is in-line with fill where the
+ // first activateMaterial() achieves the same.
+ if (!g->vertexCount())
+ n->markDirty(QSGNode::DirtyMaterial);
+
+ if ((d->effectiveDirty & DirtyColor) && !(d->effectiveDirty & DirtyStrokeGeom)) {
+ ColoredVertex *vdst = reinterpret_cast<ColoredVertex *>(g->vertexData());
+ for (int i = 0; i < g->vertexCount(); ++i)
+ vdst[i].set(vdst[i].x, vdst[i].y, d->strokeColor);
+ return;
+ }
+
+ g->allocate(d->strokeVertices.count(), 0);
+ g->setDrawingMode(QSGGeometry::DrawTriangleStrip);
+ memcpy(g->vertexData(), d->strokeVertices.constData(), g->vertexCount() * g->sizeOfVertex());
+}
+
+QSGMaterial *QQuickShapeGenericMaterialFactory::createVertexColor(QQuickWindow *window)
+{
+ QSGRendererInterface::GraphicsApi api = window->rendererInterface()->graphicsApi();
+
+#if QT_CONFIG(opengl)
+ if (api == QSGRendererInterface::OpenGL) // ### so much for "generic"...
+ return new QSGVertexColorMaterial;
+#endif
+
+ qWarning("Vertex-color material: Unsupported graphics API %d", api);
+ return nullptr;
+}
+
+QSGMaterial *QQuickShapeGenericMaterialFactory::createLinearGradient(QQuickWindow *window,
+ QQuickShapeGenericStrokeFillNode *node)
+{
+ QSGRendererInterface::GraphicsApi api = window->rendererInterface()->graphicsApi();
+
+#if QT_CONFIG(opengl)
+ if (api == QSGRendererInterface::OpenGL) // ### so much for "generic"...
+ return new QQuickShapeLinearGradientMaterial(node);
+#else
+ Q_UNUSED(node);
+#endif
+
+ qWarning("Linear gradient material: Unsupported graphics API %d", api);
+ return nullptr;
+}
+
+#if QT_CONFIG(opengl)
+
+QSGMaterialType QQuickShapeLinearGradientShader::type;
+
+QQuickShapeLinearGradientShader::QQuickShapeLinearGradientShader()
+{
+ setShaderSourceFile(QOpenGLShader::Vertex,
+ QStringLiteral(":/qt-project.org/items/shaders/lineargradient.vert"));
+ setShaderSourceFile(QOpenGLShader::Fragment,
+ QStringLiteral(":/qt-project.org/items/shaders/lineargradient.frag"));
+}
+
+void QQuickShapeLinearGradientShader::initialize()
+{
+ m_opacityLoc = program()->uniformLocation("opacity");
+ m_matrixLoc = program()->uniformLocation("matrix");
+ m_gradStartLoc = program()->uniformLocation("gradStart");
+ m_gradEndLoc = program()->uniformLocation("gradEnd");
+}
+
+void QQuickShapeLinearGradientShader::updateState(const RenderState &state, QSGMaterial *mat, QSGMaterial *)
+{
+ QQuickShapeLinearGradientMaterial *m = static_cast<QQuickShapeLinearGradientMaterial *>(mat);
+
+ if (state.isOpacityDirty())
+ program()->setUniformValue(m_opacityLoc, state.opacity());
+
+ if (state.isMatrixDirty())
+ program()->setUniformValue(m_matrixLoc, state.combinedMatrix());
+
+ QQuickShapeGenericStrokeFillNode *node = m->node();
+ program()->setUniformValue(m_gradStartLoc, QVector2D(node->m_fillGradient.start));
+ program()->setUniformValue(m_gradEndLoc, QVector2D(node->m_fillGradient.end));
+
+ QSGTexture *tx = QQuickShapeGradientCache::currentCache()->get(node->m_fillGradient);
+ tx->bind();
+}
+
+char const *const *QQuickShapeLinearGradientShader::attributeNames() const
+{
+ static const char *const attr[] = { "vertexCoord", "vertexColor", nullptr };
+ return attr;
+}
+
+int QQuickShapeLinearGradientMaterial::compare(const QSGMaterial *other) const
+{
+ Q_ASSERT(other && type() == other->type());
+ const QQuickShapeLinearGradientMaterial *m = static_cast<const QQuickShapeLinearGradientMaterial *>(other);
+
+ QQuickShapeGenericStrokeFillNode *a = node();
+ QQuickShapeGenericStrokeFillNode *b = m->node();
+ Q_ASSERT(a && b);
+ if (a == b)
+ return 0;
+
+ const QQuickShapeGradientCache::GradientDesc *ga = &a->m_fillGradient;
+ const QQuickShapeGradientCache::GradientDesc *gb = &b->m_fillGradient;
+
+ if (int d = ga->spread - gb->spread)
+ return d;
+
+ if (int d = ga->start.x() - gb->start.x())
+ return d;
+ if (int d = ga->start.y() - gb->start.y())
+ return d;
+ if (int d = ga->end.x() - gb->end.x())
+ return d;
+ if (int d = ga->end.y() - gb->end.y())
+ return d;
+
+ if (int d = ga->stops.count() - gb->stops.count())
+ return d;
+
+ for (int i = 0; i < ga->stops.count(); ++i) {
+ if (int d = ga->stops[i].first - gb->stops[i].first)
+ return d;
+ if (int d = ga->stops[i].second.rgba() - gb->stops[i].second.rgba())
+ return d;
+ }
+
+ return 0;
+}
+
+#endif // QT_CONFIG(opengl)
+
+QT_END_NAMESPACE
diff --git a/src/imports/shapes/qquickshapegenericrenderer_p.h b/src/imports/shapes/qquickshapegenericrenderer_p.h
new file mode 100644
index 0000000000..1f36e3decf
--- /dev/null
+++ b/src/imports/shapes/qquickshapegenericrenderer_p.h
@@ -0,0 +1,308 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKSHAPEGENERICRENDERER_P_H
+#define QQUICKSHAPEGENERICRENDERER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of a number of Qt sources files. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qquickshape_p_p.h"
+#include <qsgnode.h>
+#include <qsggeometry.h>
+#include <qsgmaterial.h>
+#include <qsgrendererinterface.h>
+#include <QtCore/qrunnable.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickShapeGenericNode;
+class QQuickShapeGenericStrokeFillNode;
+class QQuickShapeFillRunnable;
+class QQuickShapeStrokeRunnable;
+
+class QQuickShapeGenericRenderer : public QQuickAbstractPathRenderer
+{
+public:
+ enum Dirty {
+ DirtyFillGeom = 0x01,
+ DirtyStrokeGeom = 0x02,
+ DirtyColor = 0x04,
+ DirtyFillGradient = 0x08,
+ DirtyList = 0x10 // only for accDirty
+ };
+
+ QQuickShapeGenericRenderer(QQuickItem *item)
+ : m_item(item),
+ m_api(QSGRendererInterface::Unknown),
+ m_rootNode(nullptr),
+ m_accDirty(0),
+ m_asyncCallback(nullptr),
+ m_asyncCallbackData(nullptr)
+ { }
+ ~QQuickShapeGenericRenderer();
+
+ void beginSync(int totalCount) override;
+ void setPath(int index, const QQuickPath *path) override;
+ void setJSPath(int index, const QQuickShapePathCommands &path) override;
+ void setStrokeColor(int index, const QColor &color) override;
+ void setStrokeWidth(int index, qreal w) override;
+ void setFillColor(int index, const QColor &color) override;
+ void setFillRule(int index, QQuickShapePath::FillRule fillRule) override;
+ void setJoinStyle(int index, QQuickShapePath::JoinStyle joinStyle, int miterLimit) override;
+ void setCapStyle(int index, QQuickShapePath::CapStyle capStyle) override;
+ void setStrokeStyle(int index, QQuickShapePath::StrokeStyle strokeStyle,
+ qreal dashOffset, const QVector<qreal> &dashPattern) override;
+ void setFillGradient(int index, QQuickShapeGradient *gradient) override;
+ void endSync(bool async) override;
+ void setAsyncCallback(void (*)(void *), void *) override;
+ Flags flags() const override { return SupportsAsync; }
+
+ void updateNode() override;
+
+ void setRootNode(QQuickShapeGenericNode *node);
+
+ struct Color4ub { unsigned char r, g, b, a; };
+ typedef QVector<QSGGeometry::ColoredPoint2D> VertexContainerType;
+ typedef QVector<quint32> IndexContainerType;
+
+ static void triangulateFill(const QPainterPath &path,
+ const Color4ub &fillColor,
+ VertexContainerType *fillVertices,
+ IndexContainerType *fillIndices,
+ QSGGeometry::Type *indexType,
+ bool supportsElementIndexUint);
+ static void triangulateStroke(const QPainterPath &path,
+ const QPen &pen,
+ const Color4ub &strokeColor,
+ VertexContainerType *strokeVertices,
+ const QSize &clipSize);
+
+private:
+ void maybeUpdateAsyncItem();
+
+ struct ShapePathData {
+ float strokeWidth;
+ QPen pen;
+ Color4ub strokeColor;
+ Color4ub fillColor;
+ Qt::FillRule fillRule;
+ QPainterPath path;
+ bool fillGradientActive;
+#if QT_CONFIG(opengl)
+ QQuickShapeGradientCache::GradientDesc fillGradient;
+#endif
+ VertexContainerType fillVertices;
+ IndexContainerType fillIndices;
+ QSGGeometry::Type indexType;
+ VertexContainerType strokeVertices;
+ int syncDirty;
+ int effectiveDirty = 0;
+ QQuickShapeFillRunnable *pendingFill = nullptr;
+ QQuickShapeStrokeRunnable *pendingStroke = nullptr;
+ };
+
+ void updateShadowDataInNode(ShapePathData *d, QQuickShapeGenericStrokeFillNode *n);
+ void updateFillNode(ShapePathData *d, QQuickShapeGenericNode *node);
+ void updateStrokeNode(ShapePathData *d, QQuickShapeGenericNode *node);
+
+ QQuickItem *m_item;
+ QSGRendererInterface::GraphicsApi m_api;
+ QQuickShapeGenericNode *m_rootNode;
+ QVector<ShapePathData> m_sp;
+ int m_accDirty;
+ void (*m_asyncCallback)(void *);
+ void *m_asyncCallbackData;
+};
+
+class QQuickShapeFillRunnable : public QObject, public QRunnable
+{
+ Q_OBJECT
+
+public:
+ void run() override;
+
+ bool orphaned = false;
+
+ // input
+ QPainterPath path;
+ QQuickShapeGenericRenderer::Color4ub fillColor;
+ bool supportsElementIndexUint;
+
+ // output
+ QQuickShapeGenericRenderer::VertexContainerType fillVertices;
+ QQuickShapeGenericRenderer::IndexContainerType fillIndices;
+ QSGGeometry::Type indexType;
+
+Q_SIGNALS:
+ void done(QQuickShapeFillRunnable *self);
+};
+
+class QQuickShapeStrokeRunnable : public QObject, public QRunnable
+{
+ Q_OBJECT
+
+public:
+ void run() override;
+
+ bool orphaned = false;
+
+ // input
+ QPainterPath path;
+ QPen pen;
+ QQuickShapeGenericRenderer::Color4ub strokeColor;
+ QSize clipSize;
+
+ // output
+ QQuickShapeGenericRenderer::VertexContainerType strokeVertices;
+
+Q_SIGNALS:
+ void done(QQuickShapeStrokeRunnable *self);
+};
+
+class QQuickShapeGenericStrokeFillNode : public QSGGeometryNode
+{
+public:
+ QQuickShapeGenericStrokeFillNode(QQuickWindow *window);
+ ~QQuickShapeGenericStrokeFillNode();
+
+ enum Material {
+ MatSolidColor,
+ MatLinearGradient
+ };
+
+ void activateMaterial(Material m);
+
+ QQuickWindow *window() const { return m_window; }
+
+ // shadow data for custom materials
+#if QT_CONFIG(opengl)
+ QQuickShapeGradientCache::GradientDesc m_fillGradient;
+#endif
+
+private:
+ QSGGeometry *m_geometry;
+ QQuickWindow *m_window;
+ QSGMaterial *m_material;
+ QScopedPointer<QSGMaterial> m_solidColorMaterial;
+ QScopedPointer<QSGMaterial> m_linearGradientMaterial;
+
+ friend class QQuickShapeGenericRenderer;
+};
+
+class QQuickShapeGenericNode : public QSGNode
+{
+public:
+ QQuickShapeGenericStrokeFillNode *m_fillNode = nullptr;
+ QQuickShapeGenericStrokeFillNode *m_strokeNode = nullptr;
+ QQuickShapeGenericNode *m_next = nullptr;
+};
+
+class QQuickShapeGenericMaterialFactory
+{
+public:
+ static QSGMaterial *createVertexColor(QQuickWindow *window);
+ static QSGMaterial *createLinearGradient(QQuickWindow *window, QQuickShapeGenericStrokeFillNode *node);
+};
+
+#if QT_CONFIG(opengl)
+
+class QQuickShapeLinearGradientShader : public QSGMaterialShader
+{
+public:
+ QQuickShapeLinearGradientShader();
+
+ void initialize() override;
+ void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
+ char const *const *attributeNames() const override;
+
+ static QSGMaterialType type;
+
+private:
+ int m_opacityLoc = -1;
+ int m_matrixLoc = -1;
+ int m_gradStartLoc = -1;
+ int m_gradEndLoc = -1;
+};
+
+class QQuickShapeLinearGradientMaterial : public QSGMaterial
+{
+public:
+ QQuickShapeLinearGradientMaterial(QQuickShapeGenericStrokeFillNode *node)
+ : m_node(node)
+ {
+ // Passing RequiresFullMatrix is essential in order to prevent the
+ // batch renderer from baking in simple, translate-only transforms into
+ // the vertex data. The shader will rely on the fact that
+ // vertexCoord.xy is the Shape-space coordinate and so no modifications
+ // are welcome.
+ setFlag(Blending | RequiresFullMatrix);
+ }
+
+ QSGMaterialType *type() const override
+ {
+ return &QQuickShapeLinearGradientShader::type;
+ }
+
+ int compare(const QSGMaterial *other) const override;
+
+ QSGMaterialShader *createShader() const override
+ {
+ return new QQuickShapeLinearGradientShader;
+ }
+
+ QQuickShapeGenericStrokeFillNode *node() const { return m_node; }
+
+private:
+ QQuickShapeGenericStrokeFillNode *m_node;
+};
+
+#endif // QT_CONFIG(opengl)
+
+QT_END_NAMESPACE
+
+#endif // QQUICKSHAPEGENERICRENDERER_P_H
diff --git a/src/imports/shapes/qquickshapenvprrenderer.cpp b/src/imports/shapes/qquickshapenvprrenderer.cpp
new file mode 100644
index 0000000000..f3f8d807ec
--- /dev/null
+++ b/src/imports/shapes/qquickshapenvprrenderer.cpp
@@ -0,0 +1,923 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickshapenvprrenderer_p.h"
+#include <QOpenGLExtraFunctions>
+#include <QOpenGLFramebufferObject>
+#include <QOpenGLShaderProgram>
+#include <QOpenGLBuffer>
+#include <private/qquickpath_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+void QQuickShapeNvprRenderer::beginSync(int totalCount)
+{
+ if (m_sp.count() != totalCount) {
+ m_sp.resize(totalCount);
+ m_accDirty |= DirtyList;
+ }
+}
+
+void QQuickShapeNvprRenderer::setPath(int index, const QQuickPath *path)
+{
+ ShapePathGuiData &d(m_sp[index]);
+ convertPath(path, &d);
+ d.dirty |= DirtyPath;
+ m_accDirty |= DirtyPath;
+}
+
+void QQuickShapeNvprRenderer::setJSPath(int index, const QQuickShapePathCommands &path)
+{
+ ShapePathGuiData &d(m_sp[index]);
+ convertJSPath(path, &d);
+ d.dirty |= DirtyPath;
+ m_accDirty |= DirtyPath;
+}
+
+void QQuickShapeNvprRenderer::setStrokeColor(int index, const QColor &color)
+{
+ ShapePathGuiData &d(m_sp[index]);
+ d.strokeColor = color;
+ d.dirty |= DirtyStyle;
+ m_accDirty |= DirtyStyle;
+}
+
+void QQuickShapeNvprRenderer::setStrokeWidth(int index, qreal w)
+{
+ ShapePathGuiData &d(m_sp[index]);
+ d.strokeWidth = w;
+ d.dirty |= DirtyStyle;
+ m_accDirty |= DirtyStyle;
+}
+
+void QQuickShapeNvprRenderer::setFillColor(int index, const QColor &color)
+{
+ ShapePathGuiData &d(m_sp[index]);
+ d.fillColor = color;
+ d.dirty |= DirtyStyle;
+ m_accDirty |= DirtyStyle;
+}
+
+void QQuickShapeNvprRenderer::setFillRule(int index, QQuickShapePath::FillRule fillRule)
+{
+ ShapePathGuiData &d(m_sp[index]);
+ d.fillRule = fillRule;
+ d.dirty |= DirtyFillRule;
+ m_accDirty |= DirtyFillRule;
+}
+
+void QQuickShapeNvprRenderer::setJoinStyle(int index, QQuickShapePath::JoinStyle joinStyle, int miterLimit)
+{
+ ShapePathGuiData &d(m_sp[index]);
+ d.joinStyle = joinStyle;
+ d.miterLimit = miterLimit;
+ d.dirty |= DirtyStyle;
+ m_accDirty |= DirtyStyle;
+}
+
+void QQuickShapeNvprRenderer::setCapStyle(int index, QQuickShapePath::CapStyle capStyle)
+{
+ ShapePathGuiData &d(m_sp[index]);
+ d.capStyle = capStyle;
+ d.dirty |= DirtyStyle;
+ m_accDirty |= DirtyStyle;
+}
+
+void QQuickShapeNvprRenderer::setStrokeStyle(int index, QQuickShapePath::StrokeStyle strokeStyle,
+ qreal dashOffset, const QVector<qreal> &dashPattern)
+{
+ ShapePathGuiData &d(m_sp[index]);
+ d.dashActive = strokeStyle == QQuickShapePath::DashLine;
+ d.dashOffset = dashOffset;
+ d.dashPattern = dashPattern;
+ d.dirty |= DirtyDash;
+ m_accDirty |= DirtyDash;
+}
+
+void QQuickShapeNvprRenderer::setFillGradient(int index, QQuickShapeGradient *gradient)
+{
+ ShapePathGuiData &d(m_sp[index]);
+ d.fillGradientActive = gradient != nullptr;
+ if (gradient) {
+ d.fillGradient.stops = gradient->gradientStops(); // sorted
+ d.fillGradient.spread = gradient->spread();
+ if (QQuickShapeLinearGradient *g = qobject_cast<QQuickShapeLinearGradient *>(gradient)) {
+ d.fillGradient.start = QPointF(g->x1(), g->y1());
+ d.fillGradient.end = QPointF(g->x2(), g->y2());
+ } else {
+ Q_UNREACHABLE();
+ }
+ }
+ d.dirty |= DirtyFillGradient;
+ m_accDirty |= DirtyFillGradient;
+}
+
+void QQuickShapeNvprRenderer::endSync(bool)
+{
+}
+
+void QQuickShapeNvprRenderer::setNode(QQuickShapeNvprRenderNode *node)
+{
+ if (m_node != node) {
+ m_node = node;
+ m_accDirty |= DirtyList;
+ }
+}
+
+QDebug operator<<(QDebug debug, const QQuickShapeNvprRenderer::NvprPath &path)
+{
+ QDebugStateSaver saver(debug);
+ debug.space().noquote();
+ if (!path.str.isEmpty()) {
+ debug << "Path with SVG string" << path.str;
+ return debug;
+ }
+ debug << "Path with" << path.cmd.count() << "commands";
+ int ci = 0;
+ for (GLubyte cmd : path.cmd) {
+ static struct { GLubyte cmd; const char *s; int coordCount; } nameTab[] = {
+ { GL_MOVE_TO_NV, "moveTo", 2 },
+ { GL_LINE_TO_NV, "lineTo", 2 },
+ { GL_QUADRATIC_CURVE_TO_NV, "quadTo", 4 },
+ { GL_CUBIC_CURVE_TO_NV, "cubicTo", 6 },
+ { GL_LARGE_CW_ARC_TO_NV, "arcTo-large-CW", 5 },
+ { GL_LARGE_CCW_ARC_TO_NV, "arcTo-large-CCW", 5 },
+ { GL_SMALL_CW_ARC_TO_NV, "arcTo-small-CW", 5 },
+ { GL_SMALL_CCW_ARC_TO_NV, "arcTo-small-CCW", 5 },
+ { GL_CLOSE_PATH_NV, "closePath", 0 } };
+ for (size_t i = 0; i < sizeof(nameTab) / sizeof(nameTab[0]); ++i) {
+ if (nameTab[i].cmd == cmd) {
+ QByteArray cs;
+ for (int j = 0; j < nameTab[i].coordCount; ++j) {
+ cs.append(QByteArray::number(path.coord[ci++]));
+ cs.append(' ');
+ }
+ debug << "\n " << nameTab[i].s << " " << cs;
+ break;
+ }
+ }
+ }
+ return debug;
+}
+
+static inline void appendCoords(QVector<GLfloat> *v, QQuickCurve *c, QPointF *pos)
+{
+ QPointF p(c->hasRelativeX() ? pos->x() + c->relativeX() : c->x(),
+ c->hasRelativeY() ? pos->y() + c->relativeY() : c->y());
+ v->append(p.x());
+ v->append(p.y());
+ *pos = p;
+}
+
+static inline void appendControlCoords(QVector<GLfloat> *v, QQuickPathQuad *c, const QPointF &pos)
+{
+ QPointF p(c->hasRelativeControlX() ? pos.x() + c->relativeControlX() : c->controlX(),
+ c->hasRelativeControlY() ? pos.y() + c->relativeControlY() : c->controlY());
+ v->append(p.x());
+ v->append(p.y());
+}
+
+static inline void appendControl1Coords(QVector<GLfloat> *v, QQuickPathCubic *c, const QPointF &pos)
+{
+ QPointF p(c->hasRelativeControl1X() ? pos.x() + c->relativeControl1X() : c->control1X(),
+ c->hasRelativeControl1Y() ? pos.y() + c->relativeControl1Y() : c->control1Y());
+ v->append(p.x());
+ v->append(p.y());
+}
+
+static inline void appendControl2Coords(QVector<GLfloat> *v, QQuickPathCubic *c, const QPointF &pos)
+{
+ QPointF p(c->hasRelativeControl2X() ? pos.x() + c->relativeControl2X() : c->control2X(),
+ c->hasRelativeControl2Y() ? pos.y() + c->relativeControl2Y() : c->control2Y());
+ v->append(p.x());
+ v->append(p.y());
+}
+
+void QQuickShapeNvprRenderer::convertPath(const QQuickPath *path, ShapePathGuiData *d)
+{
+ d->path = NvprPath();
+ if (!path)
+ return;
+
+ const QList<QQuickPathElement *> &pp(QQuickPathPrivate::get(path)->_pathElements);
+ if (pp.isEmpty())
+ return;
+
+ QPointF startPos(path->startX(), path->startY());
+ QPointF pos(startPos);
+ if (!qFuzzyIsNull(pos.x()) || !qFuzzyIsNull(pos.y())) {
+ d->path.cmd.append(GL_MOVE_TO_NV);
+ d->path.coord.append(pos.x());
+ d->path.coord.append(pos.y());
+ }
+
+ for (QQuickPathElement *e : pp) {
+ if (QQuickPathMove *o = qobject_cast<QQuickPathMove *>(e)) {
+ d->path.cmd.append(GL_MOVE_TO_NV);
+ appendCoords(&d->path.coord, o, &pos);
+ startPos = pos;
+ } else if (QQuickPathLine *o = qobject_cast<QQuickPathLine *>(e)) {
+ d->path.cmd.append(GL_LINE_TO_NV);
+ appendCoords(&d->path.coord, o, &pos);
+ } else if (QQuickPathQuad *o = qobject_cast<QQuickPathQuad *>(e)) {
+ d->path.cmd.append(GL_QUADRATIC_CURVE_TO_NV);
+ appendControlCoords(&d->path.coord, o, pos);
+ appendCoords(&d->path.coord, o, &pos);
+ } else if (QQuickPathCubic *o = qobject_cast<QQuickPathCubic *>(e)) {
+ d->path.cmd.append(GL_CUBIC_CURVE_TO_NV);
+ appendControl1Coords(&d->path.coord, o, pos);
+ appendControl2Coords(&d->path.coord, o, pos);
+ appendCoords(&d->path.coord, o, &pos);
+ } else if (QQuickPathArc *o = qobject_cast<QQuickPathArc *>(e)) {
+ const bool sweepFlag = o->direction() == QQuickPathArc::Clockwise; // maps to CCW, not a typo
+ GLenum cmd;
+ if (o->useLargeArc())
+ cmd = sweepFlag ? GL_LARGE_CCW_ARC_TO_NV : GL_LARGE_CW_ARC_TO_NV;
+ else
+ cmd = sweepFlag ? GL_SMALL_CCW_ARC_TO_NV : GL_SMALL_CW_ARC_TO_NV;
+ d->path.cmd.append(cmd);
+ d->path.coord.append(o->radiusX());
+ d->path.coord.append(o->radiusY());
+ d->path.coord.append(o->xAxisRotation());
+ appendCoords(&d->path.coord, o, &pos);
+ } else if (QQuickPathSvg *o = qobject_cast<QQuickPathSvg *>(e)) {
+ // PathSvg cannot be combined with other elements. But take at
+ // least startX and startY into account.
+ if (d->path.str.isEmpty())
+ d->path.str = QString(QStringLiteral("M %1 %2 ")).arg(pos.x()).arg(pos.y()).toUtf8();
+ d->path.str.append(o->path().toUtf8());
+ } else {
+ qWarning() << "Shape/NVPR: unsupported Path element" << e;
+ }
+ }
+
+ // For compatibility with QTriangulatingStroker. SVG and others would not
+ // implicitly close the path when end_pos == start_pos (start_pos being the
+ // last moveTo pos); that would still need an explicit 'z' or similar. We
+ // don't have an explicit close command, so just fake a close when the
+ // positions match.
+ if (pos == startPos)
+ d->path.cmd.append(GL_CLOSE_PATH_NV);
+}
+
+void QQuickShapeNvprRenderer::convertJSPath(const QQuickShapePathCommands &path, ShapePathGuiData *d)
+{
+ d->path = NvprPath();
+ if (path.cmd.isEmpty())
+ return;
+
+ QPointF startPos(0, 0);
+ QPointF pos(startPos);
+ int coordIdx = 0;
+
+ for (QQuickShapePathCommands::Command cmd : path.cmd) {
+ switch (cmd) {
+ case QQuickShapePathCommands::MoveTo:
+ d->path.cmd.append(GL_MOVE_TO_NV);
+ pos = QPointF(path.coords[coordIdx], path.coords[coordIdx + 1]);
+ startPos = pos;
+ d->path.coord.append(pos.x());
+ d->path.coord.append(pos.y());
+ coordIdx += 2;
+ break;
+ case QQuickShapePathCommands::LineTo:
+ d->path.cmd.append(GL_LINE_TO_NV);
+ pos = QPointF(path.coords[coordIdx], path.coords[coordIdx + 1]);
+ d->path.coord.append(pos.x());
+ d->path.coord.append(pos.y());
+ coordIdx += 2;
+ break;
+ case QQuickShapePathCommands::QuadTo:
+ d->path.cmd.append(GL_QUADRATIC_CURVE_TO_NV);
+ d->path.coord.append(path.coords[coordIdx]);
+ d->path.coord.append(path.coords[coordIdx + 1]);
+ pos = QPointF(path.coords[coordIdx + 2], path.coords[coordIdx + 3]);
+ d->path.coord.append(pos.x());
+ d->path.coord.append(pos.y());
+ coordIdx += 4;
+ break;
+ case QQuickShapePathCommands::CubicTo:
+ d->path.cmd.append(GL_CUBIC_CURVE_TO_NV);
+ d->path.coord.append(path.coords[coordIdx]);
+ d->path.coord.append(path.coords[coordIdx + 1]);
+ d->path.coord.append(path.coords[coordIdx + 2]);
+ d->path.coord.append(path.coords[coordIdx + 3]);
+ pos = QPointF(path.coords[coordIdx + 4], path.coords[coordIdx + 5]);
+ d->path.coord.append(pos.x());
+ d->path.coord.append(pos.y());
+ coordIdx += 6;
+ break;
+ case QQuickShapePathCommands::ArcTo:
+ {
+ const bool sweepFlag = !qFuzzyIsNull(path.coords[coordIdx + 5]);
+ const bool useLargeArc = !qFuzzyIsNull(path.coords[coordIdx + 6]);
+ GLenum cmd;
+ if (useLargeArc)
+ cmd = sweepFlag ? GL_LARGE_CCW_ARC_TO_NV : GL_LARGE_CW_ARC_TO_NV;
+ else
+ cmd = sweepFlag ? GL_SMALL_CCW_ARC_TO_NV : GL_SMALL_CW_ARC_TO_NV;
+ d->path.cmd.append(cmd);
+ d->path.coord.append(path.coords[coordIdx]); // rx
+ d->path.coord.append(path.coords[coordIdx + 1]); // ry
+ d->path.coord.append(path.coords[coordIdx + 2]); // xrot
+ pos = QPointF(path.coords[coordIdx + 3], path.coords[coordIdx + 4]);
+ d->path.coord.append(pos.x());
+ d->path.coord.append(pos.y());
+ coordIdx += 7;
+ }
+ break;
+ default:
+ qWarning("Unknown JS path command: %d", cmd);
+ break;
+ }
+ }
+
+ if (pos == startPos)
+ d->path.cmd.append(GL_CLOSE_PATH_NV);
+}
+
+static inline QVector4D qsg_premultiply(const QColor &c, float globalOpacity)
+{
+ const float o = c.alphaF() * globalOpacity;
+ return QVector4D(c.redF() * o, c.greenF() * o, c.blueF() * o, o);
+}
+
+void QQuickShapeNvprRenderer::updateNode()
+{
+ // Called on the render thread with gui blocked -> update the node with its
+ // own copy of all relevant data.
+
+ if (!m_accDirty)
+ return;
+
+ const int count = m_sp.count();
+ const bool listChanged = m_accDirty & DirtyList;
+ if (listChanged)
+ m_node->m_sp.resize(count);
+
+ for (int i = 0; i < count; ++i) {
+ ShapePathGuiData &src(m_sp[i]);
+ QQuickShapeNvprRenderNode::ShapePathRenderData &dst(m_node->m_sp[i]);
+
+ int dirty = src.dirty;
+ src.dirty = 0;
+ if (listChanged)
+ dirty |= DirtyPath | DirtyStyle | DirtyFillRule | DirtyDash | DirtyFillGradient;
+
+ // updateNode() can be called several times with different dirty
+ // states before render() gets invoked. So accumulate.
+ dst.dirty |= dirty;
+
+ if (dirty & DirtyPath)
+ dst.source = src.path;
+
+ if (dirty & DirtyStyle) {
+ dst.strokeWidth = src.strokeWidth;
+ dst.strokeColor = qsg_premultiply(src.strokeColor, 1.0f);
+ dst.fillColor = qsg_premultiply(src.fillColor, 1.0f);
+ switch (src.joinStyle) {
+ case QQuickShapePath::MiterJoin:
+ dst.joinStyle = GL_MITER_TRUNCATE_NV;
+ break;
+ case QQuickShapePath::BevelJoin:
+ dst.joinStyle = GL_BEVEL_NV;
+ break;
+ case QQuickShapePath::RoundJoin:
+ dst.joinStyle = GL_ROUND_NV;
+ break;
+ default:
+ Q_UNREACHABLE();
+ }
+ dst.miterLimit = src.miterLimit;
+ switch (src.capStyle) {
+ case QQuickShapePath::FlatCap:
+ dst.capStyle = GL_FLAT;
+ break;
+ case QQuickShapePath::SquareCap:
+ dst.capStyle = GL_SQUARE_NV;
+ break;
+ case QQuickShapePath::RoundCap:
+ dst.capStyle = GL_ROUND_NV;
+ break;
+ default:
+ Q_UNREACHABLE();
+ }
+ }
+
+ if (dirty & DirtyFillRule) {
+ switch (src.fillRule) {
+ case QQuickShapePath::OddEvenFill:
+ dst.fillRule = GL_INVERT;
+ break;
+ case QQuickShapePath::WindingFill:
+ dst.fillRule = GL_COUNT_UP_NV;
+ break;
+ default:
+ Q_UNREACHABLE();
+ }
+ }
+
+ if (dirty & DirtyDash) {
+ dst.dashOffset = src.dashOffset;
+ if (src.dashActive) {
+ dst.dashPattern.resize(src.dashPattern.count());
+ // Multiply by strokeWidth because the Shape API follows QPen
+ // meaning the input dash pattern here is in width units.
+ for (int i = 0; i < src.dashPattern.count(); ++i)
+ dst.dashPattern[i] = GLfloat(src.dashPattern[i]) * src.strokeWidth;
+ } else {
+ dst.dashPattern.clear();
+ }
+ }
+
+ if (dirty & DirtyFillGradient) {
+ dst.fillGradientActive = src.fillGradientActive;
+ if (src.fillGradientActive)
+ dst.fillGradient = src.fillGradient;
+ }
+ }
+
+ m_node->markDirty(QSGNode::DirtyMaterial);
+ m_accDirty = 0;
+}
+
+bool QQuickShapeNvprRenderNode::nvprInited = false;
+QQuickNvprFunctions QQuickShapeNvprRenderNode::nvpr;
+QQuickNvprMaterialManager QQuickShapeNvprRenderNode::mtlmgr;
+
+QQuickShapeNvprRenderNode::~QQuickShapeNvprRenderNode()
+{
+ releaseResources();
+}
+
+void QQuickShapeNvprRenderNode::releaseResources()
+{
+ for (ShapePathRenderData &d : m_sp) {
+ if (d.path) {
+ nvpr.deletePaths(d.path, 1);
+ d.path = 0;
+ }
+ if (d.fallbackFbo) {
+ delete d.fallbackFbo;
+ d.fallbackFbo = nullptr;
+ }
+ }
+
+ m_fallbackBlitter.destroy();
+}
+
+void QQuickNvprMaterialManager::create(QQuickNvprFunctions *nvpr)
+{
+ m_nvpr = nvpr;
+}
+
+void QQuickNvprMaterialManager::releaseResources()
+{
+ QOpenGLExtraFunctions *f = QOpenGLContext::currentContext()->extraFunctions();
+ for (MaterialDesc &mtl : m_materials) {
+ if (mtl.ppl) {
+ f->glDeleteProgramPipelines(1, &mtl.ppl);
+ mtl = MaterialDesc();
+ }
+ }
+}
+
+QQuickNvprMaterialManager::MaterialDesc *QQuickNvprMaterialManager::activateMaterial(Material m)
+{
+ QOpenGLExtraFunctions *f = QOpenGLContext::currentContext()->extraFunctions();
+ MaterialDesc &mtl(m_materials[m]);
+
+ if (!mtl.ppl) {
+ if (m == MatSolid) {
+ static const char *fragSrc =
+ "#version 310 es\n"
+ "precision highp float;\n"
+ "out vec4 fragColor;\n"
+ "uniform vec4 color;\n"
+ "uniform float opacity;\n"
+ "void main() {\n"
+ " fragColor = color * opacity;\n"
+ "}\n";
+ if (!m_nvpr->createFragmentOnlyPipeline(fragSrc, &mtl.ppl, &mtl.prg)) {
+ qWarning("NVPR: Failed to create shader pipeline for solid fill");
+ return nullptr;
+ }
+ Q_ASSERT(mtl.ppl && mtl.prg);
+ mtl.uniLoc[0] = f->glGetProgramResourceLocation(mtl.prg, GL_UNIFORM, "color");
+ Q_ASSERT(mtl.uniLoc[0] >= 0);
+ mtl.uniLoc[1] = f->glGetProgramResourceLocation(mtl.prg, GL_UNIFORM, "opacity");
+ Q_ASSERT(mtl.uniLoc[1] >= 0);
+ } else if (m == MatLinearGradient) {
+ static const char *fragSrc =
+ "#version 310 es\n"
+ "precision highp float;\n"
+ "layout(location = 0) in vec2 uv;"
+ "uniform float opacity;\n"
+ "uniform sampler2D gradTab;\n"
+ "uniform vec2 gradStart;\n"
+ "uniform vec2 gradEnd;\n"
+ "out vec4 fragColor;\n"
+ "void main() {\n"
+ " vec2 gradVec = gradEnd - gradStart;\n"
+ " float gradTabIndex = dot(gradVec, uv - gradStart) / (gradVec.x * gradVec.x + gradVec.y * gradVec.y);\n"
+ " fragColor = texture(gradTab, vec2(gradTabIndex, 0.5)) * opacity;\n"
+ "}\n";
+ if (!m_nvpr->createFragmentOnlyPipeline(fragSrc, &mtl.ppl, &mtl.prg)) {
+ qWarning("NVPR: Failed to create shader pipeline for linear gradient");
+ return nullptr;
+ }
+ Q_ASSERT(mtl.ppl && mtl.prg);
+ mtl.uniLoc[1] = f->glGetProgramResourceLocation(mtl.prg, GL_UNIFORM, "opacity");
+ Q_ASSERT(mtl.uniLoc[1] >= 0);
+ mtl.uniLoc[2] = f->glGetProgramResourceLocation(mtl.prg, GL_UNIFORM, "gradStart");
+ Q_ASSERT(mtl.uniLoc[2] >= 0);
+ mtl.uniLoc[3] = f->glGetProgramResourceLocation(mtl.prg, GL_UNIFORM, "gradEnd");
+ Q_ASSERT(mtl.uniLoc[3] >= 0);
+ } else {
+ Q_UNREACHABLE();
+ }
+ }
+
+ f->glBindProgramPipeline(mtl.ppl);
+
+ return &mtl;
+}
+
+void QQuickShapeNvprRenderNode::updatePath(ShapePathRenderData *d)
+{
+ if (d->dirty & QQuickShapeNvprRenderer::DirtyPath) {
+ if (!d->path) {
+ d->path = nvpr.genPaths(1);
+ Q_ASSERT(d->path != 0);
+ }
+ if (d->source.str.isEmpty()) {
+ nvpr.pathCommands(d->path, d->source.cmd.count(), d->source.cmd.constData(),
+ d->source.coord.count(), GL_FLOAT, d->source.coord.constData());
+ } else {
+ nvpr.pathString(d->path, GL_PATH_FORMAT_SVG_NV, d->source.str.count(), d->source.str.constData());
+ }
+ }
+
+ if (d->dirty & QQuickShapeNvprRenderer::DirtyStyle) {
+ nvpr.pathParameterf(d->path, GL_PATH_STROKE_WIDTH_NV, d->strokeWidth);
+ nvpr.pathParameteri(d->path, GL_PATH_JOIN_STYLE_NV, d->joinStyle);
+ nvpr.pathParameteri(d->path, GL_PATH_MITER_LIMIT_NV, d->miterLimit);
+ nvpr.pathParameteri(d->path, GL_PATH_END_CAPS_NV, d->capStyle);
+ nvpr.pathParameteri(d->path, GL_PATH_DASH_CAPS_NV, d->capStyle);
+ }
+
+ if (d->dirty & QQuickShapeNvprRenderer::DirtyDash) {
+ nvpr.pathParameterf(d->path, GL_PATH_DASH_OFFSET_NV, d->dashOffset);
+ // count == 0 -> no dash
+ nvpr.pathDashArray(d->path, d->dashPattern.count(), d->dashPattern.constData());
+ }
+
+ if (d->dirty)
+ d->fallbackValid = false;
+}
+
+void QQuickShapeNvprRenderNode::renderStroke(ShapePathRenderData *d, int strokeStencilValue, int writeMask)
+{
+ QQuickNvprMaterialManager::MaterialDesc *mtl = mtlmgr.activateMaterial(QQuickNvprMaterialManager::MatSolid);
+ f->glProgramUniform4f(mtl->prg, mtl->uniLoc[0],
+ d->strokeColor.x(), d->strokeColor.y(), d->strokeColor.z(), d->strokeColor.w());
+ f->glProgramUniform1f(mtl->prg, mtl->uniLoc[1], inheritedOpacity());
+
+ nvpr.stencilThenCoverStrokePath(d->path, strokeStencilValue, writeMask, GL_CONVEX_HULL_NV);
+}
+
+void QQuickShapeNvprRenderNode::renderFill(ShapePathRenderData *d)
+{
+ QQuickNvprMaterialManager::MaterialDesc *mtl = nullptr;
+ if (d->fillGradientActive) {
+ mtl = mtlmgr.activateMaterial(QQuickNvprMaterialManager::MatLinearGradient);
+ QSGTexture *tx = QQuickShapeGradientCache::currentCache()->get(d->fillGradient);
+ tx->bind();
+ // uv = vec2(coeff[0] * x + coeff[1] * y + coeff[2], coeff[3] * x + coeff[4] * y + coeff[5])
+ // where x and y are in path coordinate space, which is just what
+ // we need since the gradient's start and stop are in that space too.
+ GLfloat coeff[6] = { 1, 0, 0,
+ 0, 1, 0 };
+ nvpr.programPathFragmentInputGen(mtl->prg, 0, GL_OBJECT_LINEAR_NV, 2, coeff);
+ f->glProgramUniform2f(mtl->prg, mtl->uniLoc[2], d->fillGradient.start.x(), d->fillGradient.start.y());
+ f->glProgramUniform2f(mtl->prg, mtl->uniLoc[3], d->fillGradient.end.x(), d->fillGradient.end.y());
+ } else {
+ mtl = mtlmgr.activateMaterial(QQuickNvprMaterialManager::MatSolid);
+ f->glProgramUniform4f(mtl->prg, mtl->uniLoc[0],
+ d->fillColor.x(), d->fillColor.y(), d->fillColor.z(), d->fillColor.w());
+ }
+ f->glProgramUniform1f(mtl->prg, mtl->uniLoc[1], inheritedOpacity());
+
+ const int writeMask = 0xFF;
+ nvpr.stencilThenCoverFillPath(d->path, d->fillRule, writeMask, GL_BOUNDING_BOX_NV);
+}
+
+void QQuickShapeNvprRenderNode::renderOffscreenFill(ShapePathRenderData *d)
+{
+ if (d->fallbackValid && d->fallbackFbo)
+ return;
+
+ GLfloat bb[4];
+ nvpr.getPathParameterfv(d->path, GL_PATH_STROKE_BOUNDING_BOX_NV, bb);
+ QSize sz = QSizeF(bb[2] - bb[0] + 1, bb[3] - bb[1] + 1).toSize();
+ d->fallbackSize = QSize(qMax(32, sz.width()), qMax(32, sz.height()));
+ d->fallbackTopLeft = QPointF(bb[0], bb[1]);
+
+ if (d->fallbackFbo && d->fallbackFbo->size() != d->fallbackSize) {
+ delete d->fallbackFbo;
+ d->fallbackFbo = nullptr;
+ }
+ if (!d->fallbackFbo)
+ d->fallbackFbo = new QOpenGLFramebufferObject(d->fallbackSize, QOpenGLFramebufferObject::CombinedDepthStencil);
+ if (!d->fallbackFbo->bind())
+ return;
+
+ GLint prevViewport[4];
+ f->glGetIntegerv(GL_VIEWPORT, prevViewport);
+
+ f->glViewport(0, 0, d->fallbackSize.width(), d->fallbackSize.height());
+ f->glDisable(GL_DEPTH_TEST);
+ f->glClearColor(0, 0, 0, 0);
+ f->glClearStencil(0);
+ f->glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ f->glStencilFunc(GL_NOTEQUAL, 0, 0xFF);
+ f->glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+
+ QMatrix4x4 mv;
+ mv.translate(-d->fallbackTopLeft.x(), -d->fallbackTopLeft.y());
+ nvpr.matrixLoadf(GL_PATH_MODELVIEW_NV, mv.constData());
+ QMatrix4x4 proj;
+ proj.ortho(0, d->fallbackSize.width(), d->fallbackSize.height(), 0, 1, -1);
+ nvpr.matrixLoadf(GL_PATH_PROJECTION_NV, proj.constData());
+
+ renderFill(d);
+
+ d->fallbackFbo->release();
+ f->glEnable(GL_DEPTH_TEST);
+ f->glViewport(prevViewport[0], prevViewport[1], prevViewport[2], prevViewport[3]);
+
+ d->fallbackValid = true;
+}
+
+void QQuickShapeNvprRenderNode::setupStencilForCover(bool stencilClip, int sv)
+{
+ if (!stencilClip) {
+ // Assume stencil buffer is cleared to 0 for each frame.
+ // Within the frame dppass=GL_ZERO for glStencilOp ensures stencil is reset and so no need to clear.
+ f->glStencilFunc(GL_NOTEQUAL, 0, 0xFF);
+ f->glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
+ } else {
+ f->glStencilFunc(GL_LESS, sv, 0xFF); // pass if (sv & 0xFF) < (stencil_value & 0xFF)
+ f->glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); // dppass: replace with the original value (clip's stencil ref value)
+ }
+}
+
+void QQuickShapeNvprRenderNode::render(const RenderState *state)
+{
+ f = QOpenGLContext::currentContext()->extraFunctions();
+
+ if (!nvprInited) {
+ if (!nvpr.create()) {
+ qWarning("NVPR init failed");
+ return;
+ }
+ mtlmgr.create(&nvpr);
+ nvprInited = true;
+ }
+
+ f->glUseProgram(0);
+ f->glStencilMask(~0);
+ f->glEnable(GL_STENCIL_TEST);
+
+ const bool stencilClip = state->stencilEnabled();
+ // when true, the stencil buffer already has a clip path with a ref value of sv
+ const int sv = state->stencilValue();
+ const bool hasScissor = state->scissorEnabled();
+
+ if (hasScissor) {
+ // scissor rect is already set, just enable scissoring
+ f->glEnable(GL_SCISSOR_TEST);
+ }
+
+ // Depth test against the opaque batches rendered before.
+ f->glEnable(GL_DEPTH_TEST);
+ f->glDepthFunc(GL_LESS);
+ nvpr.pathCoverDepthFunc(GL_LESS);
+ nvpr.pathStencilDepthOffset(-0.05f, -1);
+
+ bool reloadMatrices = true;
+
+ for (ShapePathRenderData &d : m_sp) {
+ updatePath(&d);
+
+ const bool hasFill = d.hasFill();
+ const bool hasStroke = d.hasStroke();
+
+ if (hasFill && stencilClip) {
+ // Fall back to a texture when complex clipping is in use and we have
+ // to fill. Reconciling glStencilFillPath's and the scenegraph's clip
+ // stencil semantics has not succeeded so far...
+ if (hasScissor)
+ f->glDisable(GL_SCISSOR_TEST);
+ renderOffscreenFill(&d);
+ reloadMatrices = true;
+ if (hasScissor)
+ f->glEnable(GL_SCISSOR_TEST);
+ }
+
+ if (reloadMatrices) {
+ reloadMatrices = false;
+ nvpr.matrixLoadf(GL_PATH_MODELVIEW_NV, matrix()->constData());
+ nvpr.matrixLoadf(GL_PATH_PROJECTION_NV, state->projectionMatrix()->constData());
+ }
+
+ // Fill!
+ if (hasFill) {
+ if (!stencilClip) {
+ setupStencilForCover(false, 0);
+ renderFill(&d);
+ } else {
+ if (!m_fallbackBlitter.isCreated())
+ m_fallbackBlitter.create();
+ f->glStencilFunc(GL_EQUAL, sv, 0xFF);
+ f->glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ QMatrix4x4 mv = *matrix();
+ mv.translate(d.fallbackTopLeft.x(), d.fallbackTopLeft.y());
+ m_fallbackBlitter.texturedQuad(d.fallbackFbo->texture(), d.fallbackFbo->size(),
+ *state->projectionMatrix(), mv,
+ inheritedOpacity());
+ }
+ }
+
+ // Stroke!
+ if (hasStroke) {
+ const int strokeStencilValue = 0x80;
+ const int writeMask = 0x80;
+
+ setupStencilForCover(stencilClip, sv);
+ if (stencilClip) {
+ // for the stencil step (eff. read mask == 0xFF & ~writeMask)
+ nvpr.pathStencilFunc(GL_EQUAL, sv, 0xFF);
+ // With stencilCLip == true the read mask for the stencil test before the stencil step is 0x7F.
+ // This assumes the clip stencil value is <= 127.
+ if (sv >= strokeStencilValue)
+ qWarning("Shape/NVPR: stencil clip ref value %d too large; expect rendering errors", sv);
+ }
+
+ renderStroke(&d, strokeStencilValue, writeMask);
+ }
+
+ if (stencilClip)
+ nvpr.pathStencilFunc(GL_ALWAYS, 0, ~0);
+
+ d.dirty = 0;
+ }
+
+ f->glBindProgramPipeline(0);
+}
+
+QSGRenderNode::StateFlags QQuickShapeNvprRenderNode::changedStates() const
+{
+ return BlendState | StencilState | DepthState | ScissorState;
+}
+
+QSGRenderNode::RenderingFlags QQuickShapeNvprRenderNode::flags() const
+{
+ return DepthAwareRendering; // avoid hitting the less optimal no-opaque-batch path in the renderer
+}
+
+bool QQuickShapeNvprRenderNode::isSupported()
+{
+ static const bool nvprDisabled = qEnvironmentVariableIntValue("QT_NO_NVPR") != 0;
+ return !nvprDisabled && QQuickNvprFunctions::isSupported();
+}
+
+bool QQuickNvprBlitter::create()
+{
+ if (isCreated())
+ destroy();
+
+ m_program = new QOpenGLShaderProgram;
+ if (QOpenGLContext::currentContext()->format().profile() == QSurfaceFormat::CoreProfile) {
+ m_program->addCacheableShaderFromSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/items/shaders/shadereffect_core.vert"));
+ m_program->addCacheableShaderFromSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/items/shaders/shadereffect_core.frag"));
+ } else {
+ m_program->addCacheableShaderFromSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/items/shaders/shadereffect.vert"));
+ m_program->addCacheableShaderFromSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/items/shaders/shadereffect.frag"));
+ }
+ m_program->bindAttributeLocation("qt_Vertex", 0);
+ m_program->bindAttributeLocation("qt_MultiTexCoord0", 1);
+ if (!m_program->link())
+ return false;
+
+ m_matrixLoc = m_program->uniformLocation("qt_Matrix");
+ m_opacityLoc = m_program->uniformLocation("qt_Opacity");
+
+ m_buffer = new QOpenGLBuffer;
+ if (!m_buffer->create())
+ return false;
+ m_buffer->bind();
+ m_buffer->allocate(4 * sizeof(GLfloat) * 6);
+ m_buffer->release();
+
+ return true;
+}
+
+void QQuickNvprBlitter::destroy()
+{
+ if (m_program) {
+ delete m_program;
+ m_program = nullptr;
+ }
+ if (m_buffer) {
+ delete m_buffer;
+ m_buffer = nullptr;
+ }
+}
+
+void QQuickNvprBlitter::texturedQuad(GLuint textureId, const QSize &size,
+ const QMatrix4x4 &proj, const QMatrix4x4 &modelview,
+ float opacity)
+{
+ QOpenGLExtraFunctions *f = QOpenGLContext::currentContext()->extraFunctions();
+
+ m_program->bind();
+
+ QMatrix4x4 m = proj * modelview;
+ m_program->setUniformValue(m_matrixLoc, m);
+ m_program->setUniformValue(m_opacityLoc, opacity);
+
+ m_buffer->bind();
+
+ if (size != m_prevSize) {
+ m_prevSize = size;
+
+ QPointF p0(size.width() - 1, size.height() - 1);
+ QPointF p1(0, 0);
+ QPointF p2(0, size.height() - 1);
+ QPointF p3(size.width() - 1, 0);
+
+ GLfloat vertices[6 * 4] = {
+ GLfloat(p0.x()), GLfloat(p0.y()), 1, 0,
+ GLfloat(p1.x()), GLfloat(p1.y()), 0, 1,
+ GLfloat(p2.x()), GLfloat(p2.y()), 0, 0,
+
+ GLfloat(p0.x()), GLfloat(p0.y()), 1, 0,
+ GLfloat(p3.x()), GLfloat(p3.y()), 1, 1,
+ GLfloat(p1.x()), GLfloat(p1.y()), 0, 1,
+ };
+
+ m_buffer->write(0, vertices, sizeof(vertices));
+ }
+
+ m_program->enableAttributeArray(0);
+ m_program->enableAttributeArray(1);
+ f->glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
+ f->glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (const void *) (2 * sizeof(GLfloat)));
+
+ f->glBindTexture(GL_TEXTURE_2D, textureId);
+
+ f->glDrawArrays(GL_TRIANGLES, 0, 6);
+
+ f->glBindTexture(GL_TEXTURE_2D, 0);
+ m_buffer->release();
+ m_program->release();
+}
+
+QT_END_NAMESPACE
diff --git a/src/imports/shapes/qquickshapenvprrenderer_p.h b/src/imports/shapes/qquickshapenvprrenderer_p.h
new file mode 100644
index 0000000000..ec7ba498f9
--- /dev/null
+++ b/src/imports/shapes/qquickshapenvprrenderer_p.h
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKSHAPENVPRRENDERER_P_H
+#define QQUICKSHAPENVPRRENDERER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of a number of Qt sources files. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qquickshape_p_p.h"
+#include "qquicknvprfunctions_p.h"
+#include <qsgrendernode.h>
+#include <QColor>
+#include <QVector4D>
+#include <QDebug>
+
+#if QT_CONFIG(opengl)
+
+QT_BEGIN_NAMESPACE
+
+class QQuickShapeNvprRenderNode;
+class QOpenGLFramebufferObject;
+class QOpenGLBuffer;
+class QOpenGLExtraFunctions;
+
+class QQuickShapeNvprRenderer : public QQuickAbstractPathRenderer
+{
+public:
+ enum Dirty {
+ DirtyPath = 0x01,
+ DirtyStyle = 0x02,
+ DirtyFillRule = 0x04,
+ DirtyDash = 0x08,
+ DirtyFillGradient = 0x10,
+ DirtyList = 0x20
+ };
+
+ void beginSync(int totalCount) override;
+ void setPath(int index, const QQuickPath *path) override;
+ void setJSPath(int index, const QQuickShapePathCommands &path) override;
+ void setStrokeColor(int index, const QColor &color) override;
+ void setStrokeWidth(int index, qreal w) override;
+ void setFillColor(int index, const QColor &color) override;
+ void setFillRule(int index, QQuickShapePath::FillRule fillRule) override;
+ void setJoinStyle(int index, QQuickShapePath::JoinStyle joinStyle, int miterLimit) override;
+ void setCapStyle(int index, QQuickShapePath::CapStyle capStyle) override;
+ void setStrokeStyle(int index, QQuickShapePath::StrokeStyle strokeStyle,
+ qreal dashOffset, const QVector<qreal> &dashPattern) override;
+ void setFillGradient(int index, QQuickShapeGradient *gradient) override;
+ void endSync(bool async) override;
+
+ void updateNode() override;
+
+ void setNode(QQuickShapeNvprRenderNode *node);
+
+ struct NvprPath {
+ QVector<GLubyte> cmd;
+ QVector<GLfloat> coord;
+ QByteArray str;
+ };
+
+private:
+ struct ShapePathGuiData {
+ int dirty = 0;
+ NvprPath path;
+ qreal strokeWidth;
+ QColor strokeColor;
+ QColor fillColor;
+ QQuickShapePath::JoinStyle joinStyle;
+ int miterLimit;
+ QQuickShapePath::CapStyle capStyle;
+ QQuickShapePath::FillRule fillRule;
+ bool dashActive;
+ qreal dashOffset;
+ QVector<qreal> dashPattern;
+ bool fillGradientActive;
+ QQuickShapeGradientCache::GradientDesc fillGradient;
+ };
+
+ void convertPath(const QQuickPath *path, ShapePathGuiData *d);
+ void convertJSPath(const QQuickShapePathCommands &path, ShapePathGuiData *d);
+
+ QQuickShapeNvprRenderNode *m_node = nullptr;
+ int m_accDirty = 0;
+
+ QVector<ShapePathGuiData> m_sp;
+};
+
+QDebug operator<<(QDebug debug, const QQuickShapeNvprRenderer::NvprPath &path);
+
+class QQuickNvprMaterialManager
+{
+public:
+ enum Material {
+ MatSolid,
+ MatLinearGradient,
+
+ NMaterials
+ };
+
+ struct MaterialDesc {
+ GLuint ppl = 0;
+ GLuint prg = 0;
+ int uniLoc[4];
+ };
+
+ void create(QQuickNvprFunctions *nvpr);
+ MaterialDesc *activateMaterial(Material m);
+ void releaseResources();
+
+private:
+ QQuickNvprFunctions *m_nvpr = nullptr;
+ MaterialDesc m_materials[NMaterials];
+};
+
+class QQuickNvprBlitter
+{
+public:
+ bool create();
+ void destroy();
+ bool isCreated() const { return m_program != nullptr; }
+ void texturedQuad(GLuint textureId, const QSize &size,
+ const QMatrix4x4 &proj, const QMatrix4x4 &modelview,
+ float opacity);
+
+private:
+ QOpenGLShaderProgram *m_program = nullptr;
+ QOpenGLBuffer *m_buffer = nullptr;
+ int m_matrixLoc = -1;
+ int m_opacityLoc = -1;
+ QSize m_prevSize;
+};
+
+class QQuickShapeNvprRenderNode : public QSGRenderNode
+{
+public:
+ ~QQuickShapeNvprRenderNode();
+
+ void render(const RenderState *state) override;
+ void releaseResources() override;
+ StateFlags changedStates() const override;
+ RenderingFlags flags() const override;
+
+ static bool isSupported();
+
+private:
+ struct ShapePathRenderData {
+ GLuint path = 0;
+ int dirty = 0;
+ QQuickShapeNvprRenderer::NvprPath source;
+ GLfloat strokeWidth;
+ QVector4D strokeColor;
+ QVector4D fillColor;
+ GLenum joinStyle;
+ GLint miterLimit;
+ GLenum capStyle;
+ GLenum fillRule;
+ GLfloat dashOffset;
+ QVector<GLfloat> dashPattern;
+ bool fillGradientActive;
+ QQuickShapeGradientCache::GradientDesc fillGradient;
+ QOpenGLFramebufferObject *fallbackFbo = nullptr;
+ bool fallbackValid = false;
+ QSize fallbackSize;
+ QPointF fallbackTopLeft;
+
+ bool hasFill() const { return !qFuzzyIsNull(fillColor.w()) || fillGradientActive; }
+ bool hasStroke() const { return strokeWidth >= 0.0f && !qFuzzyIsNull(strokeColor.w()); }
+ };
+
+ void updatePath(ShapePathRenderData *d);
+ void renderStroke(ShapePathRenderData *d, int strokeStencilValue, int writeMask);
+ void renderFill(ShapePathRenderData *d);
+ void renderOffscreenFill(ShapePathRenderData *d);
+ void setupStencilForCover(bool stencilClip, int sv);
+
+ static bool nvprInited;
+ static QQuickNvprFunctions nvpr;
+ static QQuickNvprMaterialManager mtlmgr;
+
+ QQuickNvprBlitter m_fallbackBlitter;
+ QOpenGLExtraFunctions *f = nullptr;
+
+ QVector<ShapePathRenderData> m_sp;
+
+ friend class QQuickShapeNvprRenderer;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(opengl)
+
+#endif // QQUICKSHAPENVPRRENDERER_P_H
diff --git a/src/imports/shapes/qquickshapesoftwarerenderer.cpp b/src/imports/shapes/qquickshapesoftwarerenderer.cpp
new file mode 100644
index 0000000000..b3373106af
--- /dev/null
+++ b/src/imports/shapes/qquickshapesoftwarerenderer.cpp
@@ -0,0 +1,277 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickshapesoftwarerenderer_p.h"
+#include <private/qquickpath_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+void QQuickShapeSoftwareRenderer::beginSync(int totalCount)
+{
+ if (m_sp.count() != totalCount) {
+ m_sp.resize(totalCount);
+ m_accDirty |= DirtyList;
+ }
+}
+
+void QQuickShapeSoftwareRenderer::setPath(int index, const QQuickPath *path)
+{
+ ShapePathGuiData &d(m_sp[index]);
+ d.path = path ? path->path() : QPainterPath();
+ d.dirty |= DirtyPath;
+ m_accDirty |= DirtyPath;
+}
+
+void QQuickShapeSoftwareRenderer::setJSPath(int index, const QQuickShapePathCommands &path)
+{
+ ShapePathGuiData &d(m_sp[index]);
+ d.path = path.toPainterPath();
+ d.dirty |= DirtyPath;
+ m_accDirty |= DirtyPath;
+}
+
+void QQuickShapeSoftwareRenderer::setStrokeColor(int index, const QColor &color)
+{
+ ShapePathGuiData &d(m_sp[index]);
+ d.pen.setColor(color);
+ d.dirty |= DirtyPen;
+ m_accDirty |= DirtyPen;
+}
+
+void QQuickShapeSoftwareRenderer::setStrokeWidth(int index, qreal w)
+{
+ ShapePathGuiData &d(m_sp[index]);
+ d.strokeWidth = w;
+ if (w >= 0.0f)
+ d.pen.setWidthF(w);
+ d.dirty |= DirtyPen;
+ m_accDirty |= DirtyPen;
+}
+
+void QQuickShapeSoftwareRenderer::setFillColor(int index, const QColor &color)
+{
+ ShapePathGuiData &d(m_sp[index]);
+ d.fillColor = color;
+ d.brush.setColor(color);
+ d.dirty |= DirtyBrush;
+ m_accDirty |= DirtyBrush;
+}
+
+void QQuickShapeSoftwareRenderer::setFillRule(int index, QQuickShapePath::FillRule fillRule)
+{
+ ShapePathGuiData &d(m_sp[index]);
+ d.fillRule = Qt::FillRule(fillRule);
+ d.dirty |= DirtyFillRule;
+ m_accDirty |= DirtyFillRule;
+}
+
+void QQuickShapeSoftwareRenderer::setJoinStyle(int index, QQuickShapePath::JoinStyle joinStyle, int miterLimit)
+{
+ ShapePathGuiData &d(m_sp[index]);
+ d.pen.setJoinStyle(Qt::PenJoinStyle(joinStyle));
+ d.pen.setMiterLimit(miterLimit);
+ d.dirty |= DirtyPen;
+ m_accDirty |= DirtyPen;
+}
+
+void QQuickShapeSoftwareRenderer::setCapStyle(int index, QQuickShapePath::CapStyle capStyle)
+{
+ ShapePathGuiData &d(m_sp[index]);
+ d.pen.setCapStyle(Qt::PenCapStyle(capStyle));
+ d.dirty |= DirtyPen;
+ m_accDirty |= DirtyPen;
+}
+
+void QQuickShapeSoftwareRenderer::setStrokeStyle(int index, QQuickShapePath::StrokeStyle strokeStyle,
+ qreal dashOffset, const QVector<qreal> &dashPattern)
+{
+ ShapePathGuiData &d(m_sp[index]);
+ switch (strokeStyle) {
+ case QQuickShapePath::SolidLine:
+ d.pen.setStyle(Qt::SolidLine);
+ break;
+ case QQuickShapePath::DashLine:
+ d.pen.setStyle(Qt::CustomDashLine);
+ d.pen.setDashPattern(dashPattern);
+ d.pen.setDashOffset(dashOffset);
+ break;
+ default:
+ break;
+ }
+ d.dirty |= DirtyPen;
+ m_accDirty |= DirtyPen;
+}
+
+void QQuickShapeSoftwareRenderer::setFillGradient(int index, QQuickShapeGradient *gradient)
+{
+ ShapePathGuiData &d(m_sp[index]);
+ if (QQuickShapeLinearGradient *linearGradient = qobject_cast<QQuickShapeLinearGradient *>(gradient)) {
+ QLinearGradient painterGradient(linearGradient->x1(), linearGradient->y1(),
+ linearGradient->x2(), linearGradient->y2());
+ painterGradient.setStops(linearGradient->gradientStops()); // sorted
+ switch (gradient->spread()) {
+ case QQuickShapeGradient::PadSpread:
+ painterGradient.setSpread(QGradient::PadSpread);
+ break;
+ case QQuickShapeGradient::RepeatSpread:
+ painterGradient.setSpread(QGradient::RepeatSpread);
+ break;
+ case QQuickShapeGradient::ReflectSpread:
+ painterGradient.setSpread(QGradient::ReflectSpread);
+ break;
+ default:
+ break;
+ }
+ d.brush = QBrush(painterGradient);
+ } else {
+ d.brush = QBrush(d.fillColor);
+ }
+ d.dirty |= DirtyBrush;
+ m_accDirty |= DirtyBrush;
+}
+
+void QQuickShapeSoftwareRenderer::endSync(bool)
+{
+}
+
+void QQuickShapeSoftwareRenderer::setNode(QQuickShapeSoftwareRenderNode *node)
+{
+ if (m_node != node) {
+ m_node = node;
+ m_accDirty |= DirtyList;
+ }
+}
+
+void QQuickShapeSoftwareRenderer::updateNode()
+{
+ if (!m_accDirty)
+ return;
+
+ const int count = m_sp.count();
+ const bool listChanged = m_accDirty & DirtyList;
+ if (listChanged)
+ m_node->m_sp.resize(count);
+
+ m_node->m_boundingRect = QRectF();
+
+ for (int i = 0; i < count; ++i) {
+ ShapePathGuiData &src(m_sp[i]);
+ QQuickShapeSoftwareRenderNode::ShapePathRenderData &dst(m_node->m_sp[i]);
+
+ if (listChanged || (src.dirty & DirtyPath)) {
+ dst.path = src.path;
+ dst.path.setFillRule(src.fillRule);
+ }
+
+ if (listChanged || (src.dirty & DirtyFillRule))
+ dst.path.setFillRule(src.fillRule);
+
+ if (listChanged || (src.dirty & DirtyPen)) {
+ dst.pen = src.pen;
+ dst.strokeWidth = src.strokeWidth;
+ }
+
+ if (listChanged || (src.dirty & DirtyBrush))
+ dst.brush = src.brush;
+
+ src.dirty = 0;
+
+ QRectF br = dst.path.boundingRect();
+ const float sw = qMax(1.0f, dst.strokeWidth);
+ br.adjust(-sw, -sw, sw, sw);
+ m_node->m_boundingRect |= br;
+ }
+
+ m_node->markDirty(QSGNode::DirtyMaterial);
+ m_accDirty = 0;
+}
+
+QQuickShapeSoftwareRenderNode::QQuickShapeSoftwareRenderNode(QQuickShape *item)
+ : m_item(item)
+{
+}
+
+QQuickShapeSoftwareRenderNode::~QQuickShapeSoftwareRenderNode()
+{
+ releaseResources();
+}
+
+void QQuickShapeSoftwareRenderNode::releaseResources()
+{
+}
+
+void QQuickShapeSoftwareRenderNode::render(const RenderState *state)
+{
+ if (m_sp.isEmpty())
+ return;
+
+ QSGRendererInterface *rif = m_item->window()->rendererInterface();
+ QPainter *p = static_cast<QPainter *>(rif->getResource(m_item->window(), QSGRendererInterface::PainterResource));
+ Q_ASSERT(p);
+
+ const QRegion *clipRegion = state->clipRegion();
+ if (clipRegion && !clipRegion->isEmpty())
+ p->setClipRegion(*clipRegion, Qt::ReplaceClip); // must be done before setTransform
+
+ p->setTransform(matrix()->toTransform());
+ p->setOpacity(inheritedOpacity());
+
+ for (const ShapePathRenderData &d : qAsConst(m_sp)) {
+ p->setPen(d.strokeWidth >= 0.0f && d.pen.color() != Qt::transparent ? d.pen : Qt::NoPen);
+ p->setBrush(d.brush.color() != Qt::transparent ? d.brush : Qt::NoBrush);
+ p->drawPath(d.path);
+ }
+}
+
+QSGRenderNode::StateFlags QQuickShapeSoftwareRenderNode::changedStates() const
+{
+ return 0;
+}
+
+QSGRenderNode::RenderingFlags QQuickShapeSoftwareRenderNode::flags() const
+{
+ return BoundedRectRendering; // avoid fullscreen updates by saying we won't draw outside rect()
+}
+
+QRectF QQuickShapeSoftwareRenderNode::rect() const
+{
+ return m_boundingRect;
+}
+
+QT_END_NAMESPACE
diff --git a/src/imports/shapes/qquickshapesoftwarerenderer_p.h b/src/imports/shapes/qquickshapesoftwarerenderer_p.h
new file mode 100644
index 0000000000..53982ce347
--- /dev/null
+++ b/src/imports/shapes/qquickshapesoftwarerenderer_p.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKSHAPESOFTWARERENDERER_P_H
+#define QQUICKSHAPESOFTWARERENDERER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of a number of Qt sources files. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qquickshape_p_p.h"
+#include <qsgrendernode.h>
+#include <QPen>
+#include <QBrush>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickShapeSoftwareRenderNode;
+
+class QQuickShapeSoftwareRenderer : public QQuickAbstractPathRenderer
+{
+public:
+ enum Dirty {
+ DirtyPath = 0x01,
+ DirtyPen = 0x02,
+ DirtyFillRule = 0x04,
+ DirtyBrush = 0x08,
+ DirtyList = 0x10
+ };
+
+ void beginSync(int totalCount) override;
+ void setPath(int index, const QQuickPath *path) override;
+ void setJSPath(int index, const QQuickShapePathCommands &path) override;
+ void setStrokeColor(int index, const QColor &color) override;
+ void setStrokeWidth(int index, qreal w) override;
+ void setFillColor(int index, const QColor &color) override;
+ void setFillRule(int index, QQuickShapePath::FillRule fillRule) override;
+ void setJoinStyle(int index, QQuickShapePath::JoinStyle joinStyle, int miterLimit) override;
+ void setCapStyle(int index, QQuickShapePath::CapStyle capStyle) override;
+ void setStrokeStyle(int index, QQuickShapePath::StrokeStyle strokeStyle,
+ qreal dashOffset, const QVector<qreal> &dashPattern) override;
+ void setFillGradient(int index, QQuickShapeGradient *gradient) override;
+ void endSync(bool async) override;
+
+ void updateNode() override;
+
+ void setNode(QQuickShapeSoftwareRenderNode *node);
+
+private:
+ QQuickShapeSoftwareRenderNode *m_node = nullptr;
+ int m_accDirty = 0;
+ struct ShapePathGuiData {
+ int dirty = 0;
+ QPainterPath path;
+ QPen pen;
+ float strokeWidth;
+ QColor fillColor;
+ QBrush brush;
+ Qt::FillRule fillRule;
+ };
+ QVector<ShapePathGuiData> m_sp;
+};
+
+class QQuickShapeSoftwareRenderNode : public QSGRenderNode
+{
+public:
+ QQuickShapeSoftwareRenderNode(QQuickShape *item);
+ ~QQuickShapeSoftwareRenderNode();
+
+ void render(const RenderState *state) override;
+ void releaseResources() override;
+ StateFlags changedStates() const override;
+ RenderingFlags flags() const override;
+ QRectF rect() const override;
+
+private:
+ QQuickShape *m_item;
+
+ struct ShapePathRenderData {
+ QPainterPath path;
+ QPen pen;
+ float strokeWidth;
+ QBrush brush;
+ };
+ QVector<ShapePathRenderData> m_sp;
+ QRectF m_boundingRect;
+
+ friend class QQuickShapeSoftwareRenderer;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKSHAPESOFTWARERENDERER_P_H
diff --git a/src/imports/shapes/shapes.pro b/src/imports/shapes/shapes.pro
new file mode 100644
index 0000000000..80e6a22142
--- /dev/null
+++ b/src/imports/shapes/shapes.pro
@@ -0,0 +1,31 @@
+CXX_MODULE = qml
+TARGET = qmlshapesplugin
+TARGETPATH = QtQuick/Shapes
+IMPORT_VERSION = 1.0
+
+QT = core gui qml quick quick-private
+
+HEADERS += \
+ qquickshape_p.h \
+ qquickshape_p_p.h \
+ qquickshapegenericrenderer_p.h \
+ qquickshapesoftwarerenderer_p.h
+
+SOURCES += \
+ plugin.cpp \
+ qquickshape.cpp \
+ qquickshapegenericrenderer.cpp \
+ qquickshapesoftwarerenderer.cpp
+
+qtConfig(opengl) {
+ HEADERS += \
+ qquicknvprfunctions_p.h \
+ qquicknvprfunctions_p_p.h \
+ qquickshapenvprrenderer_p.h
+
+ SOURCES += \
+ qquicknvprfunctions.cpp \
+ qquickshapenvprrenderer.cpp
+}
+
+load(qml_plugin)
diff --git a/src/imports/testlib/TestCase.qml b/src/imports/testlib/TestCase.qml
index 82211b5192..7ff51bb6d6 100644
--- a/src/imports/testlib/TestCase.qml
+++ b/src/imports/testlib/TestCase.qml
@@ -38,6 +38,7 @@
****************************************************************************/
import QtQuick 2.0
+import QtQuick.Window 2.0 // used for qtest_verifyItem
import QtTest 1.1
import "testlogger.js" as TestLogger
import Qt.test.qtestroot 1.0
@@ -443,6 +444,9 @@ Item {
or \c{QVERIFY2(condition, message)} in C++.
*/
function verify(cond, msg) {
+ if (arguments.length > 2)
+ qtest_fail("More than two arguments given to verify(). Did you mean tryVerify() or tryCompare()?", 1)
+
if (msg === undefined)
msg = "";
if (!qtest_results.verify(cond, msg, util.callerFile(), util.callerLine()))
@@ -837,7 +841,14 @@ Item {
Returns a snapshot image object of the given \a item.
- The returned image object has the following methods:
+ The returned image object has the following properties:
+ \list
+ \li width Returns the width of the underlying image (since 5.10)
+ \li height Returns the height of the underlying image (since 5.10)
+ \li size Returns the size of the underlying image (since 5.10)
+ \endlist
+
+ Additionally, the returned image object has the following methods:
\list
\li red(x, y) Returns the red channel value of the pixel at \a x, \a y position
\li green(x, y) Returns the green channel value of the pixel at \a x, \a y position
@@ -858,6 +869,21 @@ Item {
var newImage = grabImage(rect);
verify(!newImage.equals(image));
\endcode
+ \li save(path) Saves the image to the given \a path. If the image cannot
+ be saved, an exception will be thrown. (since 5.10)
+
+ This can be useful to perform postmortem analysis on failing tests, for
+ example:
+
+ \code
+ var image = grabImage(rect);
+ try {
+ compare(image.width, 100);
+ } catch (ex) {
+ image.save("debug.png");
+ throw ex;
+ }
+ \endcode
\endlist
@@ -1089,8 +1115,8 @@ Item {
function waitForRendering(item, timeout) {
if (timeout === undefined)
timeout = 5000
- if (!item)
- qtest_fail("No item given to waitForRendering", 1)
+ if (!qtest_verifyItem(item, "waitForRendering"))
+ return
return qtest_results.waitForRendering(item, timeout)
}
@@ -1202,8 +1228,8 @@ Item {
\sa mouseRelease(), mouseClick(), mouseDoubleClick(), mouseDoubleClickSequence(), mouseMove(), mouseDrag(), mouseWheel()
*/
function mousePress(item, x, y, button, modifiers, delay) {
- if (!item)
- qtest_fail("No item given to mousePress", 1)
+ if (!qtest_verifyItem(item, "mousePress"))
+ return
if (button === undefined)
button = Qt.LeftButton
@@ -1236,8 +1262,8 @@ Item {
\sa mousePress(), mouseClick(), mouseDoubleClick(), mouseDoubleClickSequence(), mouseMove(), mouseDrag(), mouseWheel()
*/
function mouseRelease(item, x, y, button, modifiers, delay) {
- if (!item)
- qtest_fail("No item given to mouseRelease", 1)
+ if (!qtest_verifyItem(item, "mouseRelease"))
+ return
if (button === undefined)
button = Qt.LeftButton
@@ -1272,8 +1298,8 @@ Item {
\sa mousePress(), mouseClick(), mouseDoubleClick(), mouseDoubleClickSequence(), mouseMove(), mouseRelease(), mouseWheel()
*/
function mouseDrag(item, x, y, dx, dy, button, modifiers, delay) {
- if (!item)
- qtest_fail("No item given to mouseDrag", 1)
+ if (!qtest_verifyItem(item, "mouseDrag"))
+ return
if (item.x === undefined || item.y === undefined)
return
@@ -1323,8 +1349,8 @@ Item {
\sa mousePress(), mouseRelease(), mouseDoubleClick(), mouseDoubleClickSequence(), mouseMove(), mouseDrag(), mouseWheel()
*/
function mouseClick(item, x, y, button, modifiers, delay) {
- if (!item)
- qtest_fail("No item given to mouseClick", 1)
+ if (!qtest_verifyItem(item, "mouseClick"))
+ return
if (button === undefined)
button = Qt.LeftButton
@@ -1357,8 +1383,8 @@ Item {
\sa mouseDoubleClickSequence(), mousePress(), mouseRelease(), mouseClick(), mouseMove(), mouseDrag(), mouseWheel()
*/
function mouseDoubleClick(item, x, y, button, modifiers, delay) {
- if (!item)
- qtest_fail("No item given to mouseDoubleClick", 1)
+ if (!qtest_verifyItem(item, "mouseDoubleClick"))
+ return
if (button === undefined)
button = Qt.LeftButton
@@ -1398,8 +1424,8 @@ Item {
\sa mouseDoubleClick(), mousePress(), mouseRelease(), mouseClick(), mouseMove(), mouseDrag(), mouseWheel()
*/
function mouseDoubleClickSequence(item, x, y, button, modifiers, delay) {
- if (!item)
- qtest_fail("No item given to mouseDoubleClickSequence", 1)
+ if (!qtest_verifyItem(item, "mouseDoubleClickSequence"))
+ return
if (button === undefined)
button = Qt.LeftButton
@@ -1430,8 +1456,8 @@ Item {
\sa mousePress(), mouseRelease(), mouseClick(), mouseDoubleClick(), mouseDoubleClickSequence(), mouseDrag(), mouseWheel()
*/
function mouseMove(item, x, y, delay, buttons) {
- if (!item)
- qtest_fail("No item given to mouseMove", 1)
+ if (!qtest_verifyItem(item, "mouseMove"))
+ return
if (delay == undefined)
delay = -1
@@ -1458,8 +1484,8 @@ Item {
\sa mousePress(), mouseClick(), mouseDoubleClick(), mouseDoubleClickSequence(), mouseMove(), mouseRelease(), mouseDrag(), QWheelEvent::angleDelta()
*/
function mouseWheel(item, x, y, xDelta, yDelta, buttons, modifiers, delay) {
- if (!item)
- qtest_fail("No item given to mouseWheel", 1)
+ if (!qtest_verifyItem(item, "mouseWheel"))
+ return
if (delay == undefined)
delay = -1
@@ -1519,8 +1545,8 @@ Item {
*/
function touchEvent(item) {
- if (!item)
- qtest_fail("No item given to touchEvent", 1)
+ if (!qtest_verifyItem(item, "touchEvent"))
+ return
return {
_defaultItem: item,
@@ -1629,6 +1655,23 @@ Item {
function cleanup() {}
/*! \internal */
+ function qtest_verifyItem(item, method) {
+ try {
+ if (!(item instanceof Item) &&
+ !(item instanceof Window)) {
+ // it's a QObject, but not a type
+ qtest_fail("TypeError: %1 requires an Item or Window type".arg(method), 2);
+ return false;
+ }
+ } catch (e) { // it's not a QObject
+ qtest_fail("TypeError: %1 requires an Item or Window type".arg(method), 3);
+ return false;
+ }
+
+ return true;
+ }
+
+ /*! \internal */
function qtest_runInternal(prop, arg) {
try {
qtest_testCaseResult = testCase[prop](arg)
diff --git a/src/particles/qquickimageparticle.cpp b/src/particles/qquickimageparticle.cpp
index d817e24866..1b3d2eed6b 100644
--- a/src/particles/qquickimageparticle.cpp
+++ b/src/particles/qquickimageparticle.cpp
@@ -118,15 +118,15 @@ public:
Q_ASSERT(!m_fragment_code.isNull());
}
- const char *vertexShader() const { return m_vertex_code.constData(); }
- const char *fragmentShader() const { return m_fragment_code.constData(); }
+ const char *vertexShader() const override { return m_vertex_code.constData(); }
+ const char *fragmentShader() const override { return m_fragment_code.constData(); }
- QList<QByteArray> attributes() const {
+ QList<QByteArray> attributes() const override {
return QList<QByteArray>() << "vPosTex" << "vData" << "vVec"
<< "vColor" << "vDeformVec" << "vRotation";
};
- void initialize() {
+ void initialize() override {
QSGSimpleMaterialShader<TabledMaterialData>::initialize();
program()->bind();
program()->setUniformValue("_qt_texture", 0);
@@ -138,7 +138,7 @@ public:
m_opacitytable_id = program()->uniformLocation("opacitytable");
}
- void updateState(const TabledMaterialData* d, const TabledMaterialData*) {
+ void updateState(const TabledMaterialData* d, const TabledMaterialData*) override {
glFuncs->glActiveTexture(GL_TEXTURE1);
d->colorTable->bind();
@@ -192,15 +192,15 @@ public:
Q_ASSERT(!m_fragment_code.isNull());
}
- const char *vertexShader() const { return m_vertex_code.constData(); }
- const char *fragmentShader() const { return m_fragment_code.constData(); }
+ const char *vertexShader() const override { return m_vertex_code.constData(); }
+ const char *fragmentShader() const override { return m_fragment_code.constData(); }
- QList<QByteArray> attributes() const {
+ QList<QByteArray> attributes() const override {
return QList<QByteArray>() << "vPosTex" << "vData" << "vVec"
<< "vColor" << "vDeformVec" << "vRotation";
};
- void initialize() {
+ void initialize() override {
QSGSimpleMaterialShader<DeformableMaterialData>::initialize();
program()->bind();
program()->setUniformValue("_qt_texture", 0);
@@ -209,7 +209,7 @@ public:
m_entry_id = program()->uniformLocation("entry");
}
- void updateState(const DeformableMaterialData* d, const DeformableMaterialData*) {
+ void updateState(const DeformableMaterialData* d, const DeformableMaterialData*) override {
d->texture->bind();
program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
@@ -259,15 +259,15 @@ public:
Q_ASSERT(!m_fragment_code.isNull());
}
- const char *vertexShader() const { return m_vertex_code.constData(); }
- const char *fragmentShader() const { return m_fragment_code.constData(); }
+ const char *vertexShader() const override { return m_vertex_code.constData(); }
+ const char *fragmentShader() const override { return m_fragment_code.constData(); }
- QList<QByteArray> attributes() const {
+ QList<QByteArray> attributes() const override {
return QList<QByteArray>() << "vPosTex" << "vData" << "vVec"
<< "vColor" << "vDeformVec" << "vRotation" << "vAnimData" << "vAnimPos";
}
- void initialize() {
+ void initialize() override {
QSGSimpleMaterialShader<SpriteMaterialData>::initialize();
program()->bind();
program()->setUniformValue("_qt_texture", 0);
@@ -280,7 +280,7 @@ public:
m_opacitytable_id = program()->uniformLocation("opacitytable");
}
- void updateState(const SpriteMaterialData* d, const SpriteMaterialData*) {
+ void updateState(const SpriteMaterialData* d, const SpriteMaterialData*) override {
glFuncs->glActiveTexture(GL_TEXTURE1);
d->colorTable->bind();
@@ -333,10 +333,10 @@ public:
Q_ASSERT(!m_fragment_code.isNull());
}
- const char *vertexShader() const { return m_vertex_code.constData(); }
- const char *fragmentShader() const { return m_fragment_code.constData(); }
+ const char *vertexShader() const override { return m_vertex_code.constData(); }
+ const char *fragmentShader() const override { return m_fragment_code.constData(); }
- void activate() {
+ void activate() override {
QSGSimpleMaterialShader<ColoredMaterialData>::activate();
#if !defined(QT_OPENGL_ES_2) && !defined(Q_OS_WIN)
glEnable(GL_POINT_SPRITE);
@@ -344,7 +344,7 @@ public:
#endif
}
- void deactivate() {
+ void deactivate() override {
QSGSimpleMaterialShader<ColoredMaterialData>::deactivate();
#if !defined(QT_OPENGL_ES_2) && !defined(Q_OS_WIN)
glDisable(GL_POINT_SPRITE);
@@ -352,11 +352,11 @@ public:
#endif
}
- QList<QByteArray> attributes() const {
+ QList<QByteArray> attributes() const override {
return QList<QByteArray>() << "vPos" << "vData" << "vVec" << "vColor";
}
- void initialize() {
+ void initialize() override {
QSGSimpleMaterialShader<ColoredMaterialData>::initialize();
program()->bind();
program()->setUniformValue("_qt_texture", 0);
@@ -365,7 +365,7 @@ public:
m_entry_id = program()->uniformLocation("entry");
}
- void updateState(const ColoredMaterialData* d, const ColoredMaterialData*) {
+ void updateState(const ColoredMaterialData* d, const ColoredMaterialData*) override {
d->texture->bind();
program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
@@ -407,10 +407,10 @@ public:
Q_ASSERT(!m_fragment_code.isNull());
}
- const char *vertexShader() const { return m_vertex_code.constData(); }
- const char *fragmentShader() const { return m_fragment_code.constData(); }
+ const char *vertexShader() const override { return m_vertex_code.constData(); }
+ const char *fragmentShader() const override { return m_fragment_code.constData(); }
- void activate() {
+ void activate() override {
QSGSimpleMaterialShader<SimpleMaterialData>::activate();
#if !defined(QT_OPENGL_ES_2) && !defined(Q_OS_WIN)
glEnable(GL_POINT_SPRITE);
@@ -418,7 +418,7 @@ public:
#endif
}
- void deactivate() {
+ void deactivate() override {
QSGSimpleMaterialShader<SimpleMaterialData>::deactivate();
#if !defined(QT_OPENGL_ES_2) && !defined(Q_OS_WIN)
glDisable(GL_POINT_SPRITE);
@@ -426,11 +426,11 @@ public:
#endif
}
- QList<QByteArray> attributes() const {
+ QList<QByteArray> attributes() const override {
return QList<QByteArray>() << "vPos" << "vData" << "vVec";
}
- void initialize() {
+ void initialize() override {
QSGSimpleMaterialShader<SimpleMaterialData>::initialize();
program()->bind();
program()->setUniformValue("_qt_texture", 0);
@@ -439,7 +439,7 @@ public:
m_entry_id = program()->uniformLocation("entry");
}
- void updateState(const SimpleMaterialData* d, const SimpleMaterialData*) {
+ void updateState(const SimpleMaterialData* d, const SimpleMaterialData*) override {
d->texture->bind();
program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
index 755235a3a7..e89b7a63d4 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
@@ -55,11 +55,11 @@
QT_BEGIN_NAMESPACE
-QV4::CallContext *QV4DataCollector::findContext(int frame)
+QV4::SimpleCallContext *QV4DataCollector::findContext(int frame)
{
QV4::ExecutionContext *ctx = engine()->currentContext;
while (ctx) {
- QV4::CallContext *cCtxt = ctx->asCallContext();
+ QV4::SimpleCallContext *cCtxt = ctx->asSimpleCallContext();
if (cCtxt && cCtxt->d()->v4Function) {
if (frame < 1)
return cCtxt;
@@ -71,7 +71,7 @@ QV4::CallContext *QV4DataCollector::findContext(int frame)
return 0;
}
-QV4::Heap::CallContext *QV4DataCollector::findScope(QV4::ExecutionContext *ctxt, int scope)
+QV4::Heap::SimpleCallContext *QV4DataCollector::findScope(QV4::ExecutionContext *ctxt, int scope)
{
if (!ctxt)
return 0;
@@ -81,7 +81,7 @@ QV4::Heap::CallContext *QV4DataCollector::findScope(QV4::ExecutionContext *ctxt,
for (; scope > 0 && ctx; --scope)
ctx = ctx->d()->outer;
- return (ctx && ctx->d()) ? ctx->asCallContext()->d() : 0;
+ return (ctx && ctx->d()) ? ctx->asSimpleCallContext()->d() : 0;
}
QVector<QV4::Heap::ExecutionContext::ContextType> QV4DataCollector::getScopeTypes(int frame)
@@ -89,7 +89,7 @@ QVector<QV4::Heap::ExecutionContext::ContextType> QV4DataCollector::getScopeType
QVector<QV4::Heap::ExecutionContext::ContextType> types;
QV4::Scope scope(engine());
- QV4::CallContext *sctxt = findContext(frame);
+ QV4::SimpleCallContext *sctxt = findContext(frame);
if (!sctxt || sctxt->d()->type < QV4::Heap::ExecutionContext::Type_QmlContext)
return types;
@@ -297,9 +297,11 @@ bool QV4DataCollector::collectScope(QJsonObject *dict, int frameNr, int scopeNr)
QV4::ScopedObject scopeObject(scope, engine()->newObject());
Q_ASSERT(names.size() == collectedRefs.size());
- for (int i = 0, ei = collectedRefs.size(); i != ei; ++i)
- scopeObject->put(engine(), names.at(i),
- QV4::Value::fromReturnedValue(getValue(collectedRefs.at(i))));
+ QV4::ScopedString propName(scope);
+ for (int i = 0, ei = collectedRefs.size(); i != ei; ++i) {
+ propName = engine()->newString(names.at(i));
+ scopeObject->put(propName, QV4::Value::fromReturnedValue(getValue(collectedRefs.at(i))));
+ }
Ref scopeObjectRef = addRef(scopeObject);
if (m_redundantRefs) {
@@ -338,7 +340,7 @@ QJsonObject QV4DataCollector::buildFrame(const QV4::StackFrame &stackFrame, int
QV4::Scope scope(engine());
QV4::ScopedContext ctxt(scope, findContext(frameNr));
while (ctxt) {
- if (QV4::CallContext *cCtxt = ctxt->asCallContext()) {
+ if (QV4::SimpleCallContext *cCtxt = ctxt->asSimpleCallContext()) {
if (cCtxt->d()->activation)
break;
}
@@ -346,7 +348,7 @@ QJsonObject QV4DataCollector::buildFrame(const QV4::StackFrame &stackFrame, int
}
if (ctxt) {
- QV4::ScopedValue o(scope, ctxt->asCallContext()->d()->activation);
+ QV4::ScopedValue o(scope, ctxt->asSimpleCallContext()->d()->activation);
frame[QLatin1String("receiver")] = toRef(collect(o));
}
@@ -398,8 +400,8 @@ QV4DataCollector::Ref QV4DataCollector::addRef(QV4::Value value, bool deduplicat
{
class ExceptionStateSaver
{
- quint32 *hasExceptionLoc;
- quint32 hadException;
+ quint8 *hasExceptionLoc;
+ quint8 hadException;
public:
ExceptionStateSaver(QV4::ExecutionEngine *engine)
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
index 2c2514a1b3..de12e8d527 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
@@ -58,11 +58,11 @@ public:
typedef uint Ref;
typedef QVector<uint> Refs;
- static QV4::Heap::CallContext *findScope(QV4::ExecutionContext *ctxt, int scope);
+ static QV4::Heap::SimpleCallContext *findScope(QV4::ExecutionContext *ctxt, int scope);
static int encodeScopeType(QV4::Heap::ExecutionContext::ContextType scopeType);
QVector<QV4::Heap::ExecutionContext::ContextType> getScopeTypes(int frame);
- QV4::CallContext *findContext(int frame);
+ QV4::SimpleCallContext *findContext(int frame);
QV4DataCollector(QV4::ExecutionEngine *engine);
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
index a624cf22a4..107ec60943 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
@@ -90,12 +90,15 @@ void JavaScriptJob::run()
QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(qmlRootContext);
QV4::ScopedObject withContext(scope, engine->newObject());
+ QV4::ScopedString k(scope);
+ QV4::ScopedValue v(scope);
for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) {
QObject *object = ctxtPriv->instances.at(ii);
if (QQmlContext *context = qmlContext(object)) {
if (QQmlContextData *cdata = QQmlContextData::get(context)) {
- QV4::ScopedValue v(scope, QV4::QObjectWrapper::wrap(engine, object));
- withContext->put(engine, cdata->findObjectId(object), v);
+ v = QV4::QObjectWrapper::wrap(engine, object);
+ k = engine->newString(cdata->findObjectId(object));
+ withContext->put(k, v);
}
}
}
diff --git a/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp
index 6152853917..97e4b4e3e4 100644
--- a/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp
+++ b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp
@@ -57,15 +57,15 @@ public:
QLocalClientConnection();
~QLocalClientConnection();
- void setServer(QQmlDebugServer *server);
- bool setPortRange(int portFrom, int portTo, bool block, const QString &hostaddress);
- bool setFileName(const QString &filename, bool block);
+ void setServer(QQmlDebugServer *server) override;
+ bool setPortRange(int portFrom, int portTo, bool block, const QString &hostaddress) override;
+ bool setFileName(const QString &filename, bool block) override;
- bool isConnected() const;
- void disconnect();
+ bool isConnected() const override;
+ void disconnect() override;
- void waitForConnection();
- void flush();
+ void waitForConnection() override;
+ void flush() override;
private:
void connectionEstablished();
diff --git a/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp b/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp
index 2015118d95..d536fd51ed 100644
--- a/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp
@@ -481,17 +481,20 @@ void NativeDebugger::handleVariables(QJsonObject *response, const QJsonObject &a
QJsonArray output;
QV4::Scope scope(engine);
- if (QV4::CallContext *callContext = executionContext->asCallContext()) {
+ if (QV4::SimpleCallContext *callContext = executionContext->asSimpleCallContext()) {
QV4::Value thisObject = callContext->thisObject();
collector.collect(&output, QString(), QStringLiteral("this"), thisObject);
QV4::Identifier *const *variables = callContext->variables();
QV4::Identifier *const *formals = callContext->formals();
- for (unsigned i = 0, ei = callContext->variableCount(); i != ei; ++i) {
- QString qName;
- if (QV4::Identifier *name = variables[i])
- qName = name->string;
- QV4::Value val = callContext->d()->locals[i];
- collector.collect(&output, QString(), qName, val);
+ if (callContext->d()->type == QV4::Heap::ExecutionContext::Type_CallContext) {
+ QV4::CallContext *ctx = static_cast<QV4::CallContext *>(callContext);
+ for (unsigned i = 0, ei = ctx->variableCount(); i != ei; ++i) {
+ QString qName;
+ if (QV4::Identifier *name = variables[i])
+ qName = name->string;
+ QV4::Value val = ctx->d()->locals[i];
+ collector.collect(&output, QString(), qName, val);
+ }
}
for (unsigned i = 0, ei = callContext->formalCount(); i != ei; ++i) {
QString qName;
diff --git a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
index 9759ad9783..0a7421842a 100644
--- a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
+++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
@@ -114,7 +114,7 @@ public:
return m_pluginName;
}
- void run();
+ void run() override;
private:
QQmlDebugServerImpl *m_server;
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
index b305c3f535..af4f5292ba 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
+++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
@@ -55,15 +55,15 @@ public:
QTcpServerConnection();
~QTcpServerConnection();
- void setServer(QQmlDebugServer *server);
- bool setPortRange(int portFrom, int portTo, bool block, const QString &hostaddress);
- bool setFileName(const QString &fileName, bool block);
+ void setServer(QQmlDebugServer *server) override;
+ bool setPortRange(int portFrom, int portTo, bool block, const QString &hostaddress) override;
+ bool setFileName(const QString &fileName, bool block) override;
- bool isConnected() const;
- void disconnect();
+ bool isConnected() const override;
+ void disconnect() override;
- void waitForConnection();
- void flush();
+ void waitForConnection() override;
+ void flush() override;
private:
void newConnection();
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12layer_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12layer_p.h
index f1ab580a84..f828843227 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12layer_p.h
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12layer_p.h
@@ -86,6 +86,7 @@ public:
void setDevicePixelRatio(qreal ratio) override;
void setMirrorHorizontal(bool mirror) override;
void setMirrorVertical(bool mirror) override;
+ void setSamples(int) override { }
public Q_SLOTS:
void markDirtyTexture() override;
diff --git a/src/plugins/scenegraph/openvg/qsgopenvglayer.h b/src/plugins/scenegraph/openvg/qsgopenvglayer.h
index 2af0bfb40f..8deedc3347 100644
--- a/src/plugins/scenegraph/openvg/qsgopenvglayer.h
+++ b/src/plugins/scenegraph/openvg/qsgopenvglayer.h
@@ -83,6 +83,7 @@ public:
void setDevicePixelRatio(qreal ratio) override;
void setMirrorHorizontal(bool mirror) override;
void setMirrorVertical(bool mirror) override;
+ void setSamples(int) override { }
public slots:
void markDirtyTexture() override;
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 03a71768d8..e05c38e14a 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -86,6 +86,7 @@ void Object::init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, cons
flags = QV4::CompiledData::Object::NoFlag;
properties = pool->New<PoolList<Property> >();
aliases = pool->New<PoolList<Alias> >();
+ qmlEnums = pool->New<PoolList<Enum>>();
qmlSignals = pool->New<PoolList<Signal> >();
bindings = pool->New<PoolList<Binding> >();
functions = pool->New<PoolList<Function> >();
@@ -118,6 +119,21 @@ QString Object::sanityCheckFunctionNames(const QSet<QString> &illegalNames, QQml
return QString(); // no error
}
+QString Object::appendEnum(Enum *enumeration)
+{
+ Object *target = declarationsOverride;
+ if (!target)
+ target = this;
+
+ for (Enum *e = qmlEnums->first; e; e = e->next) {
+ if (e->nameIndex == enumeration->nameIndex)
+ return tr("Duplicate scoped enum name");
+ }
+
+ target->qmlEnums->append(enumeration);
+ return QString(); // no error
+}
+
QString Object::appendSignal(Signal *signal)
{
Object *target = declarationsOverride;
@@ -709,6 +725,48 @@ static QStringList astNodeToStringList(QQmlJS::AST::Node *node)
return QStringList();
}
+bool IRBuilder::visit(QQmlJS::AST::UiEnumDeclaration *node)
+{
+ Enum *enumeration = New<Enum>();
+ QString enumName = node->name.toString();
+ enumeration->nameIndex = registerString(enumName);
+
+ if (enumName.at(0).isLower())
+ COMPILE_EXCEPTION(node->enumToken, tr("Scoped enum names must begin with an upper case letter"));
+
+ enumeration->location.line = node->enumToken.startLine;
+ enumeration->location.column = node->enumToken.startColumn;
+
+ enumeration->enumValues = New<PoolList<EnumValue>>();
+
+ QQmlJS::AST::UiEnumMemberList *e = node->members;
+ int i = -1;
+ while (e) {
+ EnumValue *enumValue = New<EnumValue>();
+ QString member = e->member.toString();
+ enumValue->nameIndex = registerString(member);
+ enumValue->value = ++i;
+
+ if (member.at(0).isLower())
+ COMPILE_EXCEPTION(e->memberToken, tr("Enum names must begin with an upper case letter"));
+
+ enumValue->location.line = e->memberToken.startLine;
+ enumValue->location.column = e->memberToken.startColumn;
+ enumeration->enumValues->append(enumValue);
+
+ e = e->next;
+ }
+
+ QString error = _object->appendEnum(enumeration);
+ if (!error.isEmpty()) {
+ recordError(node->enumToken, error);
+ return false;
+ }
+
+ return false;
+}
+
+
bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node)
{
static const struct TypeNameToType {
@@ -1375,13 +1433,19 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output, const QV4:
int objectsSize = 0;
for (Object *o : qAsConst(output.objects)) {
objectOffsets.insert(o, unitSize + importSize + objectOffsetTableSize + objectsSize);
- objectsSize += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->aliasCount(), o->signalCount(), o->bindingCount(), o->namedObjectsInComponent.count);
+ objectsSize += QV4::CompiledData::Object::calculateSizeExcludingSignalsAndEnums(o->functionCount(), o->propertyCount(), o->aliasCount(), o->enumCount(), o->signalCount(), o->bindingCount(), o->namedObjectsInComponent.count);
int signalTableSize = 0;
for (const Signal *s = o->firstSignal(); s; s = s->next)
signalTableSize += QV4::CompiledData::Signal::calculateSize(s->parameters->count);
objectsSize += signalTableSize;
+
+ int enumTableSize = 0;
+ for (const Enum *e = o->firstEnum(); e; e = e->next)
+ enumTableSize += QV4::CompiledData::Enum::calculateSize(e->enumValues->count);
+
+ objectsSize += enumTableSize;
}
const int totalSize = unitSize + importSize + objectOffsetTableSize + objectsSize + output.jsGenerator.stringTable.sizeOfTableAndData();
@@ -1425,7 +1489,7 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output, const QV4:
}
// write objects
- QV4::CompiledData::LEUInt32 *objectTable = reinterpret_cast<QV4::CompiledData::LEUInt32*>(data + qmlUnit->offsetToObjects);
+ quint32_le *objectTable = reinterpret_cast<quint32_le*>(data + qmlUnit->offsetToObjects);
char *objectPtr = data + qmlUnit->offsetToObjects + objectOffsetTableSize;
for (int i = 0; i < output.objects.count(); ++i) {
const Object *o = output.objects.at(i);
@@ -1455,6 +1519,10 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output, const QV4:
objectToWrite->offsetToAliases = nextOffset;
nextOffset += objectToWrite->nAliases * sizeof(QV4::CompiledData::Alias);
+ objectToWrite->nEnums = o->enumCount();
+ objectToWrite->offsetToEnums = nextOffset;
+ nextOffset += objectToWrite->nEnums * sizeof(quint32);
+
objectToWrite->nSignals = o->signalCount();
objectToWrite->offsetToSignals = nextOffset;
nextOffset += objectToWrite->nSignals * sizeof(quint32);
@@ -1467,7 +1535,7 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output, const QV4:
objectToWrite->offsetToNamedObjectsInComponent = nextOffset;
nextOffset += objectToWrite->nNamedObjectsInComponent * sizeof(quint32);
- QV4::CompiledData::LEUInt32 *functionsTable = reinterpret_cast<QV4::CompiledData::LEUInt32*>(objectPtr + objectToWrite->offsetToFunctions);
+ quint32_le *functionsTable = reinterpret_cast<quint32_le *>(objectPtr + objectToWrite->offsetToFunctions);
for (const Function *f = o->firstFunction(); f; f = f->next)
*functionsTable++ = o->runtimeFunctionIndices.at(f->index);
@@ -1493,7 +1561,7 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output, const QV4:
bindingPtr = writeBindings(bindingPtr, o, &QV4::CompiledData::Binding::isValueBindingToAlias);
Q_ASSERT((bindingPtr - objectToWrite->offsetToBindings - objectPtr) / sizeof(QV4::CompiledData::Binding) == unsigned(o->bindingCount()));
- QV4::CompiledData::LEUInt32 *signalOffsetTable = reinterpret_cast<QV4::CompiledData::LEUInt32*>(objectPtr + objectToWrite->offsetToSignals);
+ quint32_le *signalOffsetTable = reinterpret_cast<quint32_le *>(objectPtr + objectToWrite->offsetToSignals);
quint32 signalTableSize = 0;
char *signalPtr = objectPtr + nextOffset;
for (const Signal *s = o->firstSignal(); s; s = s->next) {
@@ -1512,14 +1580,36 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output, const QV4:
signalTableSize += size;
signalPtr += size;
}
+ nextOffset += signalTableSize;
+
+ quint32_le *enumOffsetTable = reinterpret_cast<quint32_le*>(objectPtr + objectToWrite->offsetToEnums);
+ quint32 enumTableSize = 0;
+ char *enumPtr = objectPtr + nextOffset;
+ for (const Enum *e = o->firstEnum(); e; e = e->next) {
+ *enumOffsetTable++ = enumPtr - objectPtr;
+ QV4::CompiledData::Enum *enumToWrite = reinterpret_cast<QV4::CompiledData::Enum*>(enumPtr);
+
+ enumToWrite->nameIndex = e->nameIndex;
+ enumToWrite->location = e->location;
+ enumToWrite->nEnumValues = e->enumValues->count;
+
+ QV4::CompiledData::EnumValue *enumValueToWrite = reinterpret_cast<QV4::CompiledData::EnumValue*>(enumPtr + sizeof(*enumToWrite));
+ for (EnumValue *enumValue = e->enumValues->first; enumValue; enumValue = enumValue->next, ++enumValueToWrite)
+ *enumValueToWrite = *enumValue;
+
+ int size = QV4::CompiledData::Enum::calculateSize(e->enumValues->count);
+ enumTableSize += size;
+ enumPtr += size;
+ }
- QV4::CompiledData::LEUInt32 *namedObjectInComponentPtr = reinterpret_cast<QV4::CompiledData::LEUInt32*>(objectPtr + objectToWrite->offsetToNamedObjectsInComponent);
+ quint32_le *namedObjectInComponentPtr = reinterpret_cast<quint32_le *>(objectPtr + objectToWrite->offsetToNamedObjectsInComponent);
for (int i = 0; i < o->namedObjectsInComponent.count; ++i) {
*namedObjectInComponentPtr++ = o->namedObjectsInComponent.at(i);
}
- objectPtr += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->aliasCount(), o->signalCount(), o->bindingCount(), o->namedObjectsInComponent.count);
+ objectPtr += QV4::CompiledData::Object::calculateSizeExcludingSignalsAndEnums(o->functionCount(), o->propertyCount(), o->aliasCount(), o->enumCount(), o->signalCount(), o->bindingCount(), o->namedObjectsInComponent.count);
objectPtr += signalTableSize;
+ objectPtr += enumTableSize;
}
// enable flag if we encountered pragma Singleton
@@ -1604,7 +1694,7 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil
scan.leaveEnvironment();
scan.leaveEnvironment();
- _env = 0;
+ _variableEnvironment = 0;
_function = _module->functions.at(defineFunction(QStringLiteral("context scope"), qmlRoot, 0, 0));
for (int i = 0; i < functions.count(); ++i) {
@@ -1687,6 +1777,7 @@ enum MetaObjectResolverFlags {
};
static void initMetaObjectResolver(QV4::IR::MemberExpressionResolver *resolver, QQmlPropertyCache *metaObject);
+static void initScopedEnumResolver(QV4::IR::MemberExpressionResolver *resolver, QQmlType *qmlType, int index);
static QV4::IR::DiscoveredType resolveQmlType(QQmlEnginePrivate *qmlEngine,
const QV4::IR::MemberExpressionResolver *resolver,
@@ -1702,6 +1793,14 @@ static QV4::IR::DiscoveredType resolveQmlType(QQmlEnginePrivate *qmlEngine,
if (ok) {
member->setEnumValue(value);
return QV4::IR::SInt32Type;
+ } else {
+ int index = type->scopedEnumIndex(qmlEngine, *member->name, &ok);
+ if (ok) {
+ auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>();
+ newResolver->owner = resolver->owner;
+ initScopedEnumResolver(newResolver, type, index);
+ return QV4::IR::DiscoveredType(newResolver);
+ }
}
}
@@ -1885,6 +1984,34 @@ static void initMetaObjectResolver(QV4::IR::MemberExpressionResolver *resolver,
resolver->flags = 0;
}
+static QV4::IR::DiscoveredType resolveScopedEnum(QQmlEnginePrivate *qmlEngine,
+ const QV4::IR::MemberExpressionResolver *resolver,
+ QV4::IR::Member *member)
+{
+ if (!member->name->constData()->isUpper())
+ return QV4::IR::VarType;
+
+ QQmlType *type = static_cast<QQmlType*>(resolver->data);
+ int index = resolver->flags;
+
+ bool ok = false;
+ int value = type->scopedEnumValue(qmlEngine, index, *member->name, &ok);
+ if (!ok)
+ return QV4::IR::VarType;
+ member->setEnumValue(value);
+ return QV4::IR::SInt32Type;
+}
+
+static void initScopedEnumResolver(QV4::IR::MemberExpressionResolver *resolver, QQmlType *qmlType, int index)
+{
+ Q_ASSERT(resolver);
+
+ resolver->resolveMember = &resolveScopedEnum;
+ resolver->data = qmlType;
+ resolver->extraData = 0;
+ resolver->flags = index;
+}
+
#endif // V4_BOOTSTRAP
void JSCodeGen::beginFunctionBodyHook()
@@ -2188,7 +2315,7 @@ QmlIR::Object *IRLoader::loadObject(const QV4::CompiledData::Object *serializedO
QQmlJS::Engine *jsParserEngine = &output->jsParserEngine;
- const QV4::CompiledData::LEUInt32 *functionIdx = serializedObject->functionOffsetTable();
+ const quint32_le *functionIdx = serializedObject->functionOffsetTable();
for (uint i = 0; i < serializedObject->nFunctions; ++i, ++functionIdx) {
QmlIR::Function *f = pool->New<QmlIR::Function>();
const QV4::CompiledData::Function *compiledFunction = unit->functionAt(*functionIdx);
@@ -2199,7 +2326,7 @@ QmlIR::Object *IRLoader::loadObject(const QV4::CompiledData::Object *serializedO
f->nameIndex = compiledFunction->nameIndex;
QQmlJS::AST::FormalParameterList *paramList = 0;
- const QV4::CompiledData::LEUInt32 *formalNameIdx = compiledFunction->formalsTable();
+ const quint32_le *formalNameIdx = compiledFunction->formalsTable();
for (uint i = 0; i < compiledFunction->nFormals; ++i, ++formalNameIdx) {
const QString formal = unit->stringAt(*formalNameIdx);
QStringRef paramNameRef = jsParserEngine->newStringRef(formal);
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 64bf111d9a..4c29e0b9f5 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -265,6 +265,25 @@ public:
struct Object;
+struct EnumValue : public QV4::CompiledData::EnumValue
+{
+ EnumValue *next;
+};
+
+struct Enum
+{
+ int nameIndex;
+ QV4::CompiledData::Location location;
+ PoolList<EnumValue> *enumValues;
+
+ int enumValueCount() const { return enumValues->count; }
+ PoolList<EnumValue>::Iterator enumValuesBegin() const { return enumValues->begin(); }
+ PoolList<EnumValue>::Iterator enumValuesEnd() const { return enumValues->end(); }
+
+ Enum *next;
+};
+
+
struct SignalParameter : public QV4::CompiledData::Parameter
{
SignalParameter *next;
@@ -359,6 +378,8 @@ public:
int propertyCount() const { return properties->count; }
Alias *firstAlias() const { return aliases->first; }
int aliasCount() const { return aliases->count; }
+ const Enum *firstEnum() const { return qmlEnums->first; }
+ int enumCount() const { return qmlEnums->count; }
const Signal *firstSignal() const { return qmlSignals->first; }
int signalCount() const { return qmlSignals->count; }
Binding *firstBinding() const { return bindings->first; }
@@ -372,6 +393,8 @@ public:
PoolList<Property>::Iterator propertiesEnd() const { return properties->end(); }
PoolList<Alias>::Iterator aliasesBegin() const { return aliases->begin(); }
PoolList<Alias>::Iterator aliasesEnd() const { return aliases->end(); }
+ PoolList<Enum>::Iterator enumsBegin() const { return qmlEnums->begin(); }
+ PoolList<Enum>::Iterator enumsEnd() const { return qmlEnums->end(); }
PoolList<Signal>::Iterator signalsBegin() const { return qmlSignals->begin(); }
PoolList<Signal>::Iterator signalsEnd() const { return qmlSignals->end(); }
PoolList<Function>::Iterator functionsBegin() const { return functions->begin(); }
@@ -385,6 +408,7 @@ public:
QString sanityCheckFunctionNames(const QSet<QString> &illegalNames, QQmlJS::AST::SourceLocation *errorLocation);
+ QString appendEnum(Enum *enumeration);
QString appendSignal(Signal *signal);
QString appendProperty(Property *prop, const QString &propertyName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation);
QString appendAlias(Alias *prop, const QString &aliasName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation);
@@ -408,6 +432,7 @@ private:
PoolList<Property> *properties;
PoolList<Alias> *aliases;
+ PoolList<Enum> *qmlEnums;
PoolList<Signal> *qmlSignals;
PoolList<Binding> *bindings;
PoolList<Function> *functions;
@@ -482,6 +507,7 @@ public:
bool visit(QQmlJS::AST::UiArrayBinding *ast) override;
bool visit(QQmlJS::AST::UiObjectBinding *ast) override;
bool visit(QQmlJS::AST::UiObjectDefinition *ast) override;
+ bool visit(QQmlJS::AST::UiEnumDeclaration *ast) override;
bool visit(QQmlJS::AST::UiPublicMember *ast) override;
bool visit(QQmlJS::AST::UiScriptBinding *ast) override;
bool visit(QQmlJS::AST::UiSourceElement *ast) override;
diff --git a/src/qml/compiler/qqmlpropertycachecreator_p.h b/src/qml/compiler/qqmlpropertycachecreator_p.h
index 3c14abc019..5901e4e13e 100644
--- a/src/qml/compiler/qqmlpropertycachecreator_p.h
+++ b/src/qml/compiler/qqmlpropertycachecreator_p.h
@@ -116,7 +116,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObje
{
const CompiledObject *obj = objectContainer->objectAt(objectIndex);
- bool needVMEMetaObject = obj->propertyCount() != 0 || obj->aliasCount() != 0 || obj->signalCount() != 0 || obj->functionCount() != 0;
+ bool needVMEMetaObject = obj->propertyCount() != 0 || obj->aliasCount() != 0 || obj->signalCount() != 0 || obj->functionCount() != 0 || obj->enumCount() != 0;
if (!needVMEMetaObject) {
auto binding = obj->bindingsBegin();
auto end = obj->bindingsEnd();
@@ -244,7 +244,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj
QQmlRefPointer<QQmlPropertyCache> cache;
cache.adopt(baseTypeCache->copyAndReserve(obj->propertyCount() + obj->aliasCount(),
obj->functionCount() + obj->propertyCount() + obj->aliasCount() + obj->signalCount(),
- obj->signalCount() + obj->propertyCount() + obj->aliasCount()));
+ obj->signalCount() + obj->propertyCount() + obj->aliasCount(), obj->enumCount()));
propertyCaches->set(objectIndex, cache);
propertyCaches->setNeedsVMEMetaObject(objectIndex);
@@ -370,6 +370,21 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj
cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
}
+ auto e = obj->enumsBegin();
+ auto eend = obj->enumsEnd();
+ for ( ; e != eend; ++e) {
+ const int enumValueCount = e->enumValueCount();
+ QVector<QQmlEnumValue> values;
+ values.reserve(enumValueCount);
+
+ auto enumValue = e->enumValuesBegin();
+ auto end = e->enumValuesEnd();
+ for ( ; enumValue != end; ++enumValue)
+ values.append(QQmlEnumValue(stringAt(enumValue->nameIndex), enumValue->value));
+
+ cache->appendEnum(stringAt(e->nameIndex), values);
+ }
+
// Dynamic signals
auto s = obj->signalsBegin();
auto send = obj->signalsEnd();
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index d1d22be0ac..c09fde86f1 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -591,21 +591,32 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
if (!string.constData()->isUpper())
return true;
+ // we support one or two '.' in the enum phrase:
+ // * <TypeName>.<EnumValue>
+ // * <TypeName>.<ScopedEnumName>.<EnumValue>
+
int dot = string.indexOf(QLatin1Char('.'));
if (dot == -1 || dot == string.length()-1)
return true;
- if (string.indexOf(QLatin1Char('.'), dot+1) != -1)
- return true;
+ int dot2 = string.indexOf(QLatin1Char('.'), dot+1);
+ if (dot2 != -1 && dot2 != string.length()-1) {
+ if (!string.at(dot+1).isUpper())
+ return true;
+ if (string.indexOf(QLatin1Char('.'), dot2+1) != -1)
+ return true;
+ }
QHashedStringRef typeName(string.constData(), dot);
const bool isQtObject = (typeName == QLatin1String("Qt"));
- const QStringRef enumValue = string.midRef(dot + 1);
+ const QStringRef scopedEnumName = (dot2 != -1 ? string.midRef(dot + 1, dot2 - dot - 1) : QStringRef());
+ // ### consider supporting scoped enums in Qt namespace
+ const QStringRef enumValue = string.midRef(!isQtObject && dot2 != -1 ? dot2 + 1 : dot + 1);
- if (isIntProp) {
+ if (isIntProp) { // ### C++11 allows enums to be other integral types. Should we support other integral types here?
// Allow enum assignment to ints.
bool ok;
- int enumval = evaluateEnum(typeName.toString(), enumValue.toUtf8(), &ok);
+ int enumval = evaluateEnum(typeName.toString(), scopedEnumName, enumValue, &ok);
if (ok) {
if (!assignEnumToBinding(binding, enumValue, enumval, isQtObject))
return false;
@@ -623,18 +634,25 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
auto *tr = resolvedTypes->value(obj->inheritedTypeNameIndex);
if (type && tr && tr->type == type) {
+ // When these two match, we can short cut the search
QMetaProperty mprop = propertyCache->firstCppMetaObject()->property(prop->coreIndex());
+ QMetaEnum menum = mprop.enumerator();
+ QByteArray enumName = enumValue.toUtf8();
+ if (menum.isScoped() && !scopedEnumName.isEmpty() && enumName != scopedEnumName.toUtf8())
+ return true;
- // When these two match, we can short cut the search
if (mprop.isFlagType()) {
- value = mprop.enumerator().keysToValue(enumValue.toUtf8().constData(), &ok);
+ value = menum.keysToValue(enumName.constData(), &ok);
} else {
- value = mprop.enumerator().keyToValue(enumValue.toUtf8().constData(), &ok);
+ value = menum.keyToValue(enumName.constData(), &ok);
}
} else {
// Otherwise we have to search the whole type
if (type) {
- value = type->enumValue(compiler->enginePrivate(), QHashedStringRef(enumValue), &ok);
+ if (!scopedEnumName.isEmpty())
+ value = type->scopedEnumValue(compiler->enginePrivate(), scopedEnumName, enumValue, &ok);
+ else
+ value = type->enumValue(compiler->enginePrivate(), QHashedStringRef(enumValue), &ok);
} else {
QByteArray enumName = enumValue.toUtf8();
const QMetaObject *metaObject = StaticQtMetaObject::get();
@@ -651,7 +669,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
return assignEnumToBinding(binding, enumValue, value, isQtObject);
}
-int QQmlEnumTypeResolver::evaluateEnum(const QString &scope, const QByteArray &enumValue, bool *ok) const
+int QQmlEnumTypeResolver::evaluateEnum(const QString &scope, const QStringRef &enumName, const QStringRef &enumValue, bool *ok) const
{
Q_ASSERT_X(ok, "QQmlEnumTypeResolver::evaluateEnum", "ok must not be a null pointer");
*ok = false;
@@ -661,13 +679,16 @@ int QQmlEnumTypeResolver::evaluateEnum(const QString &scope, const QByteArray &e
imports->resolveType(scope, &type, 0, 0, 0);
if (!type)
return -1;
- return type->enumValue(compiler->enginePrivate(), QHashedCStringRef(enumValue.constData(), enumValue.length()), ok);
+ if (!enumName.isEmpty())
+ return type->scopedEnumValue(compiler->enginePrivate(), enumName, enumValue, ok);
+ return type->enumValue(compiler->enginePrivate(), QHashedStringRef(enumValue.constData(), enumValue.length()), ok);
}
const QMetaObject *mo = StaticQtMetaObject::get();
int i = mo->enumeratorCount();
+ const QByteArray ba = enumValue.toUtf8();
while (i--) {
- int v = mo->enumerator(i).keyToValue(enumValue.constData(), ok);
+ int v = mo->enumerator(i).keyToValue(ba.constData(), ok);
if (*ok)
return v;
}
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index 79fc073d8b..76aa422fc5 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -209,7 +209,7 @@ private:
bool tryQualifiedEnumAssignment(const QmlIR::Object *obj, const QQmlPropertyCache *propertyCache,
const QQmlPropertyData *prop,
QmlIR::Binding *binding);
- int evaluateEnum(const QString &scope, const QByteArray &enumValue, bool *ok) const;
+ int evaluateEnum(const QString &scope, const QStringRef &enumName, const QStringRef &enumValue, bool *ok) const;
const QVector<QmlIR::Object*> &qmlObjects;
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 1e98d1167b..5b7a7f9050 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -128,7 +128,7 @@ static inline bool isSimpleExpr(IR::Expr *e)
Codegen::ScanFunctions::ScanFunctions(Codegen *cg, const QString &sourceCode, CompilationMode defaultProgramMode)
: _cg(cg)
, _sourceCode(sourceCode)
- , _env(0)
+ , _variableEnvironment(0)
, _allowFuncDecls(true)
, defaultProgramMode(defaultProgramMode)
{
@@ -142,17 +142,17 @@ void Codegen::ScanFunctions::operator()(Node *node)
void Codegen::ScanFunctions::enterEnvironment(Node *node, CompilationMode compilationMode)
{
- Environment *e = _cg->newEnvironment(node, _env, compilationMode);
+ Environment *e = _cg->newEnvironment(node, _variableEnvironment, compilationMode);
if (!e->isStrict)
e->isStrict = _cg->_strictMode;
_envStack.append(e);
- _env = e;
+ _variableEnvironment = e;
}
void Codegen::ScanFunctions::leaveEnvironment()
{
_envStack.pop();
- _env = _envStack.isEmpty() ? 0 : _envStack.top();
+ _variableEnvironment = _envStack.isEmpty() ? 0 : _envStack.top();
}
void Codegen::ScanFunctions::checkDirectivePrologue(SourceElements *ast)
@@ -168,7 +168,7 @@ void Codegen::ScanFunctions::checkDirectivePrologue(SourceElements *ast)
continue;
QStringRef str = _sourceCode.midRef(strLit->literalToken.offset + 1, strLit->literalToken.length - 2);
if (str == QLatin1String("use strict")) {
- _env->isStrict = true;
+ _variableEnvironment->isStrict = true;
} else {
// TODO: give a warning.
}
@@ -183,7 +183,7 @@ void Codegen::ScanFunctions::checkDirectivePrologue(SourceElements *ast)
void Codegen::ScanFunctions::checkName(const QStringRef &name, const SourceLocation &loc)
{
- if (_env->isStrict) {
+ if (_variableEnvironment->isStrict) {
if (name == QLatin1String("implements")
|| name == QLatin1String("interface")
|| name == QLatin1String("let")
@@ -201,7 +201,7 @@ void Codegen::ScanFunctions::checkForArguments(AST::FormalParameterList *paramet
{
while (parameters) {
if (parameters->name == QLatin1String("arguments"))
- _env->usesArgumentsObject = Environment::ArgumentsObjectNotUsed;
+ _variableEnvironment->usesArgumentsObject = Environment::ArgumentsObjectNotUsed;
parameters = parameters->next;
}
}
@@ -220,19 +220,19 @@ void Codegen::ScanFunctions::endVisit(Program *)
bool Codegen::ScanFunctions::visit(CallExpression *ast)
{
- if (! _env->hasDirectEval) {
+ if (! _variableEnvironment->hasDirectEval) {
if (IdentifierExpression *id = cast<IdentifierExpression *>(ast->base)) {
if (id->name == QLatin1String("eval")) {
- if (_env->usesArgumentsObject == Environment::ArgumentsObjectUnknown)
- _env->usesArgumentsObject = Environment::ArgumentsObjectUsed;
- _env->hasDirectEval = true;
+ if (_variableEnvironment->usesArgumentsObject == Environment::ArgumentsObjectUnknown)
+ _variableEnvironment->usesArgumentsObject = Environment::ArgumentsObjectUsed;
+ _variableEnvironment->hasDirectEval = true;
}
}
}
int argc = 0;
for (ArgumentList *it = ast->arguments; it; it = it->next)
++argc;
- _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, argc);
+ _variableEnvironment->maxNumberOfArguments = qMax(_variableEnvironment->maxNumberOfArguments, argc);
return true;
}
@@ -241,7 +241,7 @@ bool Codegen::ScanFunctions::visit(NewMemberExpression *ast)
int argc = 0;
for (ArgumentList *it = ast->arguments; it; it = it->next)
++argc;
- _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, argc);
+ _variableEnvironment->maxNumberOfArguments = qMax(_variableEnvironment->maxNumberOfArguments, argc);
return true;
}
@@ -257,26 +257,38 @@ bool Codegen::ScanFunctions::visit(ArrayLiteral *ast)
for (Elision *elision = ast->elision->next; elision; elision = elision->next)
++index;
}
- _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, index);
+ _variableEnvironment->maxNumberOfArguments = qMax(_variableEnvironment->maxNumberOfArguments, index);
return true;
}
bool Codegen::ScanFunctions::visit(VariableDeclaration *ast)
{
- if (_env->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments")))
+ if (_variableEnvironment->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments")))
_cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Variable name may not be eval or arguments in strict mode"));
checkName(ast->name, ast->identifierToken);
if (ast->name == QLatin1String("arguments"))
- _env->usesArgumentsObject = Environment::ArgumentsObjectNotUsed;
- _env->enter(ast->name.toString(), ast->expression ? Environment::VariableDefinition : Environment::VariableDeclaration);
+ _variableEnvironment->usesArgumentsObject = Environment::ArgumentsObjectNotUsed;
+ if (ast->scope == AST::VariableDeclaration::VariableScope::ReadOnlyBlockScope && !ast->expression) {
+ _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Missing initializer in const declaration"));
+ return false;
+ }
+ QString name = ast->name.toString();
+ const Environment::Member *m = 0;
+ if (_variableEnvironment->memberInfo(name, &m)) {
+ if (m->isLexicallyScoped() || ast->isLexicallyScoped()) {
+ _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Identifier %1 has already been declared").arg(name));
+ return false;
+ }
+ }
+ _variableEnvironment->enter(ast->name.toString(), ast->expression ? Environment::VariableDefinition : Environment::VariableDeclaration, ast->scope);
return true;
}
bool Codegen::ScanFunctions::visit(IdentifierExpression *ast)
{
checkName(ast->name, ast->identifierToken);
- if (_env->usesArgumentsObject == Environment::ArgumentsObjectUnknown && ast->name == QLatin1String("arguments"))
- _env->usesArgumentsObject = Environment::ArgumentsObjectUsed;
+ if (_variableEnvironment->usesArgumentsObject == Environment::ArgumentsObjectUnknown && ast->name == QLatin1String("arguments"))
+ _variableEnvironment->usesArgumentsObject = Environment::ArgumentsObjectUsed;
return true;
}
@@ -308,7 +320,7 @@ bool Codegen::ScanFunctions::visit(FunctionExpression *ast)
void Codegen::ScanFunctions::enterFunction(FunctionExpression *ast, bool enterName, bool isExpression)
{
- if (_env->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments")))
+ if (_variableEnvironment->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments")))
_cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Function name may not be eval or arguments in strict mode"));
enterFunction(ast, ast->name.toString(), ast->formals, ast->body, enterName ? ast : 0, isExpression);
}
@@ -329,7 +341,7 @@ bool Codegen::ScanFunctions::visit(ObjectLiteral *ast)
if (AST::cast<AST::PropertyGetterSetter *>(it->assignment))
++argc;
}
- _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, argc);
+ _variableEnvironment->maxNumberOfArguments = qMax(_variableEnvironment->maxNumberOfArguments, argc);
TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, true);
Node::accept(ast->properties, this);
@@ -361,7 +373,7 @@ void Codegen::ScanFunctions::endVisit(FunctionDeclaration *)
bool Codegen::ScanFunctions::visit(WithStatement *ast)
{
- if (_env->isStrict) {
+ if (_variableEnvironment->isStrict) {
_cg->throwSyntaxError(ast->withToken, QStringLiteral("'with' statement is not allowed in strict mode"));
return false;
}
@@ -371,7 +383,7 @@ bool Codegen::ScanFunctions::visit(WithStatement *ast)
bool Codegen::ScanFunctions::visit(DoWhileStatement *ast) {
{
- TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict);
+ TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_variableEnvironment->isStrict);
Node::accept(ast->statement, this);
}
Node::accept(ast->expression, this);
@@ -383,7 +395,7 @@ bool Codegen::ScanFunctions::visit(ForStatement *ast) {
Node::accept(ast->condition, this);
Node::accept(ast->expression, this);
- TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict);
+ TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_variableEnvironment->isStrict);
Node::accept(ast->statement, this);
return false;
@@ -394,7 +406,7 @@ bool Codegen::ScanFunctions::visit(LocalForStatement *ast) {
Node::accept(ast->condition, this);
Node::accept(ast->expression, this);
- TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict);
+ TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_variableEnvironment->isStrict);
Node::accept(ast->statement, this);
return false;
@@ -404,7 +416,7 @@ bool Codegen::ScanFunctions::visit(ForEachStatement *ast) {
Node::accept(ast->initialiser, this);
Node::accept(ast->expression, this);
- TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict);
+ TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_variableEnvironment->isStrict);
Node::accept(ast->statement, this);
return false;
@@ -414,7 +426,7 @@ bool Codegen::ScanFunctions::visit(LocalForEachStatement *ast) {
Node::accept(ast->declaration, this);
Node::accept(ast->expression, this);
- TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict);
+ TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_variableEnvironment->isStrict);
Node::accept(ast->statement, this);
return false;
@@ -422,12 +434,12 @@ bool Codegen::ScanFunctions::visit(LocalForEachStatement *ast) {
bool Codegen::ScanFunctions::visit(ThisExpression *)
{
- _env->usesThis = true;
+ _variableEnvironment->usesThis = true;
return false;
}
bool Codegen::ScanFunctions::visit(Block *ast) {
- TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, _env->isStrict ? false : _allowFuncDecls);
+ TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, _variableEnvironment->isStrict ? false : _allowFuncDecls);
Node::accept(ast->statements, this);
return false;
}
@@ -435,26 +447,26 @@ bool Codegen::ScanFunctions::visit(Block *ast) {
void Codegen::ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParameterList *formals, FunctionBody *body, FunctionExpression *expr, bool isExpression)
{
bool wasStrict = false;
- if (_env) {
- _env->hasNestedFunctions = true;
+ if (_variableEnvironment) {
+ _variableEnvironment->hasNestedFunctions = true;
// The identifier of a function expression cannot be referenced from the enclosing environment.
if (expr)
- _env->enter(name, Environment::FunctionDefinition, expr);
+ _variableEnvironment->enter(name, Environment::FunctionDefinition, AST::VariableDeclaration::FunctionScope, expr);
if (name == QLatin1String("arguments"))
- _env->usesArgumentsObject = Environment::ArgumentsObjectNotUsed;
- wasStrict = _env->isStrict;
+ _variableEnvironment->usesArgumentsObject = Environment::ArgumentsObjectNotUsed;
+ wasStrict = _variableEnvironment->isStrict;
}
enterEnvironment(ast, FunctionCode);
checkForArguments(formals);
- _env->isNamedFunctionExpression = isExpression && !name.isEmpty();
- _env->formals = formals;
+ _variableEnvironment->isNamedFunctionExpression = isExpression && !name.isEmpty();
+ _variableEnvironment->formals = formals;
if (body)
checkDirectivePrologue(body->elements);
- if (wasStrict || _env->isStrict) {
+ if (wasStrict || _variableEnvironment->isStrict) {
QStringList args;
for (FormalParameterList *it = formals; it; it = it->next) {
QString arg = it->name.toString();
@@ -478,7 +490,7 @@ Codegen::Codegen(bool strict)
, _block(0)
, _exitBlock(0)
, _returnAddress(0)
- , _env(0)
+ , _variableEnvironment(0)
, _loop(0)
, _labelledStatement(0)
, _scopeAndFinally(0)
@@ -498,7 +510,7 @@ void Codegen::generateFromProgram(const QString &fileName,
Q_ASSERT(node);
_module = module;
- _env = 0;
+ _variableEnvironment = 0;
_module->setFileName(fileName);
@@ -517,7 +529,7 @@ void Codegen::generateFromFunctionExpression(const QString &fileName,
{
_module = module;
_module->setFileName(fileName);
- _env = 0;
+ _variableEnvironment = 0;
ScanFunctions scan(this, sourceCode, GlobalCode);
// fake a global environment
@@ -534,14 +546,14 @@ void Codegen::generateFromFunctionExpression(const QString &fileName,
void Codegen::enterEnvironment(Node *node)
{
- _env = _envMap.value(node);
- Q_ASSERT(_env);
+ _variableEnvironment = _envMap.value(node);
+ Q_ASSERT(_variableEnvironment);
}
void Codegen::leaveEnvironment()
{
- Q_ASSERT(_env);
- _env = _env->parent;
+ Q_ASSERT(_variableEnvironment);
+ _variableEnvironment = _variableEnvironment->parent;
}
void Codegen::enterLoop(Statement *node, IR::BasicBlock *breakBlock, IR::BasicBlock *continueBlock)
@@ -1443,7 +1455,7 @@ bool Codegen::visit(DeleteExpression *ast)
return false;
// Temporaries cannot be deleted
IR::ArgLocal *al = expr->asArgLocal();
- if (al && al->index < static_cast<unsigned>(_env->members.size())) {
+ if (al && al->index < static_cast<unsigned>(_variableEnvironment->members.size())) {
// Trying to delete a function argument might throw.
if (_function->isStrict) {
throwSyntaxError(ast->deleteToken, QStringLiteral("Delete of an unqualified identifier in strict mode."));
@@ -1472,7 +1484,7 @@ bool Codegen::visit(DeleteExpression *ast)
}
if (expr->asTemp() ||
(expr->asArgLocal() &&
- expr->asArgLocal()->index >= static_cast<unsigned>(_env->members.size()))) {
+ expr->asArgLocal()->index >= static_cast<unsigned>(_variableEnvironment->members.size()))) {
_expr.code = _block->CONST(IR::BoolType, 1);
return false;
}
@@ -1525,7 +1537,7 @@ IR::Expr *Codegen::identifier(const QString &name, int line, int col)
return 0;
uint scope = 0;
- Environment *e = _env;
+ Environment *e = _variableEnvironment;
IR::Function *f = _function;
while (f && e->parent) {
@@ -1556,7 +1568,7 @@ IR::Expr *Codegen::identifier(const QString &name, int line, int col)
if (IR::Expr *fallback = fallbackNameLookup(name, line, col))
return fallback;
- if (!e->parent && (!f || !f->insideWithOrCatch) && _env->compilationMode != EvalCode && e->compilationMode != QmlBinding)
+ if (!e->parent && (!f || !f->insideWithOrCatch) && _variableEnvironment->compilationMode != EvalCode && e->compilationMode != QmlBinding)
return _block->GLOBALNAME(name, line, col);
// global context or with. Lookup by name
@@ -2072,7 +2084,7 @@ bool Codegen::visit(FunctionDeclaration * ast)
TempScope scope(_function);
- if (_env->compilationMode == QmlBinding)
+ if (_variableEnvironment->compilationMode == QmlBinding)
move(_block->TEMP(_returnAddress), _block->NAME(ast->name.toString(), 0, 0));
_expr.accept(nx);
return false;
@@ -2096,26 +2108,26 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
IR::BasicBlock *entryBlock = function->newBasicBlock(0);
IR::BasicBlock *exitBlock = function->newBasicBlock(0, IR::Function::DontInsertBlock);
- function->hasDirectEval = _env->hasDirectEval || _env->compilationMode == EvalCode
+ function->hasDirectEval = _variableEnvironment->hasDirectEval || _variableEnvironment->compilationMode == EvalCode
|| _module->debugMode; // Conditional breakpoints are like eval in the function
- function->usesArgumentsObject = _env->parent && (_env->usesArgumentsObject == Environment::ArgumentsObjectUsed);
- function->usesThis = _env->usesThis;
- function->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, (int)QV4::Global::ReservedArgumentCount);
- function->isStrict = _env->isStrict;
- function->isNamedExpression = _env->isNamedFunctionExpression;
- function->isQmlBinding = _env->compilationMode == QmlBinding;
+ function->usesArgumentsObject = _variableEnvironment->parent && (_variableEnvironment->usesArgumentsObject == Environment::ArgumentsObjectUsed);
+ function->usesThis = _variableEnvironment->usesThis;
+ function->maxNumberOfArguments = qMax(_variableEnvironment->maxNumberOfArguments, (int)QV4::Global::ReservedArgumentCount);
+ function->isStrict = _variableEnvironment->isStrict;
+ function->isNamedExpression = _variableEnvironment->isNamedFunctionExpression;
+ function->isQmlBinding = _variableEnvironment->compilationMode == QmlBinding;
AST::SourceLocation loc = ast->firstSourceLocation();
function->line = loc.startLine;
function->column = loc.startColumn;
if (function->usesArgumentsObject)
- _env->enter(QStringLiteral("arguments"), Environment::VariableDeclaration);
+ _variableEnvironment->enter(QStringLiteral("arguments"), Environment::VariableDeclaration, AST::VariableDeclaration::FunctionScope);
// variables in global code are properties of the global context object, not locals as with other functions.
- if (_env->compilationMode == FunctionCode || _env->compilationMode == QmlBinding) {
+ if (_variableEnvironment->compilationMode == FunctionCode || _variableEnvironment->compilationMode == QmlBinding) {
unsigned t = 0;
- for (Environment::MemberMap::iterator it = _env->members.begin(), end = _env->members.end(); it != end; ++it) {
+ for (Environment::MemberMap::iterator it = _variableEnvironment->members.begin(), end = _variableEnvironment->members.end(); it != end; ++it) {
const QString &local = it.key();
function->LOCAL(local);
(*it).index = t;
@@ -2123,18 +2135,19 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
++t;
}
} else {
- if (!_env->isStrict) {
+ if (!_variableEnvironment->isStrict) {
for (const QString &inheritedLocal : qAsConst(inheritedLocals)) {
function->LOCAL(inheritedLocal);
unsigned tempIndex = entryBlock->newTemp();
Environment::Member member = { Environment::UndefinedMember,
- static_cast<int>(tempIndex), 0 };
- _env->members.insert(inheritedLocal, member);
+ static_cast<int>(tempIndex), 0,
+ AST::VariableDeclaration::VariableScope::FunctionScope };
+ _variableEnvironment->members.insert(inheritedLocal, member);
}
}
IR::ExprList *args = 0;
- for (Environment::MemberMap::const_iterator it = _env->members.constBegin(), cend = _env->members.constEnd(); it != cend; ++it) {
+ for (Environment::MemberMap::const_iterator it = _variableEnvironment->members.constBegin(), cend = _variableEnvironment->members.constEnd(); it != cend; ++it) {
const QString &local = it.key();
IR::ExprList *next = function->New<IR::ExprList>();
next->expr = entryBlock->NAME(local, 0, 0);
@@ -2166,11 +2179,11 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
_function->RECEIVE(it->name.toString());
}
- for (const Environment::Member &member : qAsConst(_env->members)) {
+ for (const Environment::Member &member : qAsConst(_variableEnvironment->members)) {
if (member.function) {
const int function = defineFunction(member.function->name.toString(), member.function, member.function->formals,
member.function->body ? member.function->body->elements : 0);
- if (! _env->parent) {
+ if (! _variableEnvironment->parent) {
move(_block->NAME(member.function->name.toString(), member.function->identifierToken.startLine, member.function->identifierToken.startColumn),
_block->CLOSURE(function));
} else {
@@ -2356,7 +2369,7 @@ bool Codegen::visit(ExpressionStatement *ast)
TempScope scope(_function);
- if (_env->compilationMode == EvalCode || _env->compilationMode == QmlBinding) {
+ if (_variableEnvironment->compilationMode == EvalCode || _variableEnvironment->compilationMode == QmlBinding) {
Result e = expression(ast->expression);
if (*e)
move(_block->TEMP(_returnAddress), *e);
@@ -2604,7 +2617,7 @@ bool Codegen::visit(ReturnStatement *ast)
if (hasError)
return true;
- if (_env->compilationMode != FunctionCode && _env->compilationMode != QmlBinding) {
+ if (_variableEnvironment->compilationMode != FunctionCode && _variableEnvironment->compilationMode != QmlBinding) {
throwSyntaxError(ast->returnToken, QStringLiteral("Return statement outside of function"));
return false;
}
@@ -2992,7 +3005,7 @@ bool Codegen::visit(UiSourceElement *)
bool Codegen::throwSyntaxErrorOnEvalOrArgumentsInStrictMode(IR::Expr *expr, const SourceLocation& loc)
{
- if (!_env->isStrict)
+ if (!_variableEnvironment->isStrict)
return false;
if (IR::Name *n = expr->asName()) {
if (*n->id != QLatin1String("eval") && *n->id != QLatin1String("arguments"))
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index 1cbe6949a1..31e9cc0f46 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -141,10 +141,14 @@ protected:
VariableDeclaration,
FunctionDefinition
};
+
struct Member {
MemberType type;
int index;
AST::FunctionExpression *function;
+ AST::VariableDeclaration::VariableScope scope;
+
+ bool isLexicallyScoped() const { return this->scope != AST::VariableDeclaration::FunctionScope; }
};
typedef QMap<QString, Member> MemberMap;
@@ -191,6 +195,18 @@ protected:
return (*it).index;
}
+ bool memberInfo(const QString &name, const Member **m) const
+ {
+ Q_ASSERT(m);
+ MemberMap::const_iterator it = members.find(name);
+ if (it == members.end()) {
+ *m = 0;
+ return false;
+ }
+ *m = &(*it);
+ return true;
+ }
+
bool lookupMember(const QString &name, Environment **scope, int *index, int *distance)
{
Environment *it = this;
@@ -206,7 +222,7 @@ protected:
return false;
}
- void enter(const QString &name, MemberType type, AST::FunctionExpression *function = 0)
+ void enter(const QString &name, MemberType type, AST::VariableDeclaration::VariableScope scope, AST::FunctionExpression *function = 0)
{
if (! name.isEmpty()) {
if (type != FunctionDefinition) {
@@ -220,8 +236,10 @@ protected:
m.index = -1;
m.type = type;
m.function = function;
+ m.scope = scope;
members.insert(name, m);
} else {
+ Q_ASSERT(scope == (*it).scope);
if ((*it).type <= type) {
(*it).type = type;
(*it).function = function;
@@ -458,7 +476,7 @@ protected:
QV4::IR::BasicBlock *_block;
QV4::IR::BasicBlock *_exitBlock;
unsigned _returnAddress;
- Environment *_env;
+ Environment *_variableEnvironment;
Loop *_loop;
AST::LabelledStatement *_labelledStatement;
ScopeAndFinally *_scopeAndFinally;
@@ -536,7 +554,7 @@ protected:
// fields:
Codegen *_cg;
const QString _sourceCode;
- Environment *_env;
+ Environment *_variableEnvironment;
QStack<Environment *> _envStack;
bool _allowFuncDecls;
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index db707061fe..be7429df41 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -141,7 +141,8 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
flags |= IR::RegExp::RegExp_IgnoreCase;
if (re->flags & CompiledData::RegExp::RegExp_Multiline)
flags |= IR::RegExp::RegExp_Multiline;
- runtimeRegularExpressions[i] = engine->newRegExpObject(data->stringAt(re->stringIndex), flags);
+ QV4::Heap::RegExpObject *ro = engine->newRegExpObject(data->stringAt(re->stringIndex), flags);
+ runtimeRegularExpressions[i] = ro;
}
if (data->lookupTableSize) {
@@ -168,8 +169,6 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
l->level = -1;
l->index = UINT_MAX;
l->nameIndex = compiledLookups[i].nameIndex;
- if (type == CompiledData::Lookup::Type_IndexedGetter || type == CompiledData::Lookup::Type_IndexedSetter)
- l->engine = engine;
}
}
@@ -188,7 +187,7 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
Value *bigEndianConstants = new Value[data->constantTableSize];
- const LEUInt64 *littleEndianConstants = data->constants();
+ const quint64_le *littleEndianConstants = data->constants();
for (uint i = 0; i < data->constantTableSize; ++i)
bigEndianConstants[i] = Value::fromReturnedValue(littleEndianConstants[i]);
constants = bigEndianConstants;
@@ -244,14 +243,14 @@ void CompilationUnit::unlink()
#endif
}
-void CompilationUnit::markObjects(QV4::ExecutionEngine *e)
+void CompilationUnit::markObjects(QV4::MarkStack *markStack)
{
for (uint i = 0; i < data->stringTableSize; ++i)
if (runtimeStrings[i])
- runtimeStrings[i]->mark(e);
+ runtimeStrings[i]->mark(markStack);
if (runtimeRegularExpressions) {
for (uint i = 0; i < data->regexpTableSize; ++i)
- runtimeRegularExpressions[i].mark(e);
+ runtimeRegularExpressions[i].mark(markStack);
}
}
@@ -272,7 +271,7 @@ IdentifierHash<int> CompilationUnit::namedObjectsPerComponent(int componentObjec
if (it == namedObjectsPerComponentCache.end()) {
IdentifierHash<int> namedObjectCache(engine);
const CompiledData::Object *component = data->objectAt(componentObjectIndex);
- const LEUInt32 *namedObjectIndexPtr = component->namedObjectsInComponentTable();
+ const quint32_le *namedObjectIndexPtr = component->namedObjectsInComponentTable();
for (quint32 i = 0; i < component->nNamedObjectsInComponent; ++i, ++namedObjectIndexPtr) {
const CompiledData::Object *namedObject = data->objectAt(*namedObjectIndexPtr);
namedObjectCache.add(runtimeStrings[namedObject->idNameIndex], namedObject->id);
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 23f5e31ebe..b28f77e6e6 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -62,7 +62,7 @@
#include <private/qqmlnullablevalue_p.h>
#include <private/qv4identifier_p.h>
#include <private/qflagpointer_p.h>
-#include <private/qjson_p.h>
+#include <private/qendian_p.h>
#ifndef V4_BOOTSTRAP
#include <private/qqmltypenamecache_p.h>
#include <private/qqmlpropertycache_p.h>
@@ -96,13 +96,6 @@ class CompilationUnitMapper;
namespace CompiledData {
-typedef QJsonPrivate::q_littleendian<qint16> LEInt16;
-typedef QJsonPrivate::q_littleendian<quint16> LEUInt16;
-typedef QJsonPrivate::q_littleendian<quint32> LEUInt32;
-typedef QJsonPrivate::q_littleendian<qint32> LEInt32;
-typedef QJsonPrivate::q_littleendian<quint64> LEUInt64;
-typedef QJsonPrivate::q_littleendian<qint64> LEInt64;
-
struct String;
struct Function;
struct Lookup;
@@ -129,11 +122,12 @@ struct TableIterator
struct Location
{
union {
- QJsonPrivate::qle_bitfield<0, 20> line;
- QJsonPrivate::qle_bitfield<20, 12> column;
+ quint32 _dummy;
+ quint32_le_bitfield<0, 20> line;
+ quint32_le_bitfield<20, 12> column;
};
- Location() { line.val = 0; column.val = 0; }
+ Location() : _dummy(0) { }
inline bool operator<(const Location &other) const {
return line < other.line ||
@@ -149,11 +143,12 @@ struct RegExp
RegExp_Multiline = 0x04
};
union {
- QJsonPrivate::qle_bitfield<0, 4> flags;
- QJsonPrivate::qle_bitfield<4, 28> stringIndex;
+ quint32 _dummy;
+ quint32_le_bitfield<0, 4> flags;
+ quint32_le_bitfield<4, 28> stringIndex;
};
- RegExp() { flags.val = 0; stringIndex.val = 0; }
+ RegExp() : _dummy(0) { }
};
struct Lookup
@@ -167,26 +162,28 @@ struct Lookup
};
union {
- QJsonPrivate::qle_bitfield<0, 4> type_and_flags;
- QJsonPrivate::qle_bitfield<4, 28> nameIndex;
+ quint32 _dummy;
+ quint32_le_bitfield<0, 4> type_and_flags;
+ quint32_le_bitfield<4, 28> nameIndex;
};
- Lookup() { type_and_flags.val = 0; nameIndex.val = 0; }
+ Lookup() : _dummy(0) { }
};
struct JSClassMember
{
union {
- QJsonPrivate::qle_bitfield<0, 31> nameOffset;
- QJsonPrivate::qle_bitfield<31, 1> isAccessor;
+ quint32 _dummy;
+ quint32_le_bitfield<0, 31> nameOffset;
+ quint32_le_bitfield<31, 1> isAccessor;
};
- JSClassMember() { nameOffset = 0; isAccessor = 0; }
+ JSClassMember() : _dummy(0) { }
};
struct JSClass
{
- LEUInt32 nMembers;
+ quint32_le nMembers;
// JSClassMember[nMembers]
static int calculateSize(int nMembers) { return (sizeof(JSClass) + nMembers * sizeof(JSClassMember) + 7) & ~7; }
@@ -194,7 +191,7 @@ struct JSClass
struct String
{
- LEInt32 size;
+ qint32_le size;
// uint16 strdata[]
static int calculateSize(const QString &str) {
@@ -211,29 +208,30 @@ struct Function
HasDirectEval = 0x2,
UsesArgumentsObject = 0x4,
IsNamedExpression = 0x8,
- HasCatchOrWith = 0x10
+ HasCatchOrWith = 0x10,
+ CanUseSimpleCall = 0x20
};
// Absolute offset into file where the code for this function is located. Only used when the function
// is serialized.
- LEUInt64 codeOffset;
- LEUInt64 codeSize;
-
- LEUInt32 nameIndex;
- LEUInt32 nFormals;
- LEUInt32 formalsOffset;
- LEUInt32 nLocals;
- LEUInt32 localsOffset;
- LEUInt32 nInnerFunctions;
+ quint64_le codeOffset;
+ quint64_le codeSize;
+
+ quint32_le nameIndex;
+ quint32_le nFormals;
+ quint32_le formalsOffset;
+ quint32_le nLocals;
+ quint32_le localsOffset;
+ quint32_le nInnerFunctions;
Location location;
// Qml Extensions Begin
- LEUInt32 nDependingIdObjects;
- LEUInt32 dependingIdObjectsOffset; // Array of resolved ID objects
- LEUInt32 nDependingContextProperties;
- LEUInt32 dependingContextPropertiesOffset; // Array of int pairs (property index and notify index)
- LEUInt32 nDependingScopeProperties;
- LEUInt32 dependingScopePropertiesOffset; // Array of int pairs (property index and notify index)
+ quint32_le nDependingIdObjects;
+ quint32_le dependingIdObjectsOffset; // Array of resolved ID objects
+ quint32_le nDependingContextProperties;
+ quint32_le dependingContextPropertiesOffset; // Array of int pairs (property index and notify index)
+ quint32_le nDependingScopeProperties;
+ quint32_le dependingScopePropertiesOffset; // Array of int pairs (property index and notify index)
// Qml Extensions End
// quint32 formalsIndex[nFormals]
@@ -244,15 +242,15 @@ struct Function
// Keep all unaligned data at the end
quint8 flags;
- const LEUInt32 *formalsTable() const { return reinterpret_cast<const LEUInt32 *>(reinterpret_cast<const char *>(this) + formalsOffset); }
- const LEUInt32 *localsTable() const { return reinterpret_cast<const LEUInt32 *>(reinterpret_cast<const char *>(this) + localsOffset); }
- const LEUInt32 *qmlIdObjectDependencyTable() const { return reinterpret_cast<const LEUInt32 *>(reinterpret_cast<const char *>(this) + dependingIdObjectsOffset); }
- const LEUInt32 *qmlContextPropertiesDependencyTable() const { return reinterpret_cast<const LEUInt32 *>(reinterpret_cast<const char *>(this) + dependingContextPropertiesOffset); }
- const LEUInt32 *qmlScopePropertiesDependencyTable() const { return reinterpret_cast<const LEUInt32 *>(reinterpret_cast<const char *>(this) + dependingScopePropertiesOffset); }
+ const quint32_le *formalsTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + formalsOffset); }
+ const quint32_le *localsTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + localsOffset); }
+ const quint32_le *qmlIdObjectDependencyTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + dependingIdObjectsOffset); }
+ const quint32_le *qmlContextPropertiesDependencyTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + dependingContextPropertiesOffset); }
+ const quint32_le *qmlScopePropertiesDependencyTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + dependingScopePropertiesOffset); }
// --- QQmlPropertyCacheCreator interface
- const LEUInt32 *formalsBegin() const { return formalsTable(); }
- const LEUInt32 *formalsEnd() const { return formalsTable() + nFormals; }
+ const quint32_le *formalsBegin() const { return formalsTable(); }
+ const quint32_le *formalsEnd() const { return formalsTable() + nFormals; }
// ---
inline bool hasQmlDependencies() const { return nDependingIdObjects > 0 || nDependingContextProperties > 0 || nDependingScopeProperties > 0; }
@@ -265,13 +263,13 @@ struct Function
// Qml data structures
struct Q_QML_EXPORT TranslationData {
- LEUInt32 commentIndex;
- LEInt32 number;
+ quint32_le commentIndex;
+ qint32_le number;
};
struct Q_QML_PRIVATE_EXPORT Binding
{
- LEUInt32 propertyNameIndex;
+ quint32_le propertyNameIndex;
enum ValueType : unsigned int {
Type_Invalid,
@@ -299,17 +297,17 @@ struct Q_QML_PRIVATE_EXPORT Binding
};
union {
- QJsonPrivate::qle_bitfield<0, 16> flags;
- QJsonPrivate::qle_bitfield<16, 16> type;
+ quint32_le_bitfield<0, 16> flags;
+ quint32_le_bitfield<16, 16> type;
};
union {
bool b;
quint64 doubleValue; // do not access directly, needs endian protected access
- LEUInt32 compiledScriptIndex; // used when Type_Script
- LEUInt32 objectIndex;
+ quint32_le compiledScriptIndex; // used when Type_Script
+ quint32_le objectIndex;
TranslationData translationData; // used when Type_Translation
} value;
- LEUInt32 stringIndex; // Set for Type_String, Type_Translation and Type_Script (the latter because of script strings)
+ quint32_le stringIndex; // Set for Type_String, Type_Translation and Type_Script (the latter because of script strings)
Location location;
Location valueLocation;
@@ -363,7 +361,8 @@ struct Q_QML_PRIVATE_EXPORT Binding
static QString escapedString(const QString &string);
- bool evaluatesToString() const { return type == Type_String || type == Type_Translation || type == Type_TranslationById; }
+ bool containsTranslations() const { return type == Type_Translation || type == Type_TranslationById; }
+ bool evaluatesToString() const { return type == Type_String || containsTranslations(); }
QString valueAsString(const Unit *unit) const;
QString valueAsScriptString(const Unit *unit) const;
@@ -392,18 +391,48 @@ struct Q_QML_PRIVATE_EXPORT Binding
};
+struct EnumValue
+{
+ quint32_le nameIndex;
+ qint32_le value;
+ Location location;
+};
+
+struct Enum
+{
+ quint32_le nameIndex;
+ quint32_le nEnumValues;
+ Location location;
+
+ const EnumValue *enumValueAt(int idx) const {
+ return reinterpret_cast<const EnumValue*>(this + 1) + idx;
+ }
+
+ static int calculateSize(int nEnumValues) {
+ return (sizeof(Enum)
+ + nEnumValues * sizeof(EnumValue)
+ + 7) & ~0x7;
+ }
+
+ // --- QQmlPropertyCacheCreatorInterface
+ const EnumValue *enumValuesBegin() const { return enumValueAt(0); }
+ const EnumValue *enumValuesEnd() const { return enumValueAt(nEnumValues); }
+ int enumValueCount() const { return nEnumValues; }
+ // ---
+};
+
struct Parameter
{
- LEUInt32 nameIndex;
- LEUInt32 type;
- LEUInt32 customTypeNameIndex;
+ quint32_le nameIndex;
+ quint32_le type;
+ quint32_le customTypeNameIndex;
Location location;
};
struct Signal
{
- LEUInt32 nameIndex;
- LEUInt32 nParameters;
+ quint32_le nameIndex;
+ quint32_le nParameters;
Location location;
// Parameter parameters[1];
@@ -435,12 +464,12 @@ struct Property
IsReadOnly = 0x1
};
- LEUInt32 nameIndex;
+ quint32_le nameIndex;
union {
- QJsonPrivate::qle_bitfield<0, 31> type;
- QJsonPrivate::qle_bitfield<31, 1> flags; // readonly
+ quint32_le_bitfield<0, 31> type;
+ quint32_le_bitfield<31, 1> flags; // readonly
};
- LEUInt32 customTypeNameIndex; // If type >= Custom
+ quint32_le customTypeNameIndex; // If type >= Custom
Location location;
};
@@ -451,18 +480,18 @@ struct Alias {
AliasPointsToPointerObject = 0x4
};
union {
- QJsonPrivate::qle_bitfield<0, 29> nameIndex;
- QJsonPrivate::qle_bitfield<29, 3> flags;
+ quint32_le_bitfield<0, 29> nameIndex;
+ quint32_le_bitfield<29, 3> flags;
};
union {
- LEUInt32 idIndex; // string index
- QJsonPrivate::qle_bitfield<0, 31> targetObjectId; // object id index (in QQmlContextData::idValues)
- QJsonPrivate::qle_bitfield<31, 1> aliasToLocalAlias;
+ quint32_le idIndex; // string index
+ quint32_le_bitfield<0, 31> targetObjectId; // object id index (in QQmlContextData::idValues)
+ quint32_le_bitfield<31, 1> aliasToLocalAlias;
};
union {
- LEUInt32 propertyNameIndex; // string index
- LEInt32 encodedMetaPropertyIndex;
- LEUInt32 localAliasIndex; // index in list of aliases local to the object (if targetObjectId == objectId)
+ quint32_le propertyNameIndex; // string index
+ qint32_le encodedMetaPropertyIndex;
+ quint32_le localAliasIndex; // index in list of aliases local to the object (if targetObjectId == objectId)
};
Location location;
Location referenceLocation;
@@ -485,26 +514,28 @@ struct Object
// Depending on the use, this may be the type name to instantiate before instantiating this
// object. For grouped properties the type name will be empty and for attached properties
// it will be the name of the attached type.
- LEUInt32 inheritedTypeNameIndex;
- LEUInt32 idNameIndex;
+ quint32_le inheritedTypeNameIndex;
+ quint32_le idNameIndex;
union {
- QJsonPrivate::qle_bitfield<0, 15> flags;
- QJsonPrivate::qle_bitfield<15, 1> defaultPropertyIsAlias;
- QJsonPrivate::qle_signedbitfield<16, 16> id;
+ quint32_le_bitfield<0, 15> flags;
+ quint32_le_bitfield<15, 1> defaultPropertyIsAlias;
+ qint32_le_bitfield<16, 16> id;
};
- LEInt32 indexOfDefaultPropertyOrAlias; // -1 means no default property declared in this object
- LEUInt32 nFunctions;
- LEUInt32 offsetToFunctions;
- LEUInt32 nProperties;
- LEUInt32 offsetToProperties;
- LEUInt32 nAliases;
- LEUInt32 offsetToAliases;
- LEUInt32 nSignals;
- LEUInt32 offsetToSignals; // which in turn will be a table with offsets to variable-sized Signal objects
- LEUInt32 nBindings;
- LEUInt32 offsetToBindings;
- LEUInt32 nNamedObjectsInComponent;
- LEUInt32 offsetToNamedObjectsInComponent;
+ qint32_le indexOfDefaultPropertyOrAlias; // -1 means no default property declared in this object
+ quint32_le nFunctions;
+ quint32_le offsetToFunctions;
+ quint32_le nProperties;
+ quint32_le offsetToProperties;
+ quint32_le nAliases;
+ quint32_le offsetToAliases;
+ quint32_le nEnums;
+ quint32_le offsetToEnums; // which in turn will be a table with offsets to variable-sized Enum objects
+ quint32_le nSignals;
+ quint32_le offsetToSignals; // which in turn will be a table with offsets to variable-sized Signal objects
+ quint32_le nBindings;
+ quint32_le offsetToBindings;
+ quint32_le nNamedObjectsInComponent;
+ quint32_le offsetToNamedObjectsInComponent;
Location location;
Location locationOfIdProperty;
// Function[]
@@ -512,12 +543,13 @@ struct Object
// Signal[]
// Binding[]
- static int calculateSizeExcludingSignals(int nFunctions, int nProperties, int nAliases, int nSignals, int nBindings, int nNamedObjectsInComponent)
+ static int calculateSizeExcludingSignalsAndEnums(int nFunctions, int nProperties, int nAliases, int nEnums, int nSignals, int nBindings, int nNamedObjectsInComponent)
{
return ( sizeof(Object)
+ nFunctions * sizeof(quint32)
+ nProperties * sizeof(Property)
+ nAliases * sizeof(Alias)
+ + nEnums * sizeof(quint32)
+ nSignals * sizeof(quint32)
+ nBindings * sizeof(Binding)
+ nNamedObjectsInComponent * sizeof(int)
@@ -525,9 +557,9 @@ struct Object
) & ~0x7;
}
- const LEUInt32 *functionOffsetTable() const
+ const quint32_le *functionOffsetTable() const
{
- return reinterpret_cast<const LEUInt32*>(reinterpret_cast<const char *>(this) + offsetToFunctions);
+ return reinterpret_cast<const quint32_le*>(reinterpret_cast<const char *>(this) + offsetToFunctions);
}
const Property *propertyTable() const
@@ -545,21 +577,29 @@ struct Object
return reinterpret_cast<const Binding*>(reinterpret_cast<const char *>(this) + offsetToBindings);
}
+ const Enum *enumAt(int idx) const
+ {
+ const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToEnums);
+ const quint32_le offset = offsetTable[idx];
+ return reinterpret_cast<const Enum*>(reinterpret_cast<const char*>(this) + offset);
+ }
+
const Signal *signalAt(int idx) const
{
- const LEUInt32 *offsetTable = reinterpret_cast<const LEUInt32*>((reinterpret_cast<const char *>(this)) + offsetToSignals);
- const LEUInt32 offset = offsetTable[idx];
+ const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToSignals);
+ const quint32_le offset = offsetTable[idx];
return reinterpret_cast<const Signal*>(reinterpret_cast<const char*>(this) + offset);
}
- const LEUInt32 *namedObjectsInComponentTable() const
+ const quint32_le *namedObjectsInComponentTable() const
{
- return reinterpret_cast<const LEUInt32*>(reinterpret_cast<const char *>(this) + offsetToNamedObjectsInComponent);
+ return reinterpret_cast<const quint32_le*>(reinterpret_cast<const char *>(this) + offsetToNamedObjectsInComponent);
}
// --- QQmlPropertyCacheCreator interface
int propertyCount() const { return nProperties; }
int aliasCount() const { return nAliases; }
+ int enumCount() const { return nEnums; }
int signalCount() const { return nSignals; }
int functionCount() const { return nFunctions; }
@@ -572,6 +612,10 @@ struct Object
const Alias *aliasesBegin() const { return aliasTable(); }
const Alias *aliasesEnd() const { return aliasTable() + nAliases; }
+ typedef TableIterator<Enum, Object, &Object::enumAt> EnumIterator;
+ EnumIterator enumsBegin() const { return EnumIterator(this, 0); }
+ EnumIterator enumsEnd() const { return EnumIterator(this, nEnums); }
+
typedef TableIterator<Signal, Object, &Object::signalAt> SignalIterator;
SignalIterator signalsBegin() const { return SignalIterator(this, 0); }
SignalIterator signalsEnd() const { return SignalIterator(this, nSignals); }
@@ -587,13 +631,13 @@ struct Import
ImportFile = 0x2,
ImportScript = 0x3
};
- LEUInt32 type;
+ quint32_le type;
- LEUInt32 uriIndex;
- LEUInt32 qualifierIndex;
+ quint32_le uriIndex;
+ quint32_le qualifierIndex;
- LEInt32 majorVersion;
- LEInt32 minorVersion;
+ qint32_le majorVersion;
+ qint32_le minorVersion;
Location location;
@@ -606,17 +650,17 @@ struct Unit
{
// DO NOT CHANGE THESE FIELDS EVER
char magic[8];
- LEUInt32 version;
- LEUInt32 qtVersion;
- LEInt64 sourceTimeStamp;
- LEUInt32 unitSize; // Size of the Unit and any depending data.
+ quint32_le version;
+ quint32_le qtVersion;
+ qint64_le sourceTimeStamp;
+ quint32_le unitSize; // Size of the Unit and any depending data.
// END DO NOT CHANGE THESE FIELDS EVER
char md5Checksum[16]; // checksum of all bytes following this field.
void generateChecksum();
- LEUInt32 architectureIndex; // string index to QSysInfo::buildAbi()
- LEUInt32 codeGeneratorIndex;
+ quint32_le architectureIndex; // string index to QSysInfo::buildAbi()
+ quint32_le codeGeneratorIndex;
char dependencyMD5Checksum[16];
enum : unsigned int {
@@ -628,36 +672,36 @@ struct Unit
ContainsMachineCode = 0x20, // used to determine if we need to mmap with execute permissions
PendingTypeCompilation = 0x40 // the QML data structures present are incomplete and require type compilation
};
- LEUInt32 flags;
- LEUInt32 stringTableSize;
- LEUInt32 offsetToStringTable;
- LEUInt32 functionTableSize;
- LEUInt32 offsetToFunctionTable;
- LEUInt32 lookupTableSize;
- LEUInt32 offsetToLookupTable;
- LEUInt32 regexpTableSize;
- LEUInt32 offsetToRegexpTable;
- LEUInt32 constantTableSize;
- LEUInt32 offsetToConstantTable;
- LEUInt32 jsClassTableSize;
- LEUInt32 offsetToJSClassTable;
- LEInt32 indexOfRootFunction;
- LEUInt32 sourceFileIndex;
+ quint32_le flags;
+ quint32_le stringTableSize;
+ quint32_le offsetToStringTable;
+ quint32_le functionTableSize;
+ quint32_le offsetToFunctionTable;
+ quint32_le lookupTableSize;
+ quint32_le offsetToLookupTable;
+ quint32_le regexpTableSize;
+ quint32_le offsetToRegexpTable;
+ quint32_le constantTableSize;
+ quint32_le offsetToConstantTable;
+ quint32_le jsClassTableSize;
+ quint32_le offsetToJSClassTable;
+ qint32_le indexOfRootFunction;
+ quint32_le sourceFileIndex;
/* QML specific fields */
- LEUInt32 nImports;
- LEUInt32 offsetToImports;
- LEUInt32 nObjects;
- LEUInt32 offsetToObjects;
- LEUInt32 indexOfRootObject;
+ quint32_le nImports;
+ quint32_le offsetToImports;
+ quint32_le nObjects;
+ quint32_le offsetToObjects;
+ quint32_le indexOfRootObject;
const Import *importAt(int idx) const {
return reinterpret_cast<const Import*>((reinterpret_cast<const char *>(this)) + offsetToImports + idx * sizeof(Import));
}
const Object *objectAt(int idx) const {
- const LEUInt32 *offsetTable = reinterpret_cast<const LEUInt32*>((reinterpret_cast<const char *>(this)) + offsetToObjects);
- const LEUInt32 offset = offsetTable[idx];
+ const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToObjects);
+ const quint32_le offset = offsetTable[idx];
return reinterpret_cast<const Object*>(reinterpret_cast<const char*>(this) + offset);
}
@@ -667,8 +711,8 @@ struct Unit
/* end QML specific fields*/
QString stringAt(int idx) const {
- const LEUInt32 *offsetTable = reinterpret_cast<const LEUInt32*>((reinterpret_cast<const char *>(this)) + offsetToStringTable);
- const LEUInt32 offset = offsetTable[idx];
+ const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToStringTable);
+ const quint32_le offset = offsetTable[idx];
const String *str = reinterpret_cast<const String*>(reinterpret_cast<const char *>(this) + offset);
if (str->size == 0)
return QString();
@@ -680,7 +724,7 @@ struct Unit
// return QString::fromRawData(characters, str->size);
return QString(characters, str->size);
#else
- const LEUInt16 *characters = reinterpret_cast<const LEUInt16 *>(str + 1);
+ const quint16_le *characters = reinterpret_cast<const quint16_le *>(str + 1);
QString qstr(str->size, Qt::Uninitialized);
QChar *ch = qstr.data();
for (int i = 0; i < str->size; ++i)
@@ -689,11 +733,11 @@ struct Unit
#endif
}
- const LEUInt32 *functionOffsetTable() const { return reinterpret_cast<const LEUInt32*>((reinterpret_cast<const char *>(this)) + offsetToFunctionTable); }
+ const quint32_le *functionOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToFunctionTable); }
const Function *functionAt(int idx) const {
- const LEUInt32 *offsetTable = functionOffsetTable();
- const LEUInt32 offset = offsetTable[idx];
+ const quint32_le *offsetTable = functionOffsetTable();
+ const quint32_le offset = offsetTable[idx];
return reinterpret_cast<const Function*>(reinterpret_cast<const char *>(this) + offset);
}
@@ -701,13 +745,13 @@ struct Unit
const RegExp *regexpAt(int index) const {
return reinterpret_cast<const RegExp*>(reinterpret_cast<const char *>(this) + offsetToRegexpTable + index * sizeof(RegExp));
}
- const LEUInt64 *constants() const {
- return reinterpret_cast<const LEUInt64*>(reinterpret_cast<const char *>(this) + offsetToConstantTable);
+ const quint64_le *constants() const {
+ return reinterpret_cast<const quint64_le*>(reinterpret_cast<const char *>(this) + offsetToConstantTable);
}
const JSClassMember *jsClassAt(int idx, int *nMembers) const {
- const LEUInt32 *offsetTable = reinterpret_cast<const LEUInt32 *>(reinterpret_cast<const char *>(this) + offsetToJSClassTable);
- const LEUInt32 offset = offsetTable[idx];
+ const quint32_le *offsetTable = reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + offsetToJSClassTable);
+ const quint32_le offset = offsetTable[idx];
const char *ptr = reinterpret_cast<const char *>(this) + offset;
const JSClass *klass = reinterpret_cast<const JSClass *>(ptr);
*nMembers = klass->nMembers;
@@ -896,7 +940,7 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public CompilationUnitBase, public
QV4::Function *linkToEngine(QV4::ExecutionEngine *engine);
void unlink();
- void markObjects(QV4::ExecutionEngine *e);
+ void markObjects(MarkStack *markStack);
void destroy() Q_DECL_OVERRIDE;
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index ede432a1e0..35825587b1 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -78,7 +78,7 @@ void QV4::Compiler::StringTableGenerator::clear()
void QV4::Compiler::StringTableGenerator::serialize(CompiledData::Unit *unit)
{
char *dataStart = reinterpret_cast<char *>(unit);
- CompiledData::LEUInt32 *stringTable = reinterpret_cast<CompiledData::LEUInt32 *>(dataStart + unit->offsetToStringTable);
+ quint32_le *stringTable = reinterpret_cast<quint32_le *>(dataStart + unit->offsetToStringTable);
char *stringData = dataStart + unit->offsetToStringTable + unit->stringTableSize * sizeof(uint);
for (int i = 0; i < strings.size(); ++i) {
stringTable[i] = stringData - dataStart;
@@ -220,7 +220,7 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorO
registerString(*f->locals.at(i));
}
- Q_ALLOCA_VAR(CompiledData::LEUInt32, functionOffsets, irModule->functions.size() * sizeof(CompiledData::LEUInt32));
+ Q_ALLOCA_VAR(quint32_le, functionOffsets, irModule->functions.size() * sizeof(quint32_le));
uint jsClassDataOffset = 0;
char *dataPtr;
@@ -233,7 +233,7 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorO
memcpy(unit, &tempHeader, sizeof(tempHeader));
}
- memcpy(dataPtr + unit->offsetToFunctionTable, functionOffsets, unit->functionTableSize * sizeof(CompiledData::LEUInt32));
+ memcpy(dataPtr + unit->offsetToFunctionTable, functionOffsets, unit->functionTableSize * sizeof(quint32_le));
for (int i = 0; i < irModule->functions.size(); ++i) {
QV4::IR::Function *function = irModule->functions.at(i);
@@ -254,7 +254,7 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorO
ReturnedValue *constantTable = reinterpret_cast<ReturnedValue *>(dataPtr + unit->offsetToConstantTable);
memcpy(constantTable, constants.constData(), constants.size() * sizeof(ReturnedValue));
#else
- CompiledData::LEUInt64 *constantTable = reinterpret_cast<CompiledData::LEUInt64 *>(dataPtr + unit->offsetToConstantTable);
+ quint64_le *constantTable = reinterpret_cast<quint64_le *>(dataPtr + unit->offsetToConstantTable);
for (int i = 0; i < constants.count(); ++i)
constantTable[i] = constants.at(i);
#endif
@@ -263,7 +263,7 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorO
memcpy(dataPtr + jsClassDataOffset, jsClassData.constData(), jsClassData.size());
// write js classes and js class lookup table
- CompiledData::LEUInt32 *jsClassOffsetTable = reinterpret_cast<CompiledData::LEUInt32 *>(dataPtr + unit->offsetToJSClassTable);
+ quint32_le *jsClassOffsetTable = reinterpret_cast<quint32_le *>(dataPtr + unit->offsetToJSClassTable);
for (int i = 0; i < jsClassOffsets.count(); ++i)
jsClassOffsetTable[i] = jsClassDataOffset + jsClassOffsets.at(i);
}
@@ -296,6 +296,8 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::IR::Function *i
function->flags |= CompiledData::Function::IsNamedExpression;
if (irFunction->hasTry || irFunction->hasWith)
function->flags |= CompiledData::Function::HasCatchOrWith;
+ if (irFunction->canUseSimpleCall())
+ function->flags |= CompiledData::Function::CanUseSimpleCall;
function->nFormals = irFunction->formals.size();
function->formalsOffset = currentOffset;
currentOffset += function->nFormals * sizeof(quint32);
@@ -335,36 +337,36 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::IR::Function *i
function->codeSize = 0;
// write formals
- CompiledData::LEUInt32 *formals = (CompiledData::LEUInt32 *)(f + function->formalsOffset);
+ quint32_le *formals = (quint32_le *)(f + function->formalsOffset);
for (int i = 0; i < irFunction->formals.size(); ++i)
formals[i] = getStringId(*irFunction->formals.at(i));
// write locals
- CompiledData::LEUInt32 *locals = (CompiledData::LEUInt32 *)(f + function->localsOffset);
+ quint32_le *locals = (quint32_le *)(f + function->localsOffset);
for (int i = 0; i < irFunction->locals.size(); ++i)
locals[i] = getStringId(*irFunction->locals.at(i));
// write QML dependencies
- CompiledData::LEUInt32 *writtenDeps = (CompiledData::LEUInt32 *)(f + function->dependingIdObjectsOffset);
+ quint32_le *writtenDeps = (quint32_le *)(f + function->dependingIdObjectsOffset);
for (int id : irFunction->idObjectDependencies) {
Q_ASSERT(id >= 0);
*writtenDeps++ = static_cast<quint32>(id);
}
- writtenDeps = (CompiledData::LEUInt32 *)(f + function->dependingContextPropertiesOffset);
+ writtenDeps = (quint32_le *)(f + function->dependingContextPropertiesOffset);
for (auto property : irFunction->contextObjectPropertyDependencies) {
*writtenDeps++ = property.key(); // property index
*writtenDeps++ = property.value(); // notify index
}
- writtenDeps = (CompiledData::LEUInt32 *)(f + function->dependingScopePropertiesOffset);
+ writtenDeps = (quint32_le *)(f + function->dependingScopePropertiesOffset);
for (auto property : irFunction->scopeObjectPropertyDependencies) {
*writtenDeps++ = property.key(); // property index
*writtenDeps++ = property.value(); // notify index
}
}
-QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Compiler::JSUnitGenerator::GeneratorOption option, QJsonPrivate::q_littleendian<quint32> *functionOffsets, uint *jsClassDataOffset)
+QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Compiler::JSUnitGenerator::GeneratorOption option, quint32_le *functionOffsets, uint *jsClassDataOffset)
{
CompiledData::Unit unit;
memset(&unit, 0, sizeof(unit));
diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h
index 49b8664513..9c51a44bad 100644
--- a/src/qml/compiler/qv4compiler_p.h
+++ b/src/qml/compiler/qv4compiler_p.h
@@ -52,7 +52,7 @@
#include <QtCore/qstring.h>
#include "qv4jsir_p.h"
-#include <private/qjson_p.h>
+#include <private/qendian_p.h>
QT_BEGIN_NAMESPACE
@@ -120,7 +120,7 @@ struct Q_QML_PRIVATE_EXPORT JSUnitGenerator {
StringTableGenerator stringTable;
QString codeGeneratorName;
private:
- CompiledData::Unit generateHeader(GeneratorOption option, QJsonPrivate::q_littleendian<quint32> *functionOffsets, uint *jsClassDataOffset);
+ CompiledData::Unit generateHeader(GeneratorOption option, quint32_le *functionOffsets, uint *jsClassDataOffset);
IR::Module *irModule;
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index 6f14e3dfaf..190fb1bd5b 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -1357,6 +1357,31 @@ struct Function {
int getNewStatementId() { return _statementCount++; }
int statementCount() const { return _statementCount; }
+ bool canUseSimpleCall() const {
+ return nestedFunctions.isEmpty() &&
+ locals.isEmpty() && formals.size() <= QV4::Global::ReservedArgumentCount &&
+ !hasTry && !hasWith && !isNamedExpression && !usesArgumentsObject && !hasDirectEval;
+ }
+
+ bool argLocalRequiresWriteBarrier(ArgLocal *al) const {
+ uint scope = al->scope;
+ const IR::Function *f = this;
+ while (scope) {
+ f = f->outer;
+ --scope;
+ }
+ return !f->canUseSimpleCall();
+ }
+ int localsCountForScope(ArgLocal *al) const {
+ uint scope = al->scope;
+ const IR::Function *f = this;
+ while (scope) {
+ f = f->outer;
+ --scope;
+ }
+ return f->locals.size();
+ }
+
private:
BasicBlock *getOrCreateBasicBlock(int index);
void setStatementCount(int cnt);
@@ -1425,6 +1450,7 @@ public:
ArgLocal *newArgLocal = f->New<ArgLocal>();
newArgLocal->init(argLocal->kind, argLocal->index, argLocal->scope);
newArgLocal->type = argLocal->type;
+ newArgLocal->isArgumentsOrEval = argLocal->isArgumentsOrEval;
return newArgLocal;
}
diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc
index b5c5505628..c3d073872a 100644
--- a/src/qml/doc/src/cppintegration/data.qdoc
+++ b/src/qml/doc/src/cppintegration/data.qdoc
@@ -273,10 +273,17 @@ In particular, QML currently supports:
\li \c {QList<qreal>}
\li \c {QList<bool>}
\li \c {QList<QString>} and \c{QStringList}
+ \li \c {QVector<QString>}
+ \li \c {std::vector<QString>}
\li \c {QList<QUrl>}
+ \li \c {QVector<QUrl>}
+ \li \c {std::vector<QUrl>}
\li \c {QVector<int>}
\li \c {QVector<qreal>}
\li \c {QVector<bool>}
+ \li \c {std::vector<int>}
+ \li \c {std::vector<qreal>}
+ \li \c {std::vector<bool>}
\endlist
These sequence types are implemented directly in terms of the underlying C++
@@ -296,6 +303,10 @@ If the sequence is returned from a Q_INVOKABLE function, access and mutation
is much cheaper, as no QObject property read or write occurs; instead, the
C++ sequence data is accessed and modified directly.
+In both the Q_PROPERTY and return from Q_INVOKABLE cases, the elements
+of a std::vector are copied. This copying may be an expensive operation,
+so std::vector should be used judiciously.
+
Other sequence types are not supported transparently, and instead an
instance of any other sequence type will be passed between QML and C++ as an
opaque QVariantList.
@@ -318,10 +329,17 @@ The default-constructed values for each sequence type are as follows:
\row \li QList<qreal> \li real value 0.0
\row \li QList<bool> \li boolean value \c {false}
\row \li QList<QString> and QStringList \li empty QString
+\row \li QVector<QString> \li empty QString
+\row \li std::vector<QString> \li empty QString
\row \li QList<QUrl> \li empty QUrl
+\row \li QVector<QUrl> \li empty QUrl
+\row \li std::vector<QUrl> \li empty QUrl
\row \li QVector<int> \li integer value 0
\row \li QVector<qreal> \li real value 0.0
\row \li QVector<bool> \li boolean value \c {false}
+\row \li std::vector<int> \li integer value 0
+\row \li std::vector<qreal> \li real value 0.0
+\row \li std::vector<bool> \li boolean value \c {false}
\endtable
If you wish to remove elements from a sequence rather than simply replace
diff --git a/src/qml/doc/src/javascript/functionlist.qdoc b/src/qml/doc/src/javascript/functionlist.qdoc
index f5b1ed3cf1..fd916e1e24 100644
--- a/src/qml/doc/src/javascript/functionlist.qdoc
+++ b/src/qml/doc/src/javascript/functionlist.qdoc
@@ -182,6 +182,7 @@
\li lastIndexOf(searchString, position)
\li localeCompare(that)
\li match(regexp)
+ \li repeat(count) // ECMAScript 6: Added in Qt 5.9
\li replace(searchValue, replaceValue)
\li search(regexp)
\li slice(start, end)
diff --git a/src/qml/doc/src/javascript/hostenvironment.qdoc b/src/qml/doc/src/javascript/hostenvironment.qdoc
index 1e33f2f641..7e9a22f5d3 100644
--- a/src/qml/doc/src/javascript/hostenvironment.qdoc
+++ b/src/qml/doc/src/javascript/hostenvironment.qdoc
@@ -74,6 +74,19 @@ Note that QML makes the following modifications to native objects:
\li Locale-aware conversion functions are added to the \l Date and \l Number prototypes.
\endlist
+In addition, QML also extends the behavior of the instanceof function to
+allow for type checking against QML types. This means that you may use it to
+verify that a variable is indeed the type you expect, for example:
+
+\qml
+ var v = something();
+ if (!v instanceof Item) {
+ throw new TypeError("I need an Item type!");
+ }
+
+ ...
+\endqml
+
\section1 JavaScript Environment Restrictions
diff --git a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
index df65a0942f..0f08cec844 100644
--- a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
+++ b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
@@ -50,6 +50,7 @@ The set of QML object-type attribute types is as follows:
\li signal handler attributes
\li method attributes
\li attached properties and attached signal handler attributes
+\li enumeration attributes
\endlist
These attributes are discussed in detail below.
@@ -974,4 +975,41 @@ ListView {
Now \c delegateItem.ListView.isCurrentItem correctly refers to the
\c isCurrentItem attached property of the delegate.
+\section2 Enumeration Attributes
+
+Enumerations provide a fixed set of named choices. They can be declared in QML using the \c enum keyword:
+
+\qml
+// MyText.qml
+Text {
+ enum TextType {
+ Normal,
+ Heading
+ }
+}
+\endqml
+
+As shown above, enumeration types (e.g. \c TextType) and values (e.g. \c Normal) must begin with an uppercase letter.
+
+Values are referred to via \c {<Type>.<EnumerationType>.<Value>} or \c {<Type>.<Value>}.
+
+\qml
+// MyText.qml
+Text {
+ enum TextType {
+ Normal,
+ Heading
+ }
+
+ property int textType: MyText.TextType.Normal
+
+ font.bold: textType == MyText.TextType.Heading
+ font.pixelSize: textType == MyText.TextType.Heading ? 24 : 12
+}
+\endqml
+
+More information on enumeration usage in QML can be found in the \l {QML Basic Types} \l enumeration documentation.
+
+The ability to declare enumerations in QML was introduced in Qt 5.10.
+
*/
diff --git a/src/qml/doc/src/qmllanguageref/syntax/propertybinding.qdoc b/src/qml/doc/src/qmllanguageref/syntax/propertybinding.qdoc
index f28ff5082a..99426d984d 100644
--- a/src/qml/doc/src/qmllanguageref/syntax/propertybinding.qdoc
+++ b/src/qml/doc/src/qmllanguageref/syntax/propertybinding.qdoc
@@ -179,6 +179,26 @@ Rectangle {
Now, after the space key is pressed, the rectangle's height will continue
auto-updating to always be three times its width.
+\section3 Debugging overwriting of bindings
+
+A common cause of bugs in QML applications is accidentally overwriting bindings
+with static values from JavaScript statements. To help developers track down
+problems of this kind, the QML engine is able to emit messages whenever a
+binding is lost due to imperative assignments.
+
+In order to generate such messages, you need to enable the informational output
+for the \c{qt.qml.binding.removal} logging category, for instance by calling:
+
+\code
+QLoggingCategory::setFilterRules(QStringLiteral("qt.qml.binding.removal.info=true"));
+\endcode
+
+Please refer to the QLoggingCategory documentation for more information about
+enabling output from logging categories.
+
+Note that is perfectly reasonable in some circumstances to overwrite bindings.
+Any message generated by the QML engine should be treated as a diagnostic aid,
+and not necessarily as evidence of a problem without further investigation.
\section2 Using \c this with Property Binding
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp
index 71dabcd590..d062f3bbb2 100644
--- a/src/qml/jit/qv4assembler.cpp
+++ b/src/qml/jit/qv4assembler.cpp
@@ -249,13 +249,16 @@ void Assembler<TargetConfiguration>::generateCJumpOnCompare(RelationalCondition
}
template <typename TargetConfiguration>
-typename Assembler<TargetConfiguration>::Pointer Assembler<TargetConfiguration>::loadAddress(RegisterID tmp, IR::Expr *e)
+typename Assembler<TargetConfiguration>::Pointer
+Assembler<TargetConfiguration>::loadAddressForWriting(RegisterID tmp, IR::Expr *e, WriteBarrier::Type *barrier)
{
+ if (barrier)
+ *barrier = WriteBarrier::NoBarrier;
IR::Temp *t = e->asTemp();
if (t)
return loadTempAddress(t);
else
- return loadArgLocalAddress(tmp, e->asArgLocal());
+ return loadArgLocalAddressForWriting(tmp, e->asArgLocal(), barrier);
}
template <typename TargetConfiguration>
@@ -268,34 +271,42 @@ typename Assembler<TargetConfiguration>::Pointer Assembler<TargetConfiguration>:
}
template <typename TargetConfiguration>
-typename Assembler<TargetConfiguration>::Pointer Assembler<TargetConfiguration>::loadArgLocalAddress(RegisterID baseReg, IR::ArgLocal *al)
+typename Assembler<TargetConfiguration>::Pointer
+Assembler<TargetConfiguration>::loadArgLocalAddressForWriting(RegisterID baseReg, IR::ArgLocal *al, WriteBarrier::Type *barrier)
{
+ if (barrier)
+ *barrier = _function->argLocalRequiresWriteBarrier(al) ? WriteBarrier::Barrier : WriteBarrier::NoBarrier;
+
int32_t offset = 0;
int scope = al->scope;
loadPtr(Address(EngineRegister, targetStructureOffset(offsetof(EngineBase, current))), baseReg);
- const qint32 outerOffset = targetStructureOffset(Heap::ExecutionContext::baseOffset + offsetof(Heap::ExecutionContextData, outer));
+ const qint32 outerOffset = targetStructureOffset(Heap::ExecutionContextData::baseOffset + offsetof(Heap::ExecutionContextData, outer));
+ const qint32 localsOffset = targetStructureOffset(Heap::CallContextData::baseOffset + offsetof(Heap::CallContextData, function))
+ + 8 // locals is always 8 bytes away from function, regardless of pointer size.
+ + offsetof(ValueArray<0>, values);
- if (scope) {
+ while (scope) {
loadPtr(Address(baseReg, outerOffset), baseReg);
--scope;
- while (scope) {
- loadPtr(Address(baseReg, outerOffset), baseReg);
- --scope;
- }
}
switch (al->kind) {
case IR::ArgLocal::Formal:
case IR::ArgLocal::ScopedFormal: {
- const qint32 callDataOffset = targetStructureOffset(Heap::ExecutionContext::baseOffset + offsetof(Heap::ExecutionContextData, callData));
- loadPtr(Address(baseReg, callDataOffset), baseReg);
- offset = sizeof(CallData) + (al->index - 1) * sizeof(Value);
+ if (barrier && *barrier == WriteBarrier::Barrier) {
+ // if we need a barrier, the baseReg has to point to the ExecutionContext
+ // callData comes directly after locals, calculate the offset using that
+ offset = localsOffset + _function->localsCountForScope(al) * sizeof(Value);
+ offset += sizeof(CallData) + (al->index - 1) * sizeof(Value);
+ } else {
+ const qint32 callDataOffset = targetStructureOffset(Heap::ExecutionContextData::baseOffset + offsetof(Heap::ExecutionContextData, callData));
+ loadPtr(Address(baseReg, callDataOffset), baseReg);
+ offset = sizeof(CallData) + (al->index - 1) * sizeof(Value);
+ }
} break;
case IR::ArgLocal::Local:
case IR::ArgLocal::ScopedLocal: {
- const qint32 localsOffset = targetStructureOffset(Heap::CallContext::baseOffset + offsetof(Heap::CallContextData, locals));
- loadPtr(Address(baseReg, localsOffset), baseReg);
- offset = al->index * sizeof(Value);
+ offset = localsOffset + al->index * sizeof(Value);
} break;
default:
Q_UNREACHABLE();
@@ -307,7 +318,7 @@ template <typename TargetConfiguration>
typename Assembler<TargetConfiguration>::Pointer Assembler<TargetConfiguration>::loadStringAddress(RegisterID reg, const QString &string)
{
loadPtr(Address(Assembler::EngineRegister, targetStructureOffset(offsetof(QV4::EngineBase, current))), Assembler::ScratchRegister);
- loadPtr(Address(Assembler::ScratchRegister, targetStructureOffset(Heap::ExecutionContext::baseOffset + offsetof(Heap::ExecutionContextData, compilationUnit))), Assembler::ScratchRegister);
+ loadPtr(Address(Assembler::ScratchRegister, targetStructureOffset(Heap::ExecutionContextData::baseOffset + offsetof(Heap::ExecutionContextData, compilationUnit))), Assembler::ScratchRegister);
loadPtr(Address(Assembler::ScratchRegister, offsetof(CompiledData::CompilationUnitBase, runtimeStrings)), reg);
const int id = _jsGenerator->registerString(string);
return Pointer(reg, id * RegisterSize);
@@ -323,7 +334,7 @@ template <typename TargetConfiguration>
typename Assembler<TargetConfiguration>::Address Assembler<TargetConfiguration>::loadConstant(const TargetPrimitive &v, RegisterID baseReg)
{
loadPtr(Address(Assembler::EngineRegister, targetStructureOffset(offsetof(QV4::EngineBase, current))), baseReg);
- loadPtr(Address(baseReg, targetStructureOffset(Heap::ExecutionContext::baseOffset + offsetof(Heap::ExecutionContextData, constantTable))), baseReg);
+ loadPtr(Address(baseReg, targetStructureOffset(Heap::ExecutionContextData::baseOffset + offsetof(Heap::ExecutionContextData, constantTable))), baseReg);
const int index = _jsGenerator->registerConstant(v.rawValue());
return Address(baseReg, index * sizeof(QV4::Value));
}
@@ -338,8 +349,9 @@ void Assembler<TargetConfiguration>::loadStringRef(RegisterID reg, const QString
template <typename TargetConfiguration>
void Assembler<TargetConfiguration>::storeValue(TargetPrimitive value, IR::Expr *destination)
{
- Address addr = loadAddress(ScratchRegister, destination);
- storeValue(value, addr);
+ WriteBarrier::Type barrier;
+ Address addr = loadAddressForWriting(ScratchRegister, destination, &barrier);
+ storeValue(value, addr, barrier);
}
template <typename TargetConfiguration>
@@ -428,7 +440,7 @@ typename Assembler<TargetConfiguration>::Jump Assembler<TargetConfiguration>::ge
// It's not a number type, so it cannot be in a register.
Q_ASSERT(src->asArgLocal() || src->asTemp()->kind != IR::Temp::PhysicalRegister || src->type == IR::BoolType);
- Assembler::Pointer tagAddr = loadAddress(Assembler::ScratchRegister, src);
+ Assembler::Pointer tagAddr = loadAddressForReading(Assembler::ScratchRegister, src);
tagAddr.offset += 4;
load32(tagAddr, Assembler::ScratchRegister);
@@ -548,7 +560,7 @@ public:
~QIODevicePrintStream()
{}
- void vprintf(const char* format, va_list argList) WTF_ATTRIBUTE_PRINTF(2, 0)
+ void vprintf(const char* format, va_list argList) override WTF_ATTRIBUTE_PRINTF(2, 0)
{
const int written = qvsnprintf(buf.data(), buf.size(), format, argList);
if (written > 0)
@@ -556,7 +568,7 @@ public:
memset(buf.data(), 0, qMin(written, buf.size()));
}
- void flush()
+ void flush() override
{}
private:
diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h
index 8b5b307e84..9e38696d7a 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -57,6 +57,7 @@
#include "private/qv4value_p.h"
#include "private/qv4context_p.h"
#include "private/qv4engine_p.h"
+#include "private/qv4writebarrier_p.h"
#include "qv4targetplatform_p.h"
#include <config.h>
@@ -152,38 +153,86 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
using TrustedImm64 = typename JITAssembler::TrustedImm64;
using Jump = typename JITAssembler::Jump;
using Label = typename JITAssembler::Label;
-
using ValueTypeInternal = Value::ValueTypeInternal_32;
using TargetPrimitive = TargetPrimitive32;
+ static void emitSetGrayBit(JITAssembler *as, RegisterID base)
+ {
+ bool returnValueUsed = (base == TargetPlatform::ReturnValueRegister);
+
+ as->push(TargetPlatform::EngineRegister); // free up one register for work
+
+ RegisterID grayBitmap = returnValueUsed ? TargetPlatform::ScratchRegister : TargetPlatform::ReturnValueRegister;
+ as->move(base, grayBitmap);
+ Q_ASSERT(base != grayBitmap);
+ as->urshift32(TrustedImm32(Chunk::ChunkShift), grayBitmap);
+ as->lshift32(TrustedImm32(Chunk::ChunkShift), grayBitmap);
+ Q_STATIC_ASSERT(offsetof(Chunk, grayBitmap) == 0);
+
+ RegisterID index = base;
+ as->move(base, index);
+ as->sub32(grayBitmap, index);
+ as->urshift32(TrustedImm32(Chunk::SlotSizeShift), index);
+ RegisterID grayIndex = TargetPlatform::EngineRegister;
+ as->move(index, grayIndex);
+ as->urshift32(TrustedImm32(Chunk::BitShift), grayIndex);
+ as->lshift32(TrustedImm32(2), grayIndex); // 4 bytes per quintptr
+ as->add32(grayIndex, grayBitmap);
+ as->and32(TrustedImm32(Chunk::Bits - 1), index);
+
+ RegisterID bit = TargetPlatform::EngineRegister;
+ as->move(TrustedImm32(1), bit);
+ as->lshift32(index, bit);
+
+ as->load32(Pointer(grayBitmap, 0), index);
+ as->or32(bit, index);
+ as->store32(index, Pointer(grayBitmap, 0));
+
+ as->pop(TargetPlatform::EngineRegister);
+ }
+
+#if WRITEBARRIER(none)
+ static Q_ALWAYS_INLINE void emitWriteBarrier(JITAssembler *, Address) {}
+#endif
+
static void loadDouble(JITAssembler *as, Address addr, FPRegisterID dest)
{
as->MacroAssembler::loadDouble(addr, dest);
}
- static void storeDouble(JITAssembler *as, FPRegisterID source, Address addr)
+ static void storeDouble(JITAssembler *as, FPRegisterID source, Address addr, WriteBarrier::Type barrier)
{
as->MacroAssembler::storeDouble(source, addr);
+ if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier)
+ emitWriteBarrier(as, addr);
}
static void storeDouble(JITAssembler *as, FPRegisterID source, IR::Expr* target)
{
- Pointer ptr = as->loadAddress(TargetPlatform::ScratchRegister, target);
- as->storeDouble(source, ptr);
+ WriteBarrier::Type barrier;
+ Pointer ptr = as->loadAddressForWriting(TargetPlatform::ScratchRegister, target, &barrier);
+ as->storeDouble(source, ptr, barrier);
}
- static void storeValue(JITAssembler *as, TargetPrimitive value, Address destination)
+ static void storeValue(JITAssembler *as, TargetPrimitive value, Address destination, WriteBarrier::Type barrier)
{
as->store32(TrustedImm32(value.value()), destination);
destination.offset += 4;
as->store32(TrustedImm32(value.tag()), destination);
+ if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier)
+ emitWriteBarrier(as, destination);
}
template <typename Source, typename Destination>
- static void copyValueViaRegisters(JITAssembler *as, Source source, Destination destination)
+ static void copyValueViaRegisters(JITAssembler *as, Source source, Destination destination, WriteBarrier::Type barrier)
{
as->loadDouble(source, TargetPlatform::FPGpr0);
- as->storeDouble(TargetPlatform::FPGpr0, destination);
+ // We need to pass NoBarrier to storeDouble and call emitWriteBarrier ourselves, as the
+ // code in storeDouble assumes the type we're storing is actually a double, something
+ // that isn't always the case here.
+ as->storeDouble(TargetPlatform::FPGpr0, destination, WriteBarrier::NoBarrier);
+ if (WriteBarrier::isRequired<WriteBarrier::Unknown>() && barrier == WriteBarrier::Barrier)
+ emitWriteBarrier(as, destination);
}
static void loadDoubleConstant(JITAssembler *as, IR::Const *c, FPRegisterID target)
@@ -196,12 +245,14 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
as->moveIntsToDouble(TargetPlatform::LowReturnValueRegister, TargetPlatform::HighReturnValueRegister, dest, TargetPlatform::FPGpr0);
}
- static void storeReturnValue(JITAssembler *as, const Pointer &dest)
+ static void storeReturnValue(JITAssembler *as, const Pointer &dest, WriteBarrier::Type barrier)
{
Address destination = dest;
as->store32(TargetPlatform::LowReturnValueRegister, destination);
destination.offset += 4;
as->store32(TargetPlatform::HighReturnValueRegister, destination);
+ if (WriteBarrier::isRequired<WriteBarrier::Unknown>() && barrier == WriteBarrier::Barrier)
+ emitWriteBarrier(as, dest);
}
static void setFunctionReturnValueFromTemp(JITAssembler *as, IR::Temp *t)
@@ -237,7 +288,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
Q_UNREACHABLE();
}
} else {
- Pointer addr = as->loadAddress(TargetPlatform::ScratchRegister, t);
+ Pointer addr = as->loadAddressForReading(TargetPlatform::ScratchRegister, t);
as->load32(addr, lowReg);
addr.offset += 4;
as->load32(addr, highReg);
@@ -298,7 +349,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
IR::BasicBlock *nextBlock, IR::BasicBlock *currentBlock,
IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock)
{
- Pointer tagAddr = as->loadAddress(scratchRegister, right);
+ Pointer tagAddr = as->loadAddressForReading(scratchRegister, right);
as->load32(tagAddr, tagRegister);
Jump j = as->branch32(JITAssembler::invert(cond), tagRegister, TrustedImm32(0));
as->addPatch(falseBlock, j);
@@ -315,7 +366,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
{
Q_ASSERT(source->type == IR::VarType);
// load the tag:
- Pointer addr = as->loadAddress(TargetPlatform::ScratchRegister, source);
+ Pointer addr = as->loadAddressForReading(TargetPlatform::ScratchRegister, source);
Pointer tagAddr = addr;
tagAddr.offset += 4;
as->load32(tagAddr, TargetPlatform::ReturnValueRegister);
@@ -326,10 +377,13 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
IR::Temp *targetTemp = target->asTemp();
if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) {
as->load32(addr, TargetPlatform::ReturnValueRegister);
- Pointer targetAddr = as->loadAddress(TargetPlatform::ScratchRegister, target);
+ WriteBarrier::Type barrier;
+ Pointer targetAddr = as->loadAddressForWriting(TargetPlatform::ScratchRegister, target, &barrier);
as->store32(TargetPlatform::ReturnValueRegister, targetAddr);
targetAddr.offset += 4;
as->store32(TrustedImm32(quint32(Value::ValueTypeInternal_32::Integer)), targetAddr);
+ if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier)
+ emitWriteBarrier(as, targetAddr);
} else {
as->load32(addr, (RegisterID) targetTemp->index);
}
@@ -338,17 +392,19 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
// not an int:
fallback.link(as);
generateRuntimeCall(as, TargetPlatform::ReturnValueRegister, toInt,
- as->loadAddress(TargetPlatform::ScratchRegister, source));
+ as->loadAddressForReading(TargetPlatform::ScratchRegister, source));
as->storeInt32(TargetPlatform::ReturnValueRegister, target);
intDone.link(as);
}
- static void loadManagedPointer(JITAssembler *as, RegisterID registerWithPtr, Pointer destAddr)
+ static void loadManagedPointer(JITAssembler *as, RegisterID registerWithPtr, Pointer destAddr, WriteBarrier::Type barrier)
{
as->store32(registerWithPtr, destAddr);
destAddr.offset += 4;
as->store32(TrustedImm32(QV4::Value::Managed_Type_Internal_32), destAddr);
+ if (WriteBarrier::isRequired<WriteBarrier::Object>() && barrier == WriteBarrier::Barrier)
+ emitWriteBarrier(as, destAddr);
}
static Jump generateIsDoubleCheck(JITAssembler *as, RegisterID tagOrValueRegister)
@@ -393,10 +449,48 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
using BranchTruncateType = typename JITAssembler::BranchTruncateType;
using Jump = typename JITAssembler::Jump;
using Label = typename JITAssembler::Label;
-
using ValueTypeInternal = Value::ValueTypeInternal_64;
using TargetPrimitive = TargetPrimitive64;
+ static void emitSetGrayBit(JITAssembler *as, RegisterID base)
+ {
+ bool returnValueUsed = (base == TargetPlatform::ReturnValueRegister);
+
+ as->push(TargetPlatform::EngineRegister); // free up one register for work
+
+ RegisterID grayBitmap = returnValueUsed ? TargetPlatform::ScratchRegister : TargetPlatform::ReturnValueRegister;
+ as->move(base, grayBitmap);
+ Q_ASSERT(base != grayBitmap);
+ as->urshift64(TrustedImm32(Chunk::ChunkShift), grayBitmap);
+ as->lshift64(TrustedImm32(Chunk::ChunkShift), grayBitmap);
+ Q_STATIC_ASSERT(offsetof(Chunk, grayBitmap) == 0);
+
+ RegisterID index = base;
+ as->move(base, index);
+ as->sub64(grayBitmap, index);
+ as->urshift64(TrustedImm32(Chunk::SlotSizeShift), index);
+ RegisterID grayIndex = TargetPlatform::EngineRegister;
+ as->move(index, grayIndex);
+ as->urshift64(TrustedImm32(Chunk::BitShift), grayIndex);
+ as->lshift64(TrustedImm32(3), grayIndex); // 8 bytes per quintptr
+ as->add64(grayIndex, grayBitmap);
+ as->and64(TrustedImm32(Chunk::Bits - 1), index);
+
+ RegisterID bit = TargetPlatform::EngineRegister;
+ as->move(TrustedImm32(1), bit);
+ as->lshift64(index, bit);
+
+ as->load64(Pointer(grayBitmap, 0), index);
+ as->or64(bit, index);
+ as->store64(index, Pointer(grayBitmap, 0));
+
+ as->pop(TargetPlatform::EngineRegister);
+ }
+
+#if WRITEBARRIER(none)
+ static Q_ALWAYS_INLINE void emitWriteBarrier(JITAssembler *, Address) {}
+#endif
+
static void loadDouble(JITAssembler *as, Address addr, FPRegisterID dest)
{
as->load64(addr, TargetPlatform::ReturnValueRegister);
@@ -404,19 +498,24 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
as->move64ToDouble(TargetPlatform::ReturnValueRegister, dest);
}
- static void storeDouble(JITAssembler *as, FPRegisterID source, Address addr)
+ static void storeDouble(JITAssembler *as, FPRegisterID source, Address addr, WriteBarrier::Type barrier)
{
as->moveDoubleTo64(source, TargetPlatform::ReturnValueRegister);
as->xor64(TargetPlatform::DoubleMaskRegister, TargetPlatform::ReturnValueRegister);
as->store64(TargetPlatform::ReturnValueRegister, addr);
+ if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier)
+ emitWriteBarrier(as, addr);
}
static void storeDouble(JITAssembler *as, FPRegisterID source, IR::Expr* target)
{
as->moveDoubleTo64(source, TargetPlatform::ReturnValueRegister);
as->xor64(TargetPlatform::DoubleMaskRegister, TargetPlatform::ReturnValueRegister);
- Pointer ptr = as->loadAddress(TargetPlatform::ScratchRegister, target);
+ WriteBarrier::Type barrier;
+ Pointer ptr = as->loadAddressForWriting(TargetPlatform::ScratchRegister, target, &barrier);
as->store64(TargetPlatform::ReturnValueRegister, ptr);
+ if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier)
+ emitWriteBarrier(as, ptr);
}
static void storeReturnValue(JITAssembler *as, FPRegisterID dest)
@@ -425,9 +524,11 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
as->move64ToDouble(TargetPlatform::ReturnValueRegister, dest);
}
- static void storeReturnValue(JITAssembler *as, const Pointer &dest)
+ static void storeReturnValue(JITAssembler *as, const Pointer &dest, WriteBarrier::Type barrier)
{
as->store64(TargetPlatform::ReturnValueRegister, dest);
+ if (WriteBarrier::isRequired<WriteBarrier::Unknown>() && barrier == WriteBarrier::Barrier)
+ emitWriteBarrier(as, dest);
}
static void setFunctionReturnValueFromTemp(JITAssembler *as, IR::Temp *t)
@@ -468,7 +569,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
TargetPlatform::ReturnValueRegister);
}
} else {
- as->copyValue(TargetPlatform::ReturnValueRegister, t);
+ as->copyValue(TargetPlatform::ReturnValueRegister, t, WriteBarrier::NoBarrier);
}
}
@@ -477,18 +578,20 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
as->move(TrustedImm64(retVal.rawValue()), TargetPlatform::ReturnValueRegister);
}
- static void storeValue(JITAssembler *as, TargetPrimitive value, Address destination)
+ static void storeValue(JITAssembler *as, TargetPrimitive value, Address destination, WriteBarrier::Type barrier)
{
as->store64(TrustedImm64(value.rawValue()), destination);
+ if (WriteBarrier::isRequired<WriteBarrier::Unknown>() && barrier == WriteBarrier::Barrier)
+ emitWriteBarrier(as, destination);
}
template <typename Source, typename Destination>
- static void copyValueViaRegisters(JITAssembler *as, Source source, Destination destination)
+ static void copyValueViaRegisters(JITAssembler *as, Source source, Destination destination, WriteBarrier::Type barrier)
{
// Use ReturnValueRegister as "scratch" register because loadArgument
// and storeArgument are functions that may need a scratch register themselves.
loadArgumentInRegister(as, source, TargetPlatform::ReturnValueRegister, 0);
- as->storeReturnValue(destination);
+ as->storeReturnValue(destination, barrier);
}
static void loadDoubleConstant(JITAssembler *as, IR::Const *c, FPRegisterID target)
@@ -524,7 +627,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
Q_UNUSED(argumentNumber);
if (al) {
- Pointer addr = as->loadArgLocalAddress(dest, al);
+ Pointer addr = as->loadArgLocalAddressForReading(dest, al);
as->load64(addr, dest);
} else {
auto undefined = TargetPrimitive::undefinedValue();
@@ -593,7 +696,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
IR::BasicBlock *nextBlock, IR::BasicBlock *currentBlock,
IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock)
{
- Pointer addr = as->loadAddress(scratchRegister, right);
+ Pointer addr = as->loadAddressForReading(scratchRegister, right);
as->load64(addr, tagRegister);
const TrustedImm64 tag(0);
generateCJumpOnCompare(as, cond, tagRegister, tag, nextBlock, currentBlock, trueBlock, falseBlock);
@@ -602,7 +705,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
static void convertVarToSInt32(JITAssembler *as, IR::Expr *source, IR::Expr *target)
{
Q_ASSERT(source->type == IR::VarType);
- Pointer addr = as->loadAddress(TargetPlatform::ScratchRegister, source);
+ Pointer addr = as->loadAddressForReading(TargetPlatform::ScratchRegister, source);
as->load64(addr, TargetPlatform::ScratchRegister);
as->move(TargetPlatform::ScratchRegister, TargetPlatform::ReturnValueRegister);
@@ -626,25 +729,30 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
// not an int:
fallback.link(as);
generateRuntimeCall(as, TargetPlatform::ReturnValueRegister, toInt,
- as->loadAddress(TargetPlatform::ScratchRegister, source));
+ as->loadAddressForReading(TargetPlatform::ScratchRegister, source));
isIntConvertible.link(as);
success.link(as);
IR::Temp *targetTemp = target->asTemp();
if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) {
- Pointer targetAddr = as->loadAddress(TargetPlatform::ScratchRegister, target);
+ WriteBarrier::Type barrier;
+ Pointer targetAddr = as->loadAddressForWriting(TargetPlatform::ScratchRegister, target, &barrier);
as->store32(TargetPlatform::ReturnValueRegister, targetAddr);
targetAddr.offset += 4;
as->store32(TrustedImm32(quint32(Value::ValueTypeInternal_64::Integer)), targetAddr);
+ if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier)
+ emitWriteBarrier(as, targetAddr);
} else {
as->storeInt32(TargetPlatform::ReturnValueRegister, target);
}
}
- static void loadManagedPointer(JITAssembler *as, RegisterID registerWithPtr, Pointer destAddr)
+ static void loadManagedPointer(JITAssembler *as, RegisterID registerWithPtr, Pointer destAddr, WriteBarrier::Type barrier)
{
as->store64(registerWithPtr, destAddr);
+ if (WriteBarrier::isRequired<WriteBarrier::Object>() && barrier == WriteBarrier::Barrier)
+ emitWriteBarrier(as, destAddr);
}
static Jump generateIsDoubleCheck(JITAssembler *as, RegisterID tagOrValueRegister)
@@ -990,9 +1098,16 @@ public:
Jump branchDouble(bool invertCondition, IR::AluOp op, IR::Expr *left, IR::Expr *right);
Jump branchInt32(bool invertCondition, IR::AluOp op, IR::Expr *left, IR::Expr *right);
- Pointer loadAddress(RegisterID tmp, IR::Expr *t);
+ Pointer loadAddressForWriting(RegisterID tmp, IR::Expr *t, WriteBarrier::Type *barrier);
+ Pointer loadAddressForReading(RegisterID tmp, IR::Expr *t) {
+ return loadAddressForWriting(tmp, t, 0);
+ }
+
Pointer loadTempAddress(IR::Temp *t);
- Pointer loadArgLocalAddress(RegisterID baseReg, IR::ArgLocal *al);
+ Pointer loadArgLocalAddressForWriting(RegisterID baseReg, IR::ArgLocal *al, WriteBarrier::Type *barrier);
+ Pointer loadArgLocalAddressForReading(RegisterID baseReg, IR::ArgLocal *al) {
+ return loadArgLocalAddressForWriting(baseReg, al, 0);
+ }
Pointer loadStringAddress(RegisterID reg, const QString &string);
Address loadConstant(IR::Const *c, RegisterID baseReg);
Address loadConstant(const TargetPrimitive &v, RegisterID baseReg);
@@ -1014,16 +1129,16 @@ public:
Pointer addr(_stackLayout->savedRegPointer(argumentNumber));
switch (t->type) {
case IR::BoolType:
- storeBool((RegisterID) t->index, addr);
+ storeBool((RegisterID) t->index, addr, WriteBarrier::NoBarrier);
break;
case IR::SInt32Type:
- storeInt32((RegisterID) t->index, addr);
+ storeInt32((RegisterID) t->index, addr, WriteBarrier::NoBarrier);
break;
case IR::UInt32Type:
- storeUInt32((RegisterID) t->index, addr);
+ storeUInt32((RegisterID) t->index, addr, WriteBarrier::NoBarrier);
break;
case IR::DoubleType:
- storeDouble((FPRegisterID) t->index, addr);
+ storeDouble((FPRegisterID) t->index, addr, WriteBarrier::NoBarrier);
break;
default:
Q_UNIMPLEMENTED();
@@ -1054,7 +1169,7 @@ public:
if (!temp.value) {
RegisterSizeDependentOps::zeroRegister(this, dest);
} else {
- Pointer addr = toAddress(dest, temp.value, argumentNumber);
+ Pointer addr = toAddress(dest, temp.value, argumentNumber, 0);
loadArgumentInRegister(addr, dest, argumentNumber);
}
}
@@ -1067,7 +1182,7 @@ public:
void loadArgumentInRegister(Reference temp, RegisterID dest, int argumentNumber)
{
Q_ASSERT(temp.value);
- Pointer addr = loadAddress(dest, temp.value);
+ Pointer addr = loadAddressForReading(dest, temp.value);
loadArgumentInRegister(addr, dest, argumentNumber);
}
@@ -1100,8 +1215,10 @@ public:
move(imm32, dest);
}
- void storeReturnValue(RegisterID dest)
+ void storeReturnValue(RegisterID dest, WriteBarrier::Type barrier = WriteBarrier::NoBarrier)
{
+ Q_UNUSED(barrier);
+ Q_ASSERT(barrier == WriteBarrier::NoBarrier);
move(ReturnValueRegister, dest);
}
@@ -1109,7 +1226,7 @@ public:
{
subPtr(TrustedImm32(sizeof(QV4::Value)), StackPointerRegister);
Pointer tmp(StackPointerRegister, 0);
- storeReturnValue(tmp);
+ storeReturnValue(tmp, WriteBarrier::NoBarrier);
toUInt32Register(tmp, dest);
addPtr(TrustedImm32(sizeof(QV4::Value)), StackPointerRegister);
}
@@ -1119,9 +1236,9 @@ public:
RegisterSizeDependentOps::storeReturnValue(this, dest);
}
- void storeReturnValue(const Pointer &dest)
+ void storeReturnValue(const Pointer &dest, WriteBarrier::Type barrier)
{
- RegisterSizeDependentOps::storeReturnValue(this, dest);
+ RegisterSizeDependentOps::storeReturnValue(this, dest, barrier);
}
void storeReturnValue(IR::Expr *target)
@@ -1129,22 +1246,19 @@ public:
if (!target)
return;
- if (IR::Temp *temp = target->asTemp()) {
- if (temp->kind == IR::Temp::PhysicalRegister) {
- if (temp->type == IR::DoubleType)
- storeReturnValue((FPRegisterID) temp->index);
- else if (temp->type == IR::UInt32Type)
- storeUInt32ReturnValue((RegisterID) temp->index);
- else
- storeReturnValue((RegisterID) temp->index);
- return;
- } else {
- Pointer addr = loadTempAddress(temp);
- storeReturnValue(addr);
- }
- } else if (IR::ArgLocal *al = target->asArgLocal()) {
- Pointer addr = loadArgLocalAddress(ScratchRegister, al);
- storeReturnValue(addr);
+ IR::Temp *temp = target->asTemp();
+ if (temp && temp->kind == IR::Temp::PhysicalRegister) {
+ if (temp->type == IR::DoubleType)
+ storeReturnValue((FPRegisterID) temp->index);
+ else if (temp->type == IR::UInt32Type)
+ storeUInt32ReturnValue((RegisterID) temp->index);
+ else
+ storeReturnValue((RegisterID) temp->index);
+ return;
+ } else {
+ WriteBarrier::Type barrier;
+ Pointer addr = loadAddressForWriting(ScratchRegister, target, &barrier);
+ storeReturnValue(addr, barrier);
}
}
@@ -1181,7 +1295,7 @@ public:
void loadArgumentOnStack(PointerToValue temp, int argumentNumber)
{
if (temp.value) {
- Pointer ptr = toAddress(ScratchRegister, temp.value, argumentNumber);
+ Pointer ptr = toAddress(ScratchRegister, temp.value, argumentNumber, 0);
loadArgumentOnStack<StackSlot>(ptr, argumentNumber);
} else {
RegisterSizeDependentOps::zeroStackSlot(this, StackSlot);
@@ -1201,7 +1315,7 @@ public:
{
Q_ASSERT (temp.value);
- Pointer ptr = loadAddress(ScratchRegister, temp.value);
+ Pointer ptr = loadAddressForReading(ScratchRegister, temp.value);
loadArgumentOnStack<StackSlot>(ptr, argumentNumber);
}
@@ -1212,7 +1326,7 @@ public:
moveDouble((FPRegisterID) sourceTemp->index, dest);
return;
}
- Pointer ptr = loadAddress(ScratchRegister, source);
+ Pointer ptr = loadAddressForReading(ScratchRegister, source);
loadDouble(ptr, dest);
}
@@ -1231,46 +1345,65 @@ public:
RegisterSizeDependentOps::loadDouble(this, addr, dest);
}
- void storeDouble(FPRegisterID source, Address addr)
+ void storeDouble(FPRegisterID source, Address addr, WriteBarrier::Type barrier)
{
- RegisterSizeDependentOps::storeDouble(this, source, addr);
+ RegisterSizeDependentOps::storeDouble(this, source, addr, barrier);
}
template <typename Result, typename Source>
- void copyValue(Result result, Source source);
+ void copyValue(Result result, Source source, WriteBarrier::Type barrier);
template <typename Result>
- void copyValue(Result result, IR::Expr* source);
+ void copyValue(Result result, IR::Expr* source, WriteBarrier::Type barrier);
// The scratch register is used to calculate the temp address for the source.
- void memcopyValue(Pointer target, IR::Expr *source, RegisterID scratchRegister)
+ void memcopyValue(Pointer target, IR::Expr *source, RegisterID scratchRegister, WriteBarrier::Type barrier)
{
Q_ASSERT(!source->asTemp() || source->asTemp()->kind != IR::Temp::PhysicalRegister);
Q_ASSERT(target.base != scratchRegister);
- TargetConfiguration::MacroAssembler::loadDouble(loadAddress(scratchRegister, source), FPGpr0);
- TargetConfiguration::MacroAssembler::storeDouble(FPGpr0, target);
+ loadRawValue(loadAddressForReading(scratchRegister, source), FPGpr0);
+ storeRawValue(FPGpr0, target, barrier);
}
// The scratch register is used to calculate the temp address for the source.
void memcopyValue(IR::Expr *target, Pointer source, FPRegisterID fpScratchRegister, RegisterID scratchRegister)
{
- TargetConfiguration::MacroAssembler::loadDouble(source, fpScratchRegister);
- TargetConfiguration::MacroAssembler::storeDouble(fpScratchRegister, loadAddress(scratchRegister, target));
+ loadRawValue(source, fpScratchRegister);
+ WriteBarrier::Type barrier;
+ Pointer dest = loadAddressForWriting(scratchRegister, target, &barrier);
+ storeRawValue(fpScratchRegister, dest, barrier);
+ }
+
+ void loadRawValue(Pointer source, FPRegisterID dest)
+ {
+ TargetConfiguration::MacroAssembler::loadDouble(source, dest);
}
- void storeValue(TargetPrimitive value, Address destination)
+ void storeRawValue(FPRegisterID source, Pointer dest, WriteBarrier::Type barrier)
{
- RegisterSizeDependentOps::storeValue(this, value, destination);
+ TargetConfiguration::MacroAssembler::storeDouble(source, dest);
+ if (WriteBarrier::isRequired<WriteBarrier::Unknown>() && barrier == WriteBarrier::Barrier)
+ RegisterSizeDependentOps::emitWriteBarrier(this, dest);
+ }
+
+ void storeValue(TargetPrimitive value, Address destination, WriteBarrier::Type barrier)
+ {
+ RegisterSizeDependentOps::storeValue(this, value, destination, barrier);
}
void storeValue(TargetPrimitive value, IR::Expr* temp);
+ void emitWriteBarrier(Address addr, WriteBarrier::Type barrier) {
+ if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier)
+ RegisterSizeDependentOps::emitWriteBarrier(this, addr);
+ }
+
void enterStandardStackFrame(const RegisterInformation &regularRegistersToSave,
const RegisterInformation &fpRegistersToSave);
void leaveStandardStackFrame(const RegisterInformation &regularRegistersToSave,
const RegisterInformation &fpRegistersToSave);
void checkException() {
- load32(Address(EngineRegister, targetStructureOffset(offsetof(QV4::EngineBase, hasException))), ScratchRegister);
+ this->load8(Address(EngineRegister, targetStructureOffset(offsetof(QV4::EngineBase, hasException))), ScratchRegister);
Jump exceptionThrown = branch32(RelationalCondition::NotEqual, ScratchRegister, TrustedImm32(0));
if (catchBlock)
addPatch(catchBlock, exceptionThrown);
@@ -1333,7 +1466,7 @@ public:
// load the table from the context
loadPtr(Address(EngineRegister, targetStructureOffset(offsetof(QV4::EngineBase, current))), ScratchRegister);
- loadPtr(Address(ScratchRegister, targetStructureOffset(Heap::ExecutionContext::baseOffset + offsetof(Heap::ExecutionContextData, lookups))),
+ loadPtr(Address(ScratchRegister, targetStructureOffset(Heap::ExecutionContextData::baseOffset + offsetof(Heap::ExecutionContextData, lookups))),
lookupCall.addr.base);
// pre-calculate the indirect address for the lookupCall table:
if (lookupCall.addr.offset)
@@ -1426,8 +1559,10 @@ public:
generateFunctionCallImp(needsExceptionCheck, r, functionName, function, arg1, VoidType(), VoidType(), VoidType(), VoidType(), VoidType());
}
- Pointer toAddress(RegisterID tmpReg, IR::Expr *e, int offset)
+ Pointer toAddress(RegisterID tmpReg, IR::Expr *e, int offset, WriteBarrier::Type *barrier)
{
+ if (barrier)
+ *barrier = WriteBarrier::NoBarrier;
if (IR::Const *c = e->asConst()) {
Address addr = _stackLayout->savedRegPointer(offset);
Address tagAddr = addr;
@@ -1443,14 +1578,16 @@ public:
if (t->kind == IR::Temp::PhysicalRegister)
return Pointer(_stackLayout->savedRegPointer(offset));
- return loadAddress(tmpReg, e);
+ return loadAddressForWriting(tmpReg, e, barrier);
}
- void storeBool(RegisterID reg, Pointer addr)
+ void storeBool(RegisterID reg, Pointer addr, WriteBarrier::Type barrier)
{
store32(reg, addr);
addr.offset += 4;
store32(TrustedImm32(TargetPrimitive::fromBoolean(0).tag()), addr);
+ if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier)
+ RegisterSizeDependentOps::emitWriteBarrier(this, addr);
}
void storeBool(RegisterID src, RegisterID dest)
@@ -1467,8 +1604,9 @@ public:
}
}
- Pointer addr = loadAddress(ScratchRegister, target);
- storeBool(reg, addr);
+ WriteBarrier::Type barrier;
+ Pointer addr = loadAddressForWriting(ScratchRegister, target, &barrier);
+ storeBool(reg, addr, barrier);
}
void storeBool(bool value, IR::Expr *target) {
@@ -1490,25 +1628,24 @@ public:
move(src, dest);
}
- void storeInt32(RegisterID reg, Pointer addr)
+ void storeInt32(RegisterID reg, Pointer addr, WriteBarrier::Type barrier)
{
store32(reg, addr);
addr.offset += 4;
store32(TrustedImm32(TargetPrimitive::fromInt32(0).tag()), addr);
+ if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier)
+ RegisterSizeDependentOps::emitWriteBarrier(this, addr);
}
void storeInt32(RegisterID reg, IR::Expr *target)
{
- if (IR::Temp *targetTemp = target->asTemp()) {
- if (targetTemp->kind == IR::Temp::PhysicalRegister) {
- move(reg, (RegisterID) targetTemp->index);
- } else {
- Pointer addr = loadTempAddress(targetTemp);
- storeInt32(reg, addr);
- }
- } else if (IR::ArgLocal *al = target->asArgLocal()) {
- Pointer addr = loadArgLocalAddress(ScratchRegister, al);
- storeInt32(reg, addr);
+ IR::Temp *targetTemp = target->asTemp();
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) {
+ move(reg, (RegisterID) targetTemp->index);
+ } else {
+ WriteBarrier::Type barrier;
+ Pointer addr = loadAddressForWriting(ScratchRegister, target, &barrier);
+ storeInt32(reg, addr, barrier);
}
}
@@ -1517,15 +1654,15 @@ public:
move(src, dest);
}
- void storeUInt32(RegisterID reg, Pointer addr)
+ void storeUInt32(RegisterID reg, Pointer addr, WriteBarrier::Type barrier)
{
// The UInt32 representation in QV4::Value is really convoluted. See also toUInt32Register.
Jump intRange = branch32(RelationalCondition::GreaterThanOrEqual, reg, TrustedImm32(0));
convertUInt32ToDouble(reg, FPGpr0, ReturnValueRegister);
- storeDouble(FPGpr0, addr);
+ storeDouble(FPGpr0, addr, barrier);
Jump done = jump();
intRange.link(this);
- storeInt32(reg, addr);
+ storeInt32(reg, addr, barrier);
done.link(this);
}
@@ -1535,8 +1672,9 @@ public:
if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) {
move(reg, (RegisterID) targetTemp->index);
} else {
- Pointer addr = loadAddress(ScratchRegister, target);
- storeUInt32(reg, addr);
+ WriteBarrier::Type barrier;
+ Pointer addr = loadAddressForWriting(ScratchRegister, target, &barrier);
+ storeUInt32(reg, addr, barrier);
}
}
@@ -1571,7 +1709,7 @@ public:
if (t->kind == IR::Temp::PhysicalRegister)
return (RegisterID) t->index;
- return toInt32Register(loadAddress(scratchReg, e), scratchReg);
+ return toInt32Register(loadAddressForReading(scratchReg, e), scratchReg);
}
RegisterID toInt32Register(Pointer addr, RegisterID scratchReg)
@@ -1591,7 +1729,7 @@ public:
if (t->kind == IR::Temp::PhysicalRegister)
return (RegisterID) t->index;
- return toUInt32Register(loadAddress(scratchReg, e), scratchReg);
+ return toUInt32Register(loadAddressForReading(scratchReg, e), scratchReg);
}
RegisterID toUInt32Register(Pointer addr, RegisterID scratchReg)
@@ -1666,31 +1804,31 @@ const typename Assembler<TargetConfiguration>::VoidType Assembler<TargetConfigur
template <typename TargetConfiguration>
template <typename Result, typename Source>
-void Assembler<TargetConfiguration>::copyValue(Result result, Source source)
+void Assembler<TargetConfiguration>::copyValue(Result result, Source source, WriteBarrier::Type barrier)
{
- RegisterSizeDependentOps::copyValueViaRegisters(this, source, result);
+ RegisterSizeDependentOps::copyValueViaRegisters(this, source, result, barrier);
}
template <typename TargetConfiguration>
template <typename Result>
-void Assembler<TargetConfiguration>::copyValue(Result result, IR::Expr* source)
+void Assembler<TargetConfiguration>::copyValue(Result result, IR::Expr* source, WriteBarrier::Type barrier)
{
if (source->type == IR::BoolType) {
RegisterID reg = toInt32Register(source, ScratchRegister);
- storeBool(reg, result);
+ storeBool(reg, result, barrier);
} else if (source->type == IR::SInt32Type) {
RegisterID reg = toInt32Register(source, ScratchRegister);
- storeInt32(reg, result);
+ storeInt32(reg, result, barrier);
} else if (source->type == IR::UInt32Type) {
RegisterID reg = toUInt32Register(source, ScratchRegister);
- storeUInt32(reg, result);
+ storeUInt32(reg, result, barrier);
} else if (source->type == IR::DoubleType) {
- storeDouble(toDoubleRegister(source), result);
+ storeDouble(toDoubleRegister(source), result, barrier);
} else if (source->asTemp() || source->asArgLocal()) {
- RegisterSizeDependentOps::copyValueViaRegisters(this, source, result);
+ RegisterSizeDependentOps::copyValueViaRegisters(this, source, result, barrier);
} else if (IR::Const *c = source->asConst()) {
auto v = convertToValue<TargetPrimitive>(c);
- storeValue(v, result);
+ storeValue(v, result, barrier);
} else {
Q_UNREACHABLE();
}
diff --git a/src/qml/jit/qv4binop.cpp b/src/qml/jit/qv4binop.cpp
index feb30ee298..a1c65f644c 100644
--- a/src/qml/jit/qv4binop.cpp
+++ b/src/qml/jit/qv4binop.cpp
@@ -492,7 +492,7 @@ bool Binop<JITAssembler>::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource
return false;
}
} else if (inplaceOpWithAddress) { // All cases of X = X op [address-of-Y]
- Pointer rhsAddr = as->loadAddress(JITAssembler::ScratchRegister, rightSource);
+ Pointer rhsAddr = as->loadAddressForReading(JITAssembler::ScratchRegister, rightSource);
switch (op) {
case IR::OpBitAnd: as->and32(rhsAddr, targetReg); break;
case IR::OpBitOr: as->or32 (rhsAddr, targetReg); break;
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index 50d40f6f98..7784eb364e 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -133,7 +133,7 @@ void InstructionSelection<JITAssembler>::run(int functionIndex)
if (s->location.isValid()) {
if (int(s->location.startLine) != lastLine) {
_as->loadPtr(Address(JITTargetPlatform::EngineRegister, JITAssembler::targetStructureOffset(offsetof(QV4::EngineBase, current))), JITTargetPlatform::ScratchRegister);
- Address lineAddr(JITTargetPlatform::ScratchRegister, JITAssembler::targetStructureOffset(Heap::ExecutionContext::baseOffset + offsetof(Heap::ExecutionContextData, lineNumber)));
+ Address lineAddr(JITTargetPlatform::ScratchRegister, JITAssembler::targetStructureOffset(Heap::ExecutionContextData::baseOffset + offsetof(Heap::ExecutionContextData, lineNumber)));
_as->store32(TrustedImm32(s->location.startLine), lineAddr);
lastLine = s->location.startLine;
}
@@ -350,11 +350,11 @@ void InstructionSelection<JITAssembler>::callBuiltinDefineObjectLiteral(IR::Expr
bool isData = it->expr->asConst()->value;
it = it->next;
- _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr);
+ _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr, WriteBarrier::NoBarrier);
if (!isData) {
it = it->next;
- _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr);
+ _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr, WriteBarrier::NoBarrier);
}
}
@@ -376,10 +376,10 @@ void InstructionSelection<JITAssembler>::callBuiltinDefineObjectLiteral(IR::Expr
++arrayValueCount;
// Index
- _as->storeValue(JITAssembler::TargetPrimitive::fromUInt32(index), _as->stackLayout().argumentAddressForCall(argc++));
+ _as->storeValue(JITAssembler::TargetPrimitive::fromUInt32(index), _as->stackLayout().argumentAddressForCall(argc++), WriteBarrier::NoBarrier);
// Value
- _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr);
+ _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr, WriteBarrier::NoBarrier);
it = it->next;
}
@@ -400,14 +400,14 @@ void InstructionSelection<JITAssembler>::callBuiltinDefineObjectLiteral(IR::Expr
++arrayGetterSetterCount;
// Index
- _as->storeValue(JITAssembler::TargetPrimitive::fromUInt32(index), _as->stackLayout().argumentAddressForCall(argc++));
+ _as->storeValue(JITAssembler::TargetPrimitive::fromUInt32(index), _as->stackLayout().argumentAddressForCall(argc++), WriteBarrier::NoBarrier);
// Getter
- _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr);
+ _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr, WriteBarrier::NoBarrier);
it = it->next;
// Setter
- _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr);
+ _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr, WriteBarrier::NoBarrier);
it = it->next;
}
@@ -447,9 +447,11 @@ void InstructionSelection<JITAssembler>::callValue(IR::Expr *value, IR::ExprList
template <typename JITAssembler>
void InstructionSelection<JITAssembler>::loadThisObject(IR::Expr *temp)
{
- _as->loadPtr(Address(JITTargetPlatform::EngineRegister, JITAssembler::targetStructureOffset(offsetof(QV4::EngineBase, current))), JITTargetPlatform::ScratchRegister);
- _as->loadPtr(Address(JITTargetPlatform::ScratchRegister, JITAssembler::targetStructureOffset(Heap::ExecutionContext::baseOffset + offsetof(Heap::ExecutionContextData, callData))), JITTargetPlatform::ScratchRegister);
- _as->copyValue(temp, Address(JITTargetPlatform::ScratchRegister, offsetof(CallData, thisObject)));
+ WriteBarrier::Type barrier;
+ Pointer addr = _as->loadAddressForWriting(JITTargetPlatform::ScratchRegister, temp, &barrier);
+ _as->loadPtr(Address(JITTargetPlatform::EngineRegister, JITAssembler::targetStructureOffset(offsetof(QV4::EngineBase, current))), JITTargetPlatform::ReturnValueRegister);
+ _as->loadPtr(Address(JITTargetPlatform::ReturnValueRegister,JITAssembler::targetStructureOffset(Heap::ExecutionContextData::baseOffset + offsetof(Heap::ExecutionContextData, callData))), JITTargetPlatform::ReturnValueRegister);
+ _as->copyValue(addr, Address(JITTargetPlatform::ReturnValueRegister, offsetof(CallData, thisObject)), barrier);
}
template <typename JITAssembler>
@@ -503,8 +505,9 @@ void InstructionSelection<JITAssembler>::loadString(const QString &str, IR::Expr
{
Pointer srcAddr = _as->loadStringAddress(JITTargetPlatform::ReturnValueRegister, str);
_as->loadPtr(srcAddr, JITTargetPlatform::ReturnValueRegister);
- Pointer destAddr = _as->loadAddress(JITTargetPlatform::ScratchRegister, target);
- JITAssembler::RegisterSizeDependentOps::loadManagedPointer(_as, JITTargetPlatform::ReturnValueRegister, destAddr);
+ WriteBarrier::Type barrier;
+ Pointer destAddr = _as->loadAddressForWriting(JITTargetPlatform::ScratchRegister, target, &barrier);
+ JITAssembler::RegisterSizeDependentOps::loadManagedPointer(_as, JITTargetPlatform::ReturnValueRegister, destAddr, barrier);
}
template <typename JITAssembler>
@@ -621,6 +624,7 @@ void InstructionSelection<JITAssembler>::getElement(IR::Expr *base, IR::Expr *in
if (0 && useFastLookups) {
uint lookup = registerIndexedGetterLookup();
generateLookupCall(target, lookup, offsetof(QV4::Lookup, indexedGetter),
+ JITTargetPlatform::EngineRegister,
PointerToValue(base),
PointerToValue(index));
return;
@@ -636,6 +640,7 @@ void InstructionSelection<JITAssembler>::setElement(IR::Expr *source, IR::Expr *
if (0 && useFastLookups) {
uint lookup = registerIndexedSetterLookup();
generateLookupCall(JITAssembler::Void, lookup, offsetof(QV4::Lookup, indexedSetter),
+ JITTargetPlatform::EngineRegister,
PointerToValue(targetBase), PointerToValue(targetIndex),
PointerToValue(source));
return;
@@ -711,8 +716,10 @@ void InstructionSelection<JITAssembler>::copyValue(IR::Expr *source, IR::Expr *t
}
}
+ WriteBarrier::Type barrier;
+ Pointer addr = _as->loadAddressForWriting(JITTargetPlatform::ReturnValueRegister, target, &barrier);
// The target is not a physical register, nor is the source. So we can do a memory-to-memory copy:
- _as->memcopyValue(_as->loadAddress(JITTargetPlatform::ReturnValueRegister, target), source, JITTargetPlatform::ScratchRegister);
+ _as->memcopyValue(addr, source, JITTargetPlatform::ScratchRegister, barrier);
}
template <typename JITAssembler>
@@ -739,14 +746,13 @@ void InstructionSelection<JITAssembler>::swapValues(IR::Expr *source, IR::Expr *
} else if (!sourceTemp || sourceTemp->kind == IR::Temp::StackSlot) {
if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) {
// Note: a swap for two stack-slots can involve different types.
- Pointer sAddr = _as->loadAddress(JITTargetPlatform::ScratchRegister, source);
- Pointer tAddr = _as->loadAddress(JITTargetPlatform::ReturnValueRegister, target);
- // use the implementation in JSC::MacroAssembler, as it doesn't do bit swizzling
- auto platformAs = static_cast<typename JITAssembler::MacroAssembler*>(_as);
- platformAs->loadDouble(sAddr, JITTargetPlatform::FPGpr0);
- platformAs->loadDouble(tAddr, JITTargetPlatform::FPGpr1);
- platformAs->storeDouble(JITTargetPlatform::FPGpr1, sAddr);
- platformAs->storeDouble(JITTargetPlatform::FPGpr0, tAddr);
+ WriteBarrier::Type barrierForSource, barrierForTarget;
+ Pointer sAddr = _as->loadAddressForWriting(JITTargetPlatform::ScratchRegister, source, &barrierForSource);
+ Pointer tAddr = _as->loadAddressForWriting(JITTargetPlatform::ReturnValueRegister, target, &barrierForTarget);
+ _as->loadRawValue(sAddr, JITTargetPlatform::FPGpr0);
+ _as->loadRawValue(tAddr, JITTargetPlatform::FPGpr1);
+ _as->storeRawValue(JITTargetPlatform::FPGpr1, sAddr, barrierForSource);
+ _as->storeRawValue(JITTargetPlatform::FPGpr0, tAddr, barrierForTarget);
return;
}
}
@@ -757,14 +763,15 @@ void InstructionSelection<JITAssembler>::swapValues(IR::Expr *source, IR::Expr *
Q_ASSERT(memExpr);
Q_ASSERT(regTemp);
- Pointer addr = _as->loadAddress(JITTargetPlatform::ReturnValueRegister, memExpr);
+ WriteBarrier::Type barrier;
+ Pointer addr = _as->loadAddressForWriting(JITTargetPlatform::ReturnValueRegister, memExpr, &barrier);
if (regTemp->type == IR::DoubleType) {
_as->loadDouble(addr, JITTargetPlatform::FPGpr0);
- _as->storeDouble((FPRegisterID) regTemp->index, addr);
+ _as->storeDouble((FPRegisterID) regTemp->index, addr, barrier);
_as->moveDouble(JITTargetPlatform::FPGpr0, (FPRegisterID) regTemp->index);
} else if (regTemp->type == IR::UInt32Type) {
_as->toUInt32Register(addr, JITTargetPlatform::ScratchRegister);
- _as->storeUInt32((RegisterID) regTemp->index, addr);
+ _as->storeUInt32((RegisterID) regTemp->index, addr, barrier);
_as->move(JITTargetPlatform::ScratchRegister, (RegisterID) regTemp->index);
} else {
_as->load32(addr, JITTargetPlatform::ScratchRegister);
@@ -784,6 +791,7 @@ void InstructionSelection<JITAssembler>::swapValues(IR::Expr *source, IR::Expr *
Q_UNREACHABLE();
}
_as->store32(TrustedImm32(tag), addr);
+ _as->emitWriteBarrier(addr, barrier);
}
_as->move(JITTargetPlatform::ScratchRegister, (RegisterID) regTemp->index);
}
@@ -913,13 +921,13 @@ void InstructionSelection<JITAssembler>::convertTypeToDouble(IR::Expr *source, I
convertUIntToDouble(source, target);
break;
case IR::UndefinedType:
- _as->loadDouble(_as->loadAddress(JITTargetPlatform::ScratchRegister, source), JITTargetPlatform::FPGpr0);
+ _as->loadDouble(_as->loadAddressForReading(JITTargetPlatform::ScratchRegister, source), JITTargetPlatform::FPGpr0);
_as->storeDouble(JITTargetPlatform::FPGpr0, target);
break;
case IR::StringType:
case IR::VarType: {
// load the tag:
- Pointer tagAddr = _as->loadAddress(JITTargetPlatform::ScratchRegister, source);
+ Pointer tagAddr = _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, source);
tagAddr.offset += 4;
_as->load32(tagAddr, JITTargetPlatform::ScratchRegister);
@@ -938,7 +946,7 @@ void InstructionSelection<JITAssembler>::convertTypeToDouble(IR::Expr *source, I
// it is a double:
isDbl.link(_as);
- Pointer addr2 = _as->loadAddress(JITTargetPlatform::ScratchRegister, source);
+ Pointer addr2 = _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, source);
IR::Temp *targetTemp = target->asTemp();
if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) {
_as->memcopyValue(target, addr2, JITTargetPlatform::FPGpr0, JITTargetPlatform::ReturnValueRegister);
@@ -997,7 +1005,7 @@ void InstructionSelection<JITAssembler>::convertTypeToBool(IR::Expr *source, IR:
Q_FALLTHROUGH();
case IR::VarType:
default:
- Pointer addr = _as->loadAddress(JITTargetPlatform::ScratchRegister, source);
+ Pointer addr = _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, source);
Pointer tagAddr = addr;
tagAddr.offset += 4;
_as->load32(tagAddr, JITTargetPlatform::ReturnValueRegister);
@@ -1062,7 +1070,7 @@ void InstructionSelection<JITAssembler>::convertTypeToSInt32(IR::Expr *source, I
case IR::StringType:
default:
generateRuntimeCall(_as, JITTargetPlatform::ReturnValueRegister, toInt,
- _as->loadAddress(JITTargetPlatform::ScratchRegister, source));
+ _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, source));
_as->storeInt32(JITTargetPlatform::ReturnValueRegister, target);
break;
} // switch (source->type)
@@ -1074,21 +1082,21 @@ void InstructionSelection<JITAssembler>::convertTypeToUInt32(IR::Expr *source, I
switch (source->type) {
case IR::VarType: {
// load the tag:
- Pointer tagAddr = _as->loadAddress(JITTargetPlatform::ScratchRegister, source);
+ Pointer tagAddr = _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, source);
tagAddr.offset += 4;
_as->load32(tagAddr, JITTargetPlatform::ScratchRegister);
// check if it's an int32:
Jump isNoInt = _as->branch32(RelationalCondition::NotEqual, JITTargetPlatform::ScratchRegister,
TrustedImm32(quint32(JITAssembler::ValueTypeInternal::Integer)));
- Pointer addr = _as->loadAddress(JITTargetPlatform::ScratchRegister, source);
+ Pointer addr = _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, source);
_as->storeUInt32(_as->toInt32Register(addr, JITTargetPlatform::ScratchRegister), target);
Jump intDone = _as->jump();
// not an int:
isNoInt.link(_as);
generateRuntimeCall(_as, JITTargetPlatform::ReturnValueRegister, toUInt,
- _as->loadAddress(JITTargetPlatform::ScratchRegister, source));
+ _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, source));
_as->storeInt32(JITTargetPlatform::ReturnValueRegister, target);
intDone.link(_as);
@@ -1193,7 +1201,7 @@ void InstructionSelection<JITAssembler>::visitCJump(IR::CJump *s)
reg = JITTargetPlatform::ReturnValueRegister;
_as->toInt32Register(t, reg);
} else {
- Address temp = _as->loadAddress(JITTargetPlatform::ScratchRegister, s->cond);
+ Address temp = _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, s->cond);
Address tag = temp;
tag.offset += QV4::Value::tagOffset();
Jump booleanConversion = _as->branch32(RelationalCondition::NotEqual, tag,
@@ -1299,9 +1307,9 @@ int InstructionSelection<JITAssembler>::prepareVariableArguments(IR::ExprList* a
Q_ASSERT(arg != 0);
Pointer dst(_as->stackLayout().argumentAddressForCall(i));
if (arg->asTemp() && arg->asTemp()->kind != IR::Temp::PhysicalRegister)
- _as->memcopyValue(dst, arg->asTemp(), JITTargetPlatform::ScratchRegister);
+ _as->memcopyValue(dst, arg->asTemp(), JITTargetPlatform::ScratchRegister, WriteBarrier::NoBarrier);
else
- _as->copyValue(dst, arg);
+ _as->copyValue(dst, arg, WriteBarrier::NoBarrier);
}
return argc;
@@ -1321,9 +1329,9 @@ int InstructionSelection<JITAssembler>::prepareCallData(IR::ExprList* args, IR::
_as->store32(TrustedImm32(argc), p);
p = _as->stackLayout().callDataAddress(offsetof(CallData, thisObject));
if (!thisObject)
- _as->storeValue(JITAssembler::TargetPrimitive::undefinedValue(), p);
+ _as->storeValue(JITAssembler::TargetPrimitive::undefinedValue(), p, WriteBarrier::NoBarrier);
else
- _as->copyValue(p, thisObject);
+ _as->copyValue(p, thisObject, WriteBarrier::NoBarrier);
int i = 0;
for (IR::ExprList *it = args; it; it = it->next, ++i) {
@@ -1331,9 +1339,9 @@ int InstructionSelection<JITAssembler>::prepareCallData(IR::ExprList* args, IR::
Q_ASSERT(arg != 0);
Pointer dst(_as->stackLayout().argumentAddressForCall(i));
if (arg->asTemp() && arg->asTemp()->kind != IR::Temp::PhysicalRegister)
- _as->memcopyValue(dst, arg->asTemp(), JITTargetPlatform::ScratchRegister);
+ _as->memcopyValue(dst, arg->asTemp(), JITTargetPlatform::ScratchRegister, WriteBarrier::NoBarrier);
else
- _as->copyValue(dst, arg);
+ _as->copyValue(dst, arg, WriteBarrier::NoBarrier);
}
return argc;
}
@@ -1451,7 +1459,7 @@ bool InstructionSelection<JITAssembler>::visitCJumpStrictNull(IR::Binop *binop,
return true;
}
- Pointer tagAddr = _as->loadAddress(JITTargetPlatform::ScratchRegister, varSrc);
+ Pointer tagAddr = _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, varSrc);
tagAddr.offset += 4;
const RegisterID tagReg = JITTargetPlatform::ScratchRegister;
_as->load32(tagAddr, tagReg);
@@ -1534,7 +1542,7 @@ bool InstructionSelection<JITAssembler>::visitCJumpStrictBool(IR::Binop *binop,
return true;
}
- Pointer otherAddr = _as->loadAddress(JITTargetPlatform::ReturnValueRegister, otherSrc);
+ Pointer otherAddr = _as->loadAddressForReading(JITTargetPlatform::ReturnValueRegister, otherSrc);
otherAddr.offset += 4; // tag address
// check if the tag of the var operand is indicates 'boolean'
@@ -1583,7 +1591,7 @@ bool InstructionSelection<JITAssembler>::visitCJumpNullUndefined(IR::Type nullOr
return true;
}
- Pointer tagAddr = _as->loadAddress(JITTargetPlatform::ScratchRegister, varSrc);
+ Pointer tagAddr = _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, varSrc);
tagAddr.offset += 4;
const RegisterID tagReg = JITTargetPlatform::ReturnValueRegister;
_as->load32(tagAddr, tagReg);
diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h
index 0992e96e8b..7019a117a2 100644
--- a/src/qml/jit/qv4isel_masm_p.h
+++ b/src/qml/jit/qv4isel_masm_p.h
@@ -209,7 +209,7 @@ private:
_as->convertInt32ToDouble((RegisterID) sourceTemp->index,
(FPRegisterID) targetTemp->index);
} else {
- _as->convertInt32ToDouble(_as->loadAddress(JITTargetPlatform::ReturnValueRegister, sourceTemp),
+ _as->convertInt32ToDouble(_as->loadAddressForReading(JITTargetPlatform::ReturnValueRegister, sourceTemp),
(FPRegisterID) targetTemp->index);
}
} else {
@@ -223,7 +223,7 @@ private:
_as->convertInt32ToDouble(_as->toInt32Register(source, JITTargetPlatform::ScratchRegister),
JITTargetPlatform::FPGpr0);
- _as->storeDouble(JITTargetPlatform::FPGpr0, _as->loadAddress(JITTargetPlatform::ReturnValueRegister, target));
+ _as->storeDouble(JITTargetPlatform::FPGpr0, target);
}
void convertUIntToDouble(IR::Expr *source, IR::Expr *target)
@@ -240,7 +240,7 @@ private:
_as->convertUInt32ToDouble(_as->toUInt32Register(source, tmpReg),
JITTargetPlatform::FPGpr0, tmpReg);
- _as->storeDouble(JITTargetPlatform::FPGpr0, _as->loadAddress(tmpReg, target));
+ _as->storeDouble(JITTargetPlatform::FPGpr0, target);
}
void convertIntToBool(IR::Expr *source, IR::Expr *target)
@@ -260,8 +260,8 @@ private:
void calculateRegistersToSave(const RegisterInformation &used);
- template <typename Retval, typename Arg1, typename Arg2, typename Arg3>
- void generateLookupCall(Retval retval, uint index, uint getterSetterOffset, Arg1 arg1, Arg2 arg2, Arg3 arg3)
+ template <typename Retval, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+ void generateLookupCall(Retval retval, uint index, uint getterSetterOffset, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
{
// Note: using the return value register is intentional: for ABIs where the first parameter
// goes into the same register as the return value (currently only ARM), the prepareCall
@@ -271,7 +271,7 @@ private:
_as->generateFunctionCallImp(true, retval, "lookup getter/setter",
typename JITAssembler::LookupCall(lookupAddr, getterSetterOffset), lookupAddr,
- arg1, arg2, arg3);
+ arg1, arg2, arg3, arg4);
}
template <typename Retval, typename Arg1, typename Arg2>
@@ -280,6 +280,12 @@ private:
generateLookupCall(retval, index, getterSetterOffset, arg1, arg2, typename JITAssembler::VoidType());
}
+ template <typename Retval, typename Arg1, typename Arg2, typename Arg3>
+ void generateLookupCall(Retval retval, uint index, uint getterSetterOffset, Arg1 arg1, Arg2 arg2, Arg3 arg3)
+ {
+ generateLookupCall(retval, index, getterSetterOffset, arg1, arg2, arg3, typename JITAssembler::VoidType());
+ }
+
IR::BasicBlock *_block;
BitVector _removableJumps;
JITAssembler* _as;
diff --git a/src/qml/jsapi/qjsvalue.h b/src/qml/jsapi/qjsvalue.h
index ab20a2607d..56bd64eec1 100644
--- a/src/qml/jsapi/qjsvalue.h
+++ b/src/qml/jsapi/qjsvalue.h
@@ -133,9 +133,9 @@ public:
bool deleteProperty(const QString &name);
bool isCallable() const;
- QJSValue call(const QJSValueList &args = QJSValueList());
- QJSValue callWithInstance(const QJSValue &instance, const QJSValueList &args = QJSValueList());
- QJSValue callAsConstructor(const QJSValueList &args = QJSValueList());
+ QJSValue call(const QJSValueList &args = QJSValueList()); // ### Qt6: Make const
+ QJSValue callWithInstance(const QJSValue &instance, const QJSValueList &args = QJSValueList()); // ### Qt6: Make const
+ QJSValue callAsConstructor(const QJSValueList &args = QJSValueList()); // ### Qt6: Make const
#ifdef QT_DEPRECATED
QT_DEPRECATED QJSEngine *engine() const;
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 6ab838c387..0905c2828a 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -48,32 +48,33 @@ DEFINE_OBJECT_VTABLE(ArgumentsObject);
void Heap::ArgumentsObject::init(QV4::CallContext *context)
{
+ ExecutionEngine *v4 = internalClass->engine;
+
Object::init();
fullyCreated = false;
- this->context = context->d();
+ this->context.set(v4, context->d());
Q_ASSERT(vtable() == QV4::ArgumentsObject::staticVTable());
- ExecutionEngine *v4 = context->engine();
Scope scope(v4);
Scoped<QV4::ArgumentsObject> args(scope, this);
if (context->d()->strictMode) {
Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(v4->id_callee()));
Q_ASSERT(CallerPropertyIndex == args->internalClass()->find(v4->id_caller()));
- *args->propertyData(CalleePropertyIndex + QV4::Object::GetterOffset) = v4->thrower();
- *args->propertyData(CalleePropertyIndex + QV4::Object::SetterOffset) = v4->thrower();
- *args->propertyData(CallerPropertyIndex + QV4::Object::GetterOffset) = v4->thrower();
- *args->propertyData(CallerPropertyIndex + QV4::Object::SetterOffset) = v4->thrower();
+ args->setProperty(CalleePropertyIndex + QV4::Object::GetterOffset, *v4->thrower());
+ args->setProperty(CalleePropertyIndex + QV4::Object::SetterOffset, *v4->thrower());
+ args->setProperty(CallerPropertyIndex + QV4::Object::GetterOffset, *v4->thrower());
+ args->setProperty(CallerPropertyIndex + QV4::Object::SetterOffset, *v4->thrower());
args->arrayReserve(context->argc());
args->arrayPut(0, context->args(), context->argc());
args->d()->fullyCreated = true;
} else {
Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(v4->id_callee()));
- *args->propertyData(CalleePropertyIndex) = context->d()->function->asReturnedValue();
+ args->setProperty(CalleePropertyIndex, context->d()->function);
}
Q_ASSERT(LengthPropertyIndex == args->internalClass()->find(v4->id_length()));
- *args->propertyData(LengthPropertyIndex) = Primitive::fromInt32(context->d()->callData->argc);
+ args->setProperty(LengthPropertyIndex, Primitive::fromInt32(context->d()->callData->argc));
}
void ArgumentsObject::fullyCreate()
@@ -90,9 +91,9 @@ void ArgumentsObject::fullyCreate()
Scoped<MemberData> md(scope, d()->mappedArguments);
if (numAccessors) {
- d()->mappedArguments = md->allocate(scope.engine, numAccessors);
+ d()->mappedArguments.set(scope.engine, md->allocate(scope.engine, numAccessors));
for (uint i = 0; i < numAccessors; ++i) {
- d()->mappedArguments->data[i] = context()->callData->args[i];
+ d()->mappedArguments->values.set(scope.engine, i, context()->callData->args[i]);
arraySet(i, scope.engine->argumentsAccessors + i, Attr_Accessor);
}
}
@@ -108,22 +109,22 @@ bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, con
fullyCreate();
Scope scope(engine);
- Property *pd = arrayData() ? arrayData()->getProperty(index) : 0;
ScopedProperty map(scope);
PropertyAttributes mapAttrs;
+ uint numAccessors = qMin(context()->formalParameterCount(), static_cast<uint>(context()->callData->argc));
bool isMapped = false;
- uint numAccessors = qMin((int)context()->formalParameterCount(), context()->callData->argc);
- if (pd && index < (uint)numAccessors)
- isMapped = arrayData()->attributes(index).isAccessor() &&
- pd->getter() == scope.engine->argumentsAccessors[index].getter();
+ if (arrayData() && index < numAccessors &&
+ arrayData()->attributes(index).isAccessor() &&
+ arrayData()->get(index) == scope.engine->argumentsAccessors[index].getter()->asReturnedValue())
+ isMapped = true;
if (isMapped) {
Q_ASSERT(arrayData());
mapAttrs = arrayData()->attributes(index);
- map->copy(pd, mapAttrs);
+ arrayData()->getProperty(index, map, &mapAttrs);
setArrayAttributes(index, Attr_Data);
- pd = arrayData()->getProperty(index);
- pd->value = d()->mappedArguments->data[index];
+ ArrayData::Index arrayIndex{ arrayData(), arrayData()->mappedIndex(index) };
+ arrayIndex.set(scope.engine, d()->mappedArguments->values[index]);
}
bool strict = engine->current->strictMode;
@@ -141,8 +142,7 @@ bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, con
if (attrs.isWritable()) {
setArrayAttributes(index, mapAttrs);
- pd = arrayData()->getProperty(index);
- pd->copy(map, mapAttrs);
+ arrayData()->setProperty(engine, index, map);
}
}
@@ -167,18 +167,17 @@ ReturnedValue ArgumentsObject::getIndexed(const Managed *m, uint index, bool *ha
return Encode::undefined();
}
-void ArgumentsObject::putIndexed(Managed *m, uint index, const Value &value)
+bool ArgumentsObject::putIndexed(Managed *m, uint index, const Value &value)
{
ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
if (!args->fullyCreated() && index >= static_cast<uint>(args->context()->callData->argc))
args->fullyCreate();
- if (args->fullyCreated()) {
- Object::putIndexed(m, index, value);
- return;
- }
+ if (args->fullyCreated())
+ return Object::putIndexed(m, index, value);
args->context()->callData->args[index] = value;
+ return true;
}
bool ArgumentsObject::deleteIndexedProperty(Managed *m, uint index)
@@ -237,17 +236,6 @@ void ArgumentsSetterFunction::call(const Managed *setter, Scope &scope, CallData
scope.result = Encode::undefined();
}
-void ArgumentsObject::markObjects(Heap::Base *that, ExecutionEngine *e)
-{
- ArgumentsObject::Data *o = static_cast<ArgumentsObject::Data *>(that);
- if (o->context)
- o->context->mark(e);
- if (o->mappedArguments)
- o->mappedArguments->mark(e);
-
- Object::markObjects(that, e);
-}
-
uint ArgumentsObject::getLength(const Managed *m)
{
const ArgumentsObject *a = static_cast<const ArgumentsObject *>(m);
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index 0a2ea3b42a..46e1f884e8 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -59,26 +59,35 @@ namespace QV4 {
namespace Heap {
-struct ArgumentsGetterFunction : FunctionObject {
+#define ArgumentsGetterFunctionMembers(class, Member) \
+ Member(class, NoMark, uint, index)
+
+DECLARE_HEAP_OBJECT(ArgumentsGetterFunction, FunctionObject) {
+ DECLARE_MARK_TABLE(ArgumentsGetterFunction);
inline void init(QV4::ExecutionContext *scope, uint index);
- uint index;
};
-struct ArgumentsSetterFunction : FunctionObject {
+#define ArgumentsSetterFunctionMembers(class, Member) \
+ Member(class, NoMark, uint, index)
+
+DECLARE_HEAP_OBJECT(ArgumentsSetterFunction, FunctionObject) {
+ DECLARE_MARK_TABLE(ArgumentsSetterFunction);
inline void init(QV4::ExecutionContext *scope, uint index);
- uint index;
};
-struct ArgumentsObject : Object {
+#define ArgumentsObjectMembers(class, Member) \
+ Member(class, Pointer, CallContext *, context) \
+ Member(class, Pointer, MemberData *, mappedArguments) \
+ Member(class, NoMark, bool, fullyCreated)
+
+DECLARE_HEAP_OBJECT(ArgumentsObject, Object) {
+ DECLARE_MARK_TABLE(ArgumentsObject);
enum {
LengthPropertyIndex = 0,
CalleePropertyIndex = 1,
CallerPropertyIndex = 3
};
void init(QV4::CallContext *context);
- Pointer<CallContext> context;
- bool fullyCreated;
- Pointer<MemberData> mappedArguments;
};
}
@@ -128,10 +137,9 @@ struct ArgumentsObject: Object {
bool defineOwnProperty(ExecutionEngine *engine, uint index, const Property *desc, PropertyAttributes attrs);
static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
- static void putIndexed(Managed *m, uint index, const Value &value);
+ static bool putIndexed(Managed *m, uint index, const Value &value);
static bool deleteIndexedProperty(Managed *m, uint index);
static PropertyAttributes queryIndexed(const Managed *m, uint index);
- static void markObjects(Heap::Base *that, ExecutionEngine *e);
static uint getLength(const Managed *m);
void fullyCreate();
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index 6d1fb62e0a..df9884d84a 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -52,6 +52,7 @@ const QV4::VTable QV4::ArrayData::static_vtbl = {
0,
0,
0,
+ 0,
QV4::ArrayData::IsExecutionContext,
QV4::ArrayData::IsString,
QV4::ArrayData::IsObject,
@@ -130,7 +131,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
if (d->type() < Heap::ArrayData::Sparse) {
offset = d->d()->offset;
- toCopy = d->d()->len;
+ toCopy = d->d()->values.size;
} else {
toCopy = d->alloc();
}
@@ -151,7 +152,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
Heap::SimpleArrayData *n = scope.engine->memoryManager->allocManaged<SimpleArrayData>(size);
n->init();
n->offset = 0;
- n->len = d ? d->d()->len : 0;
+ n->values.size = d ? d->d()->values.size : 0;
newData = n;
} else {
Heap::SparseArrayData *n = scope.engine->memoryManager->allocManaged<SparseArrayData>(size);
@@ -160,7 +161,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
}
newData->setAlloc(alloc);
newData->setType(newType);
- newData->setAttrs(enforceAttributes ? reinterpret_cast<PropertyAttributes *>(newData->d()->arrayData + alloc) : 0);
+ newData->setAttrs(enforceAttributes ? reinterpret_cast<PropertyAttributes *>(newData->d()->values.values + alloc) : 0);
o->setArrayData(newData);
if (d) {
@@ -172,12 +173,14 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
newData->attrs()[i] = Attr_Data;
}
- if (toCopy > d->d()->alloc - offset) {
- uint copyFromStart = toCopy - (d->d()->alloc - offset);
- memcpy(newData->d()->arrayData + toCopy - copyFromStart, d->d()->arrayData, sizeof(Value)*copyFromStart);
+ if (toCopy > d->d()->values.alloc - offset) {
+ uint copyFromStart = toCopy - (d->d()->values.alloc - offset);
+ // no write barrier required here
+ memcpy(newData->d()->values.values + toCopy - copyFromStart, d->d()->values.values, sizeof(Value)*copyFromStart);
toCopy -= copyFromStart;
}
- memcpy(newData->d()->arrayData, d->d()->arrayData + offset, sizeof(Value)*toCopy);
+ // no write barrier required here
+ memcpy(newData->d()->values.values, d->d()->values.values + offset, sizeof(Value)*toCopy);
}
if (newType != Heap::ArrayData::Sparse)
@@ -197,22 +200,22 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
lastFree = &sparse->freeList;
storeValue(lastFree, 0);
for (uint i = 0; i < toCopy; ++i) {
- if (!sparse->arrayData[i].isEmpty()) {
+ if (!sparse->values[i].isEmpty()) {
SparseArrayNode *n = sparse->sparse->insert(i);
n->value = i;
} else {
storeValue(lastFree, i);
- sparse->arrayData[i].setEmpty();
- lastFree = &sparse->arrayData[i].rawValueRef();
+ sparse->values.values[i].setEmpty();
+ lastFree = &sparse->values.values[i].rawValueRef();
}
}
}
- if (toCopy < sparse->alloc) {
- for (uint i = toCopy; i < sparse->alloc; ++i) {
+ if (toCopy < sparse->values.alloc) {
+ for (uint i = toCopy; i < sparse->values.alloc; ++i) {
storeValue(lastFree, i);
- sparse->arrayData[i].setEmpty();
- lastFree = &sparse->arrayData[i].rawValueRef();
+ sparse->values.values[i].setEmpty();
+ lastFree = &sparse->values.values[i].rawValueRef();
}
storeValue(lastFree, UINT_MAX);
}
@@ -235,24 +238,10 @@ void ArrayData::ensureAttributes(Object *o)
ArrayData::realloc(o, Heap::ArrayData::Simple, 0, true);
}
-
-void SimpleArrayData::markObjects(Heap::Base *d, ExecutionEngine *e)
-{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(d);
- uint end = dd->offset + dd->len;
- if (end > dd->alloc) {
- for (uint i = 0; i < end - dd->alloc; ++i)
- dd->arrayData[i].mark(e);
- end = dd->alloc;
- }
- for (uint i = dd->offset; i < end; ++i)
- dd->arrayData[i].mark(e);
-}
-
ReturnedValue SimpleArrayData::get(const Heap::ArrayData *d, uint index)
{
const Heap::SimpleArrayData *dd = static_cast<const Heap::SimpleArrayData *>(d);
- if (index >= dd->len)
+ if (index >= dd->values.size)
return Primitive::emptyValue().asReturnedValue();
return dd->data(index).asReturnedValue();
}
@@ -260,13 +249,13 @@ ReturnedValue SimpleArrayData::get(const Heap::ArrayData *d, uint index)
bool SimpleArrayData::put(Object *o, uint index, const Value &value)
{
Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
- Q_ASSERT(index >= dd->len || !dd->attrs || !dd->attrs[index].isAccessor());
+ Q_ASSERT(index >= dd->values.size || !dd->attrs || !dd->attrs[index].isAccessor());
// ### honour attributes
- dd->data(index) = value;
- if (index >= dd->len) {
+ dd->setData(o->engine(), index, value);
+ if (index >= dd->values.size) {
if (dd->attrs)
dd->attrs[index] = Attr_Data;
- dd->len = index + 1;
+ dd->values.size = index + 1;
}
return true;
}
@@ -274,11 +263,11 @@ bool SimpleArrayData::put(Object *o, uint index, const Value &value)
bool SimpleArrayData::del(Object *o, uint index)
{
Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
- if (index >= dd->len)
+ if (index >= dd->values.size)
return true;
if (!dd->attrs || dd->attrs[index].isConfigurable()) {
- dd->data(index) = Primitive::emptyValue();
+ dd->setData(o->engine(), index, Primitive::emptyValue());
if (dd->attrs)
dd->attrs[index] = Attr_Data;
return true;
@@ -297,8 +286,8 @@ void SimpleArrayData::push_front(Object *o, const Value *values, uint n)
{
Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
Q_ASSERT(!dd->attrs);
- if (dd->len + n > dd->alloc) {
- realloc(o, Heap::ArrayData::Simple, dd->len + n, false);
+ if (dd->values.size + n > dd->values.alloc) {
+ realloc(o, Heap::ArrayData::Simple, dd->values.size + n, false);
Q_ASSERT(o->d()->arrayData->type == Heap::ArrayData::Simple);
dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
@@ -306,70 +295,71 @@ void SimpleArrayData::push_front(Object *o, const Value *values, uint n)
dd->offset -= n; // there is enough space left in front
} else {
// we need to wrap around, so:
- dd->offset = dd->alloc - // start at the back, but subtract:
+ dd->offset = dd->values.alloc - // start at the back, but subtract:
(n - dd->offset); // the number of items we can put in the free space at the start of the allocated array
}
- dd->len += n;
+ dd->values.size += n;
for (uint i = 0; i < n; ++i)
- dd->data(i) = values[i].asReturnedValue();
+ dd->setData(o->engine(), i, values[i]);
}
ReturnedValue SimpleArrayData::pop_front(Object *o)
{
Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
Q_ASSERT(!dd->attrs);
- if (!dd->len)
+ if (!dd->values.size)
return Encode::undefined();
ReturnedValue v = dd->data(0).isEmpty() ? Encode::undefined() : dd->data(0).asReturnedValue();
- dd->offset = (dd->offset + 1) % dd->alloc;
- --dd->len;
+ dd->offset = (dd->offset + 1) % dd->values.alloc;
+ --dd->values.size;
return v;
}
uint SimpleArrayData::truncate(Object *o, uint newLen)
{
Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
- if (dd->len < newLen)
+ if (dd->values.size < newLen)
return newLen;
if (!dd->attrs) {
- dd->len = newLen;
+ dd->values.size = newLen;
return newLen;
}
- while (dd->len > newLen) {
- if (!dd->data(dd->len - 1).isEmpty() && !dd->attrs[dd->len - 1].isConfigurable())
- return dd->len;
- --dd->len;
+ while (dd->values.size > newLen) {
+ if (!dd->data(dd->values.size - 1).isEmpty() && !dd->attrs[dd->values.size - 1].isConfigurable())
+ return dd->values.size;
+ --dd->values.size;
}
- return dd->len;
+ return dd->values.size;
}
uint SimpleArrayData::length(const Heap::ArrayData *d)
{
- return d->len;
+ return d->values.size;
}
bool SimpleArrayData::putArray(Object *o, uint index, const Value *values, uint n)
{
Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
- if (index + n > dd->alloc) {
+ if (index + n > dd->values.alloc) {
reallocate(o, index + n + 1, false);
dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
- for (uint i = dd->len; i < index; ++i)
- dd->data(i) = Primitive::emptyValue();
+ QV4::ExecutionEngine *e = o->engine();
+ for (uint i = dd->values.size; i < index; ++i)
+ dd->setData(e, i, Primitive::emptyValue());
for (uint i = 0; i < n; ++i)
- dd->data(index + i) = values[i];
- dd->len = qMax(dd->len, index + n);
+ dd->setData(e, index + i, values[i]);
+ dd->values.size = qMax(dd->values.size, index + n);
return true;
}
void SparseArrayData::free(Heap::ArrayData *d, uint idx)
{
Q_ASSERT(d && d->type == Heap::ArrayData::Sparse);
- Value *v = d->arrayData + idx;
+ Value *v = d->values.values + idx;
if (d->attrs && d->attrs[idx].isAccessor()) {
// double slot, free both. Order is important, so we have a double slot for allocation again afterwards.
v[1].setEmpty(Value::fromReturnedValue(d->freeList).emptyValue());
@@ -382,15 +372,6 @@ void SparseArrayData::free(Heap::ArrayData *d, uint idx)
d->attrs[idx].clear();
}
-
-void SparseArrayData::markObjects(Heap::Base *d, ExecutionEngine *e)
-{
- Heap::SparseArrayData *dd = static_cast<Heap::SparseArrayData *>(d);
- uint l = dd->alloc;
- for (uint i = 0; i < l; ++i)
- dd->arrayData[i].mark(e);
-}
-
Heap::ArrayData *SparseArrayData::reallocate(Object *o, uint n, bool enforceAttributes)
{
realloc(o, Heap::ArrayData::Sparse, n, enforceAttributes);
@@ -406,32 +387,32 @@ uint SparseArrayData::allocate(Object *o, bool doubleSlot)
ReturnedValue *last = &dd->freeList;
while (1) {
if (Value::fromReturnedValue(*last).value() == UINT_MAX) {
- reallocate(o, dd->alloc + 2, true);
+ reallocate(o, dd->values.alloc + 2, true);
dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
last = &dd->freeList;
Q_ASSERT(Value::fromReturnedValue(*last).value() != UINT_MAX);
}
- Q_ASSERT(dd->arrayData[Value::fromReturnedValue(*last).value()].value() != Value::fromReturnedValue(*last).value());
- if (dd->arrayData[Value::fromReturnedValue(*last).value()].value() == (Value::fromReturnedValue(*last).value() + 1)) {
+ Q_ASSERT(dd->values[Value::fromReturnedValue(*last).value()].value() != Value::fromReturnedValue(*last).value());
+ if (dd->values[Value::fromReturnedValue(*last).value()].value() == (Value::fromReturnedValue(*last).value() + 1)) {
// found two slots in a row
uint idx = Value::fromReturnedValue(*last).emptyValue();
Value lastV = Value::fromReturnedValue(*last);
- lastV.setEmpty(dd->arrayData[lastV.emptyValue() + 1].value());
+ lastV.setEmpty(dd->values[lastV.emptyValue() + 1].value());
*last = lastV.rawValue();
dd->attrs[idx] = Attr_Accessor;
return idx;
}
- last = &dd->arrayData[Value::fromReturnedValue(*last).value()].rawValueRef();
+ last = &dd->values.values[Value::fromReturnedValue(*last).value()].rawValueRef();
}
} else {
if (Value::fromReturnedValue(dd->freeList).value() == UINT_MAX) {
- reallocate(o, dd->alloc + 1, false);
+ reallocate(o, dd->values.alloc + 1, false);
dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
uint idx = Value::fromReturnedValue(dd->freeList).value();
Q_ASSERT(idx != UINT_MAX);
- dd->freeList = dd->arrayData[idx].asReturnedValue();
+ dd->freeList = dd->values[idx].asReturnedValue();
Q_ASSERT(Value::fromReturnedValue(dd->freeList).isEmpty());
if (dd->attrs)
dd->attrs[idx] = Attr_Data;
@@ -445,7 +426,7 @@ ReturnedValue SparseArrayData::get(const Heap::ArrayData *d, uint index)
index = s->mappedIndex(index);
if (index == UINT_MAX)
return Primitive::emptyValue().asReturnedValue();
- return s->arrayData[index].asReturnedValue();
+ return s->values[index].asReturnedValue();
}
bool SparseArrayData::put(Object *o, uint index, const Value &value)
@@ -459,7 +440,7 @@ bool SparseArrayData::put(Object *o, uint index, const Value &value)
if (n->value == UINT_MAX)
n->value = allocate(o);
s = o->d()->arrayData.cast<Heap::SparseArrayData>();
- s->arrayData[n->value] = value;
+ s->setArrayData(o->engine(), n->value, value);
if (s->attrs)
s->attrs[n->value] = Attr_Data;
return true;
@@ -474,7 +455,7 @@ bool SparseArrayData::del(Object *o, uint index)
return true;
uint pidx = n->value;
- Q_ASSERT(!dd->arrayData[pidx].isEmpty());
+ Q_ASSERT(!dd->values[pidx].isEmpty());
bool isAccessor = false;
if (dd->attrs) {
@@ -487,11 +468,11 @@ bool SparseArrayData::del(Object *o, uint index)
if (isAccessor) {
// free up both indices
- dd->arrayData[pidx + 1].setEmpty(Value::fromReturnedValue(dd->freeList).emptyValue());
- dd->arrayData[pidx].setEmpty(pidx + 1);
+ dd->values.values[pidx + 1].setEmpty(Value::fromReturnedValue(dd->freeList).emptyValue());
+ dd->values.values[pidx].setEmpty(pidx + 1);
} else {
Q_ASSERT(dd->type == Heap::ArrayData::Sparse);
- dd->arrayData[pidx].setEmpty(Value::fromReturnedValue(dd->freeList).emptyValue());
+ dd->values.values[pidx].setEmpty(Value::fromReturnedValue(dd->freeList).emptyValue());
}
dd->freeList = Primitive::emptyValue(pidx).asReturnedValue();
@@ -520,10 +501,10 @@ void SparseArrayData::push_front(Object *o, const Value *values, uint n)
{
Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>();
Q_ASSERT(!d->attrs);
- for (int i = n - 1; i >= 0; --i) {
+ for (int i = static_cast<int>(n) - 1; i >= 0; --i) {
uint idx = allocate(o);
d = o->d()->arrayData.cast<Heap::SparseArrayData>();
- d->arrayData[idx] = values[i];
+ d->setArrayData(o->engine(), idx, values[i]);
d->sparse->push_front(idx);
}
}
@@ -535,7 +516,7 @@ ReturnedValue SparseArrayData::pop_front(Object *o)
uint idx = d->sparse->pop_front();
ReturnedValue v;
if (idx != UINT_MAX) {
- v = d->arrayData[idx].asReturnedValue();
+ v = d->values[idx].asReturnedValue();
free(o->arrayData(), idx);
} else {
v = Encode::undefined();
@@ -613,24 +594,24 @@ uint ArrayData::append(Object *obj, ArrayObject *otherObj, uint n)
ScopedValue v(scope);
for (const SparseArrayNode *it = os->sparse->begin();
it != os->sparse->end(); it = it->nextNode()) {
- v = otherObj->getValue(os->arrayData[it->value], other->d()->attrs[it->value]);
+ v = otherObj->getValue(os->values[it->value], other->d()->attrs[it->value]);
obj->arraySet(oldSize + it->key(), v);
}
} else {
for (const SparseArrayNode *it = other->d()->sparse->begin();
it != os->sparse->end(); it = it->nextNode())
- obj->arraySet(oldSize + it->key(), os->arrayData[it->value]);
+ obj->arraySet(oldSize + it->key(), os->values[it->value]);
}
} else {
Heap::SimpleArrayData *os = static_cast<Heap::SimpleArrayData *>(other->d());
uint toCopy = n;
uint chunk = toCopy;
- if (chunk > os->alloc - os->offset)
- chunk -= os->alloc - os->offset;
- obj->arrayPut(oldSize, os->arrayData + os->offset, chunk);
+ if (chunk > os->values.alloc - os->offset)
+ chunk -= os->values.alloc - os->offset;
+ obj->arrayPut(oldSize, os->values.data() + os->offset, chunk);
toCopy -= chunk;
if (toCopy)
- obj->arrayPut(oldSize + chunk, os->arrayData, toCopy);
+ obj->arrayPut(oldSize + chunk, os->values.data(), toCopy);
}
return oldSize + n;
@@ -640,18 +621,18 @@ void ArrayData::insert(Object *o, uint index, const Value *v, bool isAccessor)
{
if (!isAccessor && o->d()->arrayData->type != Heap::ArrayData::Sparse) {
Heap::SimpleArrayData *d = o->d()->arrayData.cast<Heap::SimpleArrayData>();
- if (index < 0x1000 || index < d->len + (d->len >> 2)) {
- if (index >= d->alloc) {
+ if (index < 0x1000 || index < d->values.size + (d->values.size >> 2)) {
+ if (index >= d->values.alloc) {
o->arrayReserve(index + 1);
d = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
- if (index >= d->len) {
+ if (index >= d->values.size) {
// mark possible hole in the array
- for (uint i = d->len; i < index; ++i)
- d->data(i) = Primitive::emptyValue();
- d->len = index + 1;
+ for (uint i = d->values.size; i < index; ++i)
+ d->setData(o->engine(), i, Primitive::emptyValue());
+ d->values.size = index + 1;
}
- d->arrayData[d->mappedIndex(index)] = *v;
+ d->setData(o->engine(), index, *v);
return;
}
}
@@ -662,9 +643,9 @@ void ArrayData::insert(Object *o, uint index, const Value *v, bool isAccessor)
if (n->value == UINT_MAX)
n->value = SparseArrayData::allocate(o, isAccessor);
s = o->d()->arrayData.cast<Heap::SparseArrayData>();
- s->arrayData[n->value] = *v;
+ s->setArrayData(o->engine(), n->value, *v);
if (isAccessor)
- s->arrayData[n->value + Object::SetterOffset] = v[Object::SetterOffset];
+ s->setArrayData(o->engine(), n->value + Object::SetterOffset, v[Object::SetterOffset]);
}
@@ -801,7 +782,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
break;
PropertyAttributes a = sparse->attrs() ? sparse->attrs()[n->value] : Attr_Data;
- d->data(i) = thisObject->getValue(sparse->arrayData()[n->value], a);
+ d->setData(engine, i, Value::fromReturnedValue(thisObject->getValue(sparse->arrayData()[n->value], a)));
d->attrs[i] = a.isAccessor() ? Attr_Data : a;
n = n->nextNode();
@@ -811,12 +792,12 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
while (n != sparse->sparse()->end()) {
if (n->value >= len)
break;
- d->data(i) = sparse->arrayData()[n->value];
+ d->setData(engine, i, sparse->arrayData()[n->value]);
n = n->nextNode();
++i;
}
}
- d->len = i;
+ d->values.size = i;
if (len > i)
len = i;
if (n != sparse->sparse()->end()) {
@@ -824,7 +805,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
thisObject->initSparseArray();
while (n != sparse->sparse()->end()) {
PropertyAttributes a = sparse->attrs() ? sparse->attrs()[n->value] : Attr_Data;
- thisObject->arraySet(n->value, reinterpret_cast<Property *>(sparse->arrayData() + n->value), a);
+ thisObject->arraySet(n->value, reinterpret_cast<const Property *>(sparse->arrayData() + n->value), a);
n = n->nextNode();
}
@@ -832,8 +813,8 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
}
} else {
Heap::SimpleArrayData *d = thisObject->d()->arrayData.cast<Heap::SimpleArrayData>();
- if (len > d->len)
- len = d->len;
+ if (len > d->values.size)
+ len = d->values.size;
// sort empty values to the end
for (uint i = 0; i < len; i++) {
@@ -842,8 +823,8 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
if (!d->data(len).isEmpty())
break;
Q_ASSERT(!d->attrs || !d->attrs[len].isAccessor());
- d->data(i) = d->data(len);
- d->data(len) = Primitive::emptyValue();
+ d->setData(engine, i, d->data(len));
+ d->setData(engine, len, Primitive::emptyValue());
}
}
@@ -854,7 +835,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
ArrayElementLessThan lessThan(engine, thisObject, comparefn);
- Value *begin = thisObject->arrayData()->arrayData;
+ Value *begin = thisObject->arrayData()->values.values;
sortHelper(begin, begin + len, *begin, lessThan);
#ifdef CHECK_SPARSE_ARRAYS
diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h
index daf8c36814..e1de2e82e6 100644
--- a/src/qml/jsruntime/qv4arraydata_p.h
+++ b/src/qml/jsruntime/qv4arraydata_p.h
@@ -90,27 +90,31 @@ struct ArrayVTable
namespace Heap {
-struct ArrayData : public Base {
- enum Type {
- Simple = 0,
- Complex = 1,
- Sparse = 2,
- Custom = 3
+#define ArrayDataMembers(class, Member) \
+ Member(class, NoMark, uint, type) \
+ Member(class, NoMark, uint, offset) \
+ Member(class, NoMark, PropertyAttributes *, attrs) \
+ Member(class, NoMark, ReturnedValue, freeList) \
+ Member(class, NoMark, SparseArray *, sparse) \
+ Member(class, ValueArray, ValueArray, values)
+
+DECLARE_HEAP_OBJECT(ArrayData, Base) {
+ DECLARE_MARK_TABLE(ArrayData);
+
+ enum Type { Simple = 0, Complex = 1, Sparse = 2, Custom = 3 };
+
+ struct Index {
+ Heap::ArrayData *arrayData;
+ uint index;
+
+ void set(EngineBase *e, Value newVal) {
+ arrayData->values.set(e, index, newVal);
+ }
+ const Value *operator->() const { return &arrayData->values[index]; }
+ const Value &operator*() const { return arrayData->values[index]; }
+ bool isNull() const { return !arrayData; }
};
- uint alloc;
- Type type;
- PropertyAttributes *attrs;
- union {
- uint len;
- ReturnedValue freeList;
- };
- union {
- uint offset;
- SparseArray *sparse;
- };
- Value arrayData[1];
-
bool isSparse() const { return type == Sparse; }
const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(Base::vtable()); }
@@ -118,35 +122,32 @@ struct ArrayData : public Base {
inline ReturnedValue get(uint i) const {
return vtable()->get(this, i);
}
- inline void getProperty(uint index, Property *p, PropertyAttributes *attrs);
- inline void setProperty(uint index, const Property *p);
- inline Property *getProperty(uint index);
- inline Value *getValueOrSetter(uint index, PropertyAttributes *attrs);
+ inline bool getProperty(uint index, Property *p, PropertyAttributes *attrs);
+ inline void setProperty(EngineBase *e, uint index, const Property *p);
+ inline Index getValueOrSetter(uint index, PropertyAttributes *attrs);
inline PropertyAttributes attributes(uint i) const;
bool isEmpty(uint i) const {
return get(i) == Primitive::emptyValue().asReturnedValue();
}
- inline ReturnedValue length() const {
+ inline uint length() const {
return vtable()->length(this);
}
+ void setArrayData(EngineBase *e, uint index, Value newVal) {
+ values.set(e, index, newVal);
+ }
+
+ uint mappedIndex(uint index) const;
};
V4_ASSERT_IS_TRIVIAL(ArrayData)
struct SimpleArrayData : public ArrayData {
- uint mappedIndex(uint index) const { return (index + offset) % alloc; }
- Value data(uint index) const { return arrayData[mappedIndex(index)]; }
- Value &data(uint index) { return arrayData[mappedIndex(index)]; }
-
- Property *getProperty(uint index) {
- if (index >= len)
- return 0;
- index = mappedIndex(index);
- if (arrayData[index].isEmpty())
- return 0;
- return reinterpret_cast<Property *>(arrayData + index);
+ uint mappedIndex(uint index) const { return (index + offset) % values.alloc; }
+ const Value &data(uint index) const { return values[mappedIndex(index)]; }
+ void setData(EngineBase *e, uint index, Value newVal) {
+ values.set(e, mappedIndex(index), newVal);
}
PropertyAttributes attributes(uint i) const {
@@ -168,13 +169,6 @@ struct SparseArrayData : public ArrayData {
return n->value;
}
- Property *getProperty(uint index) {
- SparseArrayNode *n = sparse->findNode(index);
- if (!n)
- return 0;
- return reinterpret_cast<Property *>(arrayData + n->value);
- }
-
PropertyAttributes attributes(uint i) const {
if (!attrs)
return Attr_Data;
@@ -189,16 +183,23 @@ struct Q_QML_EXPORT ArrayData : public Managed
{
typedef Heap::ArrayData::Type Type;
V4_MANAGED(ArrayData, Managed)
+ enum {
+ IsArrayData = true
+ };
- uint alloc() const { return d()->alloc; }
- uint &alloc() { return d()->alloc; }
- void setAlloc(uint a) { d()->alloc = a; }
- Type type() const { return d()->type; }
+ typedef Heap::ArrayData::Index Index;
+
+ uint alloc() const { return d()->values.alloc; }
+ uint &alloc() { return d()->values.alloc; }
+ void setAlloc(uint a) { d()->values.alloc = a; }
+ Type type() const { return static_cast<Type>(d()->type); }
void setType(Type t) { d()->type = t; }
PropertyAttributes *attrs() const { return d()->attrs; }
void setAttrs(PropertyAttributes *a) { d()->attrs = a; }
- const Value *arrayData() const { return &d()->arrayData[0]; }
- Value *arrayData() { return &d()->arrayData[0]; }
+ const Value *arrayData() const { return d()->values.data(); }
+ void setArrayData(EngineBase *e, uint index, Value newVal) {
+ d()->setArrayData(e, index, newVal);
+ }
const ArrayVTable *vtable() const { return d()->vtable(); }
bool isSparse() const { return type() == Heap::ArrayData::Sparse; }
@@ -221,9 +222,6 @@ struct Q_QML_EXPORT ArrayData : public Managed
ReturnedValue get(uint i) const {
return d()->get(i);
}
- inline Property *getProperty(uint index) {
- return d()->getProperty(index);
- }
static void ensureAttributes(Object *o);
static void realloc(Object *o, Type newType, uint alloc, bool enforceAttributes);
@@ -240,15 +238,12 @@ struct Q_QML_EXPORT SimpleArrayData : public ArrayData
uint mappedIndex(uint index) const { return d()->mappedIndex(index); }
Value data(uint index) const { return d()->data(index); }
- Value &data(uint index) { return d()->data(index); }
- uint &len() { return d()->len; }
- uint len() const { return d()->len; }
+ uint &len() { return d()->values.size; }
+ uint len() const { return d()->values.size; }
static Heap::ArrayData *reallocate(Object *o, uint n, bool enforceAttributes);
- static void markObjects(Heap::Base *d, ExecutionEngine *e);
-
static ReturnedValue get(const Heap::ArrayData *d, uint index);
static bool put(Object *o, uint index, const Value &value);
static bool putArray(Object *o, uint index, const Value *values, uint n);
@@ -276,8 +271,6 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData
uint mappedIndex(uint index) const { return d()->mappedIndex(index); }
- static void markObjects(Heap::Base *d, ExecutionEngine *e);
-
static Heap::ArrayData *reallocate(Object *o, uint n, bool enforceAttributes);
static ReturnedValue get(const Heap::ArrayData *d, uint index);
static bool put(Object *o, uint index, const Value &value);
@@ -292,30 +285,38 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData
namespace Heap {
-void ArrayData::getProperty(uint index, Property *p, PropertyAttributes *attrs)
+inline uint ArrayData::mappedIndex(uint index) const
{
- Property *pd = getProperty(index);
- Q_ASSERT(pd);
- *attrs = attributes(index);
- p->value = pd->value;
- if (attrs->isAccessor())
- p->set = pd->set;
+ if (isSparse())
+ return static_cast<const SparseArrayData *>(this)->mappedIndex(index);
+ if (index >= values.size)
+ return UINT_MAX;
+ uint idx = static_cast<const SimpleArrayData *>(this)->mappedIndex(index);
+ return values[idx].isEmpty() ? UINT_MAX : idx;
}
-void ArrayData::setProperty(uint index, const Property *p)
+bool ArrayData::getProperty(uint index, Property *p, PropertyAttributes *attrs)
{
- Property *pd = getProperty(index);
- Q_ASSERT(pd);
- pd->value = p->value;
- if (attributes(index).isAccessor())
- pd->set = p->set;
+ uint mapped = mappedIndex(index);
+ if (mapped == UINT_MAX) {
+ *attrs = Attr_Invalid;
+ return false;
+ }
+
+ *attrs = attributes(index);
+ p->value = *(Index{ this, mapped });
+ if (attrs->isAccessor())
+ p->set = *(Index{ this, mapped + 1 /*Object::SetterOffset*/ });
+ return true;
}
-inline Property *ArrayData::getProperty(uint index)
+void ArrayData::setProperty(QV4::EngineBase *e, uint index, const Property *p)
{
- if (isSparse())
- return static_cast<SparseArrayData *>(this)->getProperty(index);
- return static_cast<SimpleArrayData *>(this)->getProperty(index);
+ uint mapped = mappedIndex(index);
+ Q_ASSERT(mapped != UINT_MAX);
+ values.set(e, mapped, p->value);
+ if (attributes(index).isAccessor())
+ values.set(e, mapped + 1 /*QV4::Object::SetterOffset*/, p->set);
}
inline PropertyAttributes ArrayData::attributes(uint i) const
@@ -325,16 +326,16 @@ inline PropertyAttributes ArrayData::attributes(uint i) const
return static_cast<const SimpleArrayData *>(this)->attributes(i);
}
-Value *ArrayData::getValueOrSetter(uint index, PropertyAttributes *attrs)
+ArrayData::Index ArrayData::getValueOrSetter(uint index, PropertyAttributes *attrs)
{
- Property *p = getProperty(index);
- if (!p) {
+ uint idx = mappedIndex(index);
+ if (idx == UINT_MAX) {
*attrs = Attr_Invalid;
- return 0;
+ return { 0, 0 };
}
*attrs = attributes(index);
- return attrs->isAccessor() ? &p->set : &p->value;
+ return { this, attrs->isAccessor() ? idx + 1 /* QV4::Object::SetterOffset*/ : idx };
}
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 759354f4e2..a2c19e1f2d 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -690,8 +690,8 @@ void ArrayPrototype::method_indexOf(const BuiltinFunction *, Scope &scope, CallD
} else {
Q_ASSERT(instance->arrayType() == Heap::ArrayData::Simple || instance->arrayType() == Heap::ArrayData::Complex);
Heap::SimpleArrayData *sa = instance->d()->arrayData.cast<Heap::SimpleArrayData>();
- if (len > sa->len)
- len = sa->len;
+ if (len > sa->values.size)
+ len = sa->values.size;
uint idx = fromIndex;
while (idx < len) {
value = sa->data(idx);
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 3ff864d7b9..6807c835b0 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -54,41 +54,44 @@
using namespace QV4;
DEFINE_MANAGED_VTABLE(ExecutionContext);
+DEFINE_MANAGED_VTABLE(SimpleCallContext);
DEFINE_MANAGED_VTABLE(CallContext);
DEFINE_MANAGED_VTABLE(WithContext);
DEFINE_MANAGED_VTABLE(CatchContext);
DEFINE_MANAGED_VTABLE(GlobalContext);
-/* Function *f, int argc */
-#define requiredMemoryForExecutionContect(f, argc) \
- ((sizeof(CallContext::Data) + 7) & ~7) + \
- sizeof(Value) * (f->compiledFunction->nLocals + qMax((uint)argc, f->nFormals)) + sizeof(CallData)
-
Heap::CallContext *ExecutionContext::newCallContext(Function *function, CallData *callData)
{
- Heap::CallContext *c = engine()->memoryManager->allocManaged<CallContext>(
- requiredMemoryForExecutionContect(function, callData->argc));
+ uint localsAndFormals = function->compiledFunction->nLocals + sizeof(CallData)/sizeof(Value) - 1 + qMax(static_cast<uint>(callData->argc), function->nFormals);
+ size_t requiredMemory = sizeof(CallContext::Data) - sizeof(Value) + sizeof(Value) * (localsAndFormals);
+
+ ExecutionEngine *v4 = engine();
+ Heap::CallContext *c = v4->memoryManager->allocManaged<CallContext>(requiredMemory);
c->init(Heap::ExecutionContext::Type_CallContext);
c->v4Function = function;
c->strictMode = function->isStrict();
- c->outer = this->d();
-
- c->activation = 0;
+ c->outer.set(v4, this->d());
c->compilationUnit = function->compilationUnit;
c->lookups = function->compilationUnit->runtimeLookups;
c->constantTable = function->compilationUnit->constants;
- c->locals = (Value *)((quintptr(c + 1) + 7) & ~7);
const CompiledData::Function *compiledFunction = function->compiledFunction;
- int nLocals = compiledFunction->nLocals;
+ uint nLocals = compiledFunction->nLocals;
+ c->locals.size = nLocals;
+ c->locals.alloc = localsAndFormals;
+#if QT_POINTER_SIZE == 8
+ // memory allocated from the JS heap is 0 initialized, so skip the std::fill() below
+ Q_ASSERT(Primitive::undefinedValue().asReturnedValue() == 0);
+#else
if (nLocals)
- std::fill(c->locals, c->locals + nLocals, Primitive::undefinedValue());
+ std::fill(c->locals.values, c->locals.values + nLocals, Primitive::undefinedValue());
+#endif
- c->callData = reinterpret_cast<CallData *>(c->locals + nLocals);
- ::memcpy(c->callData, callData, sizeof(CallData) + (callData->argc - 1) * sizeof(Value));
+ c->callData = reinterpret_cast<CallData *>(c->locals.values + nLocals);
+ ::memcpy(c->callData, callData, sizeof(CallData) - sizeof(Value) + static_cast<uint>(callData->argc) * sizeof(Value));
if (callData->argc < static_cast<int>(compiledFunction->nFormals))
std::fill(c->callData->args + c->callData->argc, c->callData->args + compiledFunction->nFormals, Primitive::undefinedValue());
@@ -118,10 +121,10 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable)
switch (ctx->d()->type) {
case Heap::ExecutionContext::Type_CallContext:
case Heap::ExecutionContext::Type_SimpleCallContext: {
- Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
+ Heap::SimpleCallContext *c = static_cast<Heap::SimpleCallContext *>(ctx->d());
if (!activation) {
if (!c->activation)
- c->activation = scope.engine->newObject();
+ c->activation.set(scope.engine, scope.engine->newObject());
activation = c->activation;
}
break;
@@ -144,7 +147,7 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable)
ctx = ctx->d()->outer;
}
- if (activation->hasProperty(name))
+ if (activation->hasOwnProperty(name))
return;
ScopedProperty desc(scope);
PropertyAttributes attrs(Attr_Data);
@@ -155,41 +158,52 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable)
void Heap::GlobalContext::init(ExecutionEngine *eng)
{
Heap::ExecutionContext::init(Heap::ExecutionContext::Type_GlobalContext);
- global = eng->globalObject->d();
+ global.set(eng, eng->globalObject->d());
}
void Heap::CatchContext::init(ExecutionContext *outerContext, String *exceptionVarName,
const Value &exceptionValue)
{
Heap::ExecutionContext::init(Heap::ExecutionContext::Type_CatchContext);
- outer = outerContext;
+ outer.set(internalClass->engine, outerContext);
strictMode = outer->strictMode;
callData = outer->callData;
lookups = outer->lookups;
constantTable = outer->constantTable;
compilationUnit = outer->compilationUnit;
- this->exceptionVarName = exceptionVarName;
- this->exceptionValue = exceptionValue;
+ this->exceptionVarName.set(internalClass->engine, exceptionVarName);
+ this->exceptionValue.set(internalClass->engine, exceptionValue);
}
+void Heap::WithContext::init(ExecutionContext *outerContext, Object *with)
+{
+ Heap::ExecutionContext::init(Heap::ExecutionContext::Type_WithContext);
+ outer.set(internalClass->engine, outerContext);
+ callData = outer->callData;
+ lookups = outer->lookups;
+ constantTable = outer->constantTable;
+ compilationUnit = outer->compilationUnit;
-Identifier * const *CallContext::formals() const
+ withObject.set(internalClass->engine, with);
+}
+
+Identifier * const *SimpleCallContext::formals() const
{
return d()->v4Function ? d()->v4Function->internalClass->nameMap.constData() : 0;
}
-unsigned int CallContext::formalCount() const
+unsigned int SimpleCallContext::formalCount() const
{
return d()->v4Function ? d()->v4Function->nFormals : 0;
}
-Identifier * const *CallContext::variables() const
+Identifier * const *SimpleCallContext::variables() const
{
return d()->v4Function ? d()->v4Function->internalClass->nameMap.constData() + d()->v4Function->nFormals : 0;
}
-unsigned int CallContext::variableCount() const
+unsigned int SimpleCallContext::variableCount() const
{
return d()->v4Function ? d()->v4Function->compiledFunction->nLocals : 0;
}
@@ -202,7 +216,6 @@ bool ExecutionContext::deleteProperty(String *name)
Identifier *id = name->identifier();
Scope scope(this);
- bool hasWith = false;
ScopedContext ctx(scope, this);
for (; ctx; ctx = ctx->d()->outer) {
switch (ctx->d()->type) {
@@ -213,7 +226,6 @@ bool ExecutionContext::deleteProperty(String *name)
break;
}
case Heap::ExecutionContext::Type_WithContext: {
- hasWith = true;
ScopedObject withObject(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
if (withObject->hasProperty(name))
return withObject->deleteProperty(name);
@@ -226,14 +238,13 @@ bool ExecutionContext::deleteProperty(String *name)
break;
}
case Heap::ExecutionContext::Type_CallContext:
+ Q_FALLTHROUGH();
case Heap::ExecutionContext::Type_SimpleCallContext: {
- Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
- if (c->v4Function && (c->v4Function->needsActivation() || hasWith)) {
- uint index = c->v4Function->internalClass->find(id);
- if (index < UINT_MAX)
- // ### throw in strict mode?
- return false;
- }
+ Heap::SimpleCallContext *c = static_cast<Heap::SimpleCallContext *>(ctx->d());
+ uint index = c->v4Function->internalClass->find(id);
+ if (index < UINT_MAX)
+ // ### throw in strict mode?
+ return false;
ScopedObject qml(scope, c->activation);
if (qml && qml->hasProperty(name))
return qml->deleteProperty(name);
@@ -250,61 +261,6 @@ bool ExecutionContext::deleteProperty(String *name)
return true;
}
-bool CallContext::needsOwnArguments() const
-{
- QV4::Function *f = d()->v4Function;
- return (f && f->needsActivation()) || (argc() < (f ? static_cast<int>(f->nFormals) : 0));
-}
-
-void ExecutionContext::markObjects(Heap::Base *m, ExecutionEngine *engine)
-{
- ExecutionContext::Data *ctx = static_cast<ExecutionContext::Data *>(m);
-
- if (ctx->outer)
- ctx->outer->mark(engine);
-
- switch (ctx->type) {
- case Heap::ExecutionContext::Type_CatchContext: {
- CatchContext::Data *c = static_cast<CatchContext::Data *>(ctx);
- c->exceptionVarName->mark(engine);
- c->exceptionValue.mark(engine);
- break;
- }
- case Heap::ExecutionContext::Type_WithContext: {
- WithContext::Data *w = static_cast<WithContext::Data *>(ctx);
- if (w->withObject)
- w->withObject->mark(engine);
- break;
- }
- case Heap::ExecutionContext::Type_GlobalContext: {
- GlobalContext::Data *g = static_cast<GlobalContext::Data *>(ctx);
- g->global->mark(engine);
- break;
- }
- case Heap::ExecutionContext::Type_SimpleCallContext:
- break;
- case Heap::ExecutionContext::Type_CallContext: {
- QV4::Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx);
- Q_ASSERT(c->v4Function);
- ctx->callData->thisObject.mark(engine);
- for (int arg = 0; arg < qMax(ctx->callData->argc, (int)c->v4Function->nFormals); ++arg)
- ctx->callData->args[arg].mark(engine);
- for (unsigned local = 0, lastLocal = c->v4Function->compiledFunction->nLocals; local < lastLocal; ++local)
- c->locals[local].mark(engine);
- if (c->activation)
- c->activation->mark(engine);
- if (c->function)
- c->function->mark(engine);
- break;
- }
- case Heap::ExecutionContext::Type_QmlContext: {
- QmlContext::Data *g = static_cast<QmlContext::Data *>(ctx);
- g->qml->mark(engine);
- break;
- }
- }
-}
-
// Do a standard call with this execution context as the outer scope
void ExecutionContext::call(Scope &scope, CallData *callData, Function *function, const FunctionObject *f)
{
@@ -312,7 +268,7 @@ void ExecutionContext::call(Scope &scope, CallData *callData, Function *function
Scoped<CallContext> ctx(scope, newCallContext(function, callData));
if (f)
- ctx->d()->function = f->d();
+ ctx->d()->function.set(scope.engine, f->d());
scope.engine->pushContext(ctx);
scope.result = Q_V4_PROFILE(scope.engine, function);
@@ -328,7 +284,7 @@ void QV4::ExecutionContext::simpleCall(Scope &scope, CallData *callData, Functio
ExecutionContextSaver ctxSaver(scope);
- CallContext::Data *ctx = scope.engine->memoryManager->allocSimpleCallContext();
+ SimpleCallContext::Data *ctx = scope.engine->memoryManager->allocSimpleCallContext();
ctx->strictMode = function->isStrict();
ctx->callData = callData;
@@ -336,8 +292,7 @@ void QV4::ExecutionContext::simpleCall(Scope &scope, CallData *callData, Functio
ctx->compilationUnit = function->compilationUnit;
ctx->lookups = function->compilationUnit->runtimeLookups;
ctx->constantTable = function->compilationUnit->constants;
- ctx->outer = this->d();
- ctx->locals = scope.alloc(function->compiledFunction->nLocals);
+ ctx->outer.set(scope.engine, this->d());
for (int i = callData->argc; i < (int)function->nFormals; ++i)
callData->args[i] = Encode::undefined();
@@ -366,7 +321,7 @@ void ExecutionContext::setProperty(String *name, const Value &value)
case Heap::ExecutionContext::Type_CatchContext: {
Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
if (c->exceptionVarName->isEqualTo(name->d())) {
- c->exceptionValue = value;
+ c->exceptionValue.set(scope.engine, value);
return;
}
break;
@@ -385,15 +340,16 @@ void ExecutionContext::setProperty(String *name, const Value &value)
}
case Heap::ExecutionContext::Type_CallContext:
case Heap::ExecutionContext::Type_SimpleCallContext: {
- Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
+ Heap::SimpleCallContext *c = static_cast<Heap::SimpleCallContext *>(ctx->d());
if (c->v4Function) {
uint index = c->v4Function->internalClass->find(id);
if (index < UINT_MAX) {
if (index < c->v4Function->nFormals) {
c->callData->args[c->v4Function->nFormals - index - 1] = value;
} else {
+ Q_ASSERT(c->type == Heap::ExecutionContext::Type_CallContext);
index -= c->v4Function->nFormals;
- c->locals[index] = value;
+ static_cast<Heap::CallContext *>(c)->locals.set(scope.engine, index, value);
}
return;
}
@@ -434,13 +390,10 @@ ReturnedValue ExecutionContext::getProperty(String *name)
if (name->equals(engine()->id_this()))
return thisObject().asReturnedValue();
- bool hasWith = false;
- bool hasCatchScope = false;
ScopedContext ctx(scope, this);
for (; ctx; ctx = ctx->d()->outer) {
switch (ctx->d()->type) {
case Heap::ExecutionContext::Type_CatchContext: {
- hasCatchScope = true;
Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
if (c->exceptionVarName->isEqualTo(name->d()))
return c->exceptionValue.asReturnedValue();
@@ -448,7 +401,6 @@ ReturnedValue ExecutionContext::getProperty(String *name)
}
case Heap::ExecutionContext::Type_WithContext: {
ScopedObject w(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
- hasWith = true;
bool hasProperty = false;
v = w->get(name, &hasProperty);
if (hasProperty) {
@@ -465,19 +417,20 @@ ReturnedValue ExecutionContext::getProperty(String *name)
break;
}
case Heap::ExecutionContext::Type_CallContext:
+ Q_FALLTHROUGH();
case Heap::ExecutionContext::Type_SimpleCallContext: {
- Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
- if (c->v4Function && (c->v4Function->needsActivation() || hasWith || hasCatchScope)) {
- name->makeIdentifier();
- Identifier *id = name->identifier();
-
- uint index = c->v4Function->internalClass->find(id);
- if (index < UINT_MAX) {
- if (index < c->v4Function->nFormals)
- return c->callData->args[c->v4Function->nFormals - index - 1].asReturnedValue();
- return c->locals[index - c->v4Function->nFormals].asReturnedValue();
- }
+ Heap::SimpleCallContext *c = static_cast<Heap::SimpleCallContext *>(ctx->d());
+
+ name->makeIdentifier();
+ Identifier *id = name->identifier();
+ uint index = c->v4Function->internalClass->find(id);
+ if (index < UINT_MAX) {
+ if (index < c->v4Function->nFormals)
+ return c->callData->args[c->v4Function->nFormals - index - 1].asReturnedValue();
+ if (c->type == Heap::ExecutionContext::Type_CallContext)
+ return static_cast<Heap::CallContext *>(c)->locals[index - c->v4Function->nFormals].asReturnedValue();
}
+
ScopedObject activation(scope, c->activation);
if (activation) {
bool hasProperty = false;
@@ -485,9 +438,12 @@ ReturnedValue ExecutionContext::getProperty(String *name)
if (hasProperty)
return v->asReturnedValue();
}
- if (c->function && c->v4Function->isNamedExpression()
- && name->equals(ScopedString(scope, c->v4Function->name())))
- return c->function->asReturnedValue();
+
+ if (c->v4Function->isNamedExpression() && c->type == Heap::ExecutionContext::Type_CallContext) {
+ if (name->equals(ScopedString(scope, c->v4Function->name())))
+ if (auto func = static_cast<Heap::CallContext *>(c)->function)
+ return func->asReturnedValue();
+ }
break;
}
case Heap::ExecutionContext::Type_QmlContext: {
@@ -514,13 +470,10 @@ ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Value *base)
if (name->equals(engine()->id_this()))
return thisObject().asReturnedValue();
- bool hasWith = false;
- bool hasCatchScope = false;
ScopedContext ctx(scope, this);
for (; ctx; ctx = ctx->d()->outer) {
switch (ctx->d()->type) {
case Heap::ExecutionContext::Type_CatchContext: {
- hasCatchScope = true;
Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
if (c->exceptionVarName->isEqualTo(name->d()))
return c->exceptionValue.asReturnedValue();
@@ -528,7 +481,6 @@ ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Value *base)
}
case Heap::ExecutionContext::Type_WithContext: {
ScopedObject w(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
- hasWith = true;
bool hasProperty = false;
v = w->get(name, &hasProperty);
if (hasProperty) {
@@ -546,19 +498,20 @@ ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Value *base)
break;
}
case Heap::ExecutionContext::Type_CallContext:
+ Q_FALLTHROUGH();
case Heap::ExecutionContext::Type_SimpleCallContext: {
- Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
- if (c->v4Function && (c->v4Function->needsActivation() || hasWith || hasCatchScope)) {
- name->makeIdentifier();
- Identifier *id = name->identifier();
-
- uint index = c->v4Function->internalClass->find(id);
- if (index < UINT_MAX) {
- if (index < c->v4Function->nFormals)
- return c->callData->args[c->v4Function->nFormals - index - 1].asReturnedValue();
- return c->locals[index - c->v4Function->nFormals].asReturnedValue();
- }
+ Heap::SimpleCallContext *c = static_cast<Heap::SimpleCallContext *>(ctx->d());
+
+ name->makeIdentifier();
+ Identifier *id = name->identifier();
+ uint index = c->v4Function->internalClass->find(id);
+ if (index < UINT_MAX) {
+ if (index < c->v4Function->nFormals)
+ return c->callData->args[c->v4Function->nFormals - index - 1].asReturnedValue();
+ if (c->type == Heap::ExecutionContext::Type_CallContext)
+ return static_cast<Heap::CallContext *>(c)->locals[index - c->v4Function->nFormals].asReturnedValue();
}
+
ScopedObject activation(scope, c->activation);
if (activation) {
bool hasProperty = false;
@@ -566,9 +519,12 @@ ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Value *base)
if (hasProperty)
return v->asReturnedValue();
}
- if (c->function && c->v4Function->isNamedExpression()
- && name->equals(ScopedString(scope, c->v4Function->name())))
- return c->function->asReturnedValue();
+
+ if (c->v4Function->isNamedExpression() && c->type == Heap::ExecutionContext::Type_CallContext) {
+ if (name->equals(ScopedString(scope, c->v4Function->name())))
+ if (auto func = static_cast<Heap::CallContext *>(c)->function)
+ return func->asReturnedValue();
+ }
break;
}
case Heap::ExecutionContext::Type_QmlContext: {
@@ -592,7 +548,7 @@ Function *ExecutionContext::getFunction() const
Scope scope(engine());
ScopedContext it(scope, this->d());
for (; it; it = it->d()->outer) {
- if (const CallContext *callCtx = it->asCallContext())
+ if (const SimpleCallContext *callCtx = it->asSimpleCallContext())
return callCtx->d()->v4Function;
else if (it->asCatchContext() || it->asWithContext())
continue; // look in the parent context for a FunctionObject
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 0b63922a4b..a854c324d0 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -68,10 +68,11 @@ struct Function;
struct Function;
struct Identifier;
struct CallContext;
+struct SimpleCallContext;
struct CatchContext;
struct WithContext;
struct QmlContext;
-struct QmlContextWrapper;
+struct QQmlContextWrapper;
// Attention: Make sure that this structure is the same size on 32-bit and 64-bit
// architecture or you'll have to change the JIT code.
@@ -101,34 +102,17 @@ namespace Heap {
struct QmlContext;
-// ### Temporary arrangment until this code hits the dev branch and
-// can use the Members macro
-struct ExecutionContextData {
- CallData *callData;
- ExecutionContext *outer;
- Lookup *lookups;
- const QV4::Value *constantTable;
- CompiledData::CompilationUnitBase *compilationUnit;
- // as member of non-pointer size this has to come last to preserve the ability to
- // translate offsetof of it between 64-bit and 32-bit.
- int lineNumber;
-#if QT_POINTER_SIZE == 8
- uint padding_;
-#endif
-};
-
-Q_STATIC_ASSERT(std::is_standard_layout<ExecutionContextData>::value);
-Q_STATIC_ASSERT(offsetof(ExecutionContextData, callData) == 0);
-Q_STATIC_ASSERT(offsetof(ExecutionContextData, outer) == offsetof(ExecutionContextData, callData) + QT_POINTER_SIZE);
-Q_STATIC_ASSERT(offsetof(ExecutionContextData, lookups) == offsetof(ExecutionContextData, outer) + QT_POINTER_SIZE);
-Q_STATIC_ASSERT(offsetof(ExecutionContextData, constantTable) == offsetof(ExecutionContextData, lookups) + QT_POINTER_SIZE);
-Q_STATIC_ASSERT(offsetof(ExecutionContextData, compilationUnit) == offsetof(ExecutionContextData, constantTable) + QT_POINTER_SIZE);
-Q_STATIC_ASSERT(offsetof(ExecutionContextData, lineNumber) == offsetof(ExecutionContextData, compilationUnit) + QT_POINTER_SIZE);
+#define ExecutionContextMembers(class, Member) \
+ Member(class, NoMark, CallData *, callData) \
+ Member(class, Pointer, ExecutionContext *, outer) \
+ Member(class, NoMark, Lookup *, lookups) \
+ Member(class, NoMark, const QV4::Value *, constantTable) \
+ Member(class, NoMark, CompiledData::CompilationUnitBase *, compilationUnit) \
+ Member(class, NoMark, int, lineNumber) // as member of non-pointer size this has to come last to preserve the ability to
+ // translate offsetof of it between 64-bit and 32-bit.
-struct ExecutionContextSizeStruct : public Base, public ExecutionContextData {};
-
-struct ExecutionContext : Base, public ExecutionContextData {
- static Q_CONSTEXPR size_t baseOffset = sizeof(ExecutionContextSizeStruct) - sizeof(ExecutionContextData);
+DECLARE_HEAP_OBJECT(ExecutionContext, Base) {
+ DECLARE_MARK_TABLE(ExecutionContext);
enum ContextType {
Type_GlobalContext = 0x1,
@@ -158,17 +142,20 @@ struct ExecutionContext : Base, public ExecutionContextData {
V4_ASSERT_IS_TRIVIAL(ExecutionContext)
Q_STATIC_ASSERT(sizeof(ExecutionContext) == sizeof(Base) + sizeof(ExecutionContextData) + QT_POINTER_SIZE);
-struct CallContextData {
- Value *locals;
-};
-
-Q_STATIC_ASSERT(std::is_standard_layout<CallContextData>::value);
-Q_STATIC_ASSERT(offsetof(CallContextData, locals) == 0);
+Q_STATIC_ASSERT(std::is_standard_layout<ExecutionContextData>::value);
+Q_STATIC_ASSERT(offsetof(ExecutionContextData, callData) == 0);
+Q_STATIC_ASSERT(offsetof(ExecutionContextData, outer) == offsetof(ExecutionContextData, callData) + QT_POINTER_SIZE);
+Q_STATIC_ASSERT(offsetof(ExecutionContextData, lookups) == offsetof(ExecutionContextData, outer) + QT_POINTER_SIZE);
+Q_STATIC_ASSERT(offsetof(ExecutionContextData, constantTable) == offsetof(ExecutionContextData, lookups) + QT_POINTER_SIZE);
+Q_STATIC_ASSERT(offsetof(ExecutionContextData, compilationUnit) == offsetof(ExecutionContextData, constantTable) + QT_POINTER_SIZE);
+Q_STATIC_ASSERT(offsetof(ExecutionContextData, lineNumber) == offsetof(ExecutionContextData, compilationUnit) + QT_POINTER_SIZE);
-struct CallContextSizeStruct : public ExecutionContext, public CallContextData {};
+#define SimpleCallContextMembers(class, Member) \
+ Member(class, Pointer, Object *, activation) \
+ Member(class, NoMark, QV4::Function *, v4Function)
-struct CallContext : ExecutionContext, public CallContextData {
- static Q_CONSTEXPR size_t baseOffset = sizeof(CallContextSizeStruct) - sizeof(CallContextData);
+DECLARE_HEAP_OBJECT(SimpleCallContext, ExecutionContext) {
+ DECLARE_MARK_TABLE(SimpleCallContext);
void init(ContextType t = Type_SimpleCallContext)
{
@@ -177,39 +164,66 @@ struct CallContext : ExecutionContext, public CallContextData {
inline unsigned int formalParameterCount() const;
- Pointer<FunctionObject> function;
- QV4::Function *v4Function;
- Pointer<Object> activation;
};
-V4_ASSERT_IS_TRIVIAL(CallContext)
+V4_ASSERT_IS_TRIVIAL(SimpleCallContext)
+Q_STATIC_ASSERT(std::is_standard_layout<SimpleCallContextData>::value);
+Q_STATIC_ASSERT(offsetof(SimpleCallContextData, activation) == 0);
+Q_STATIC_ASSERT(offsetof(SimpleCallContextData, v4Function) == offsetof(SimpleCallContextData, activation) + QT_POINTER_SIZE);
+Q_STATIC_ASSERT(sizeof(SimpleCallContextData) == 2 * QT_POINTER_SIZE);
+Q_STATIC_ASSERT(sizeof(SimpleCallContext) == sizeof(ExecutionContext) + sizeof(SimpleCallContextData));
+
+#if QT_POINTER_SIZE == 8
+#define CallContextMembers(class, Member) \
+ Member(class, Pointer, FunctionObject *, function) \
+ Member(class, ValueArray, ValueArray, locals)
+#else
+#define CallContextMembers(class, Member) \
+ Member(class, Pointer, FunctionObject *, function) \
+ Member(class, NoMark, void *, padding) \
+ Member(class, ValueArray, ValueArray, locals)
+#endif
+
+DECLARE_HEAP_OBJECT(CallContext, SimpleCallContext) {
+ DECLARE_MARK_TABLE(CallContext);
+
+ using SimpleCallContext::formalParameterCount;
+};
+
+Q_STATIC_ASSERT(std::is_standard_layout<CallContextData>::value);
+Q_STATIC_ASSERT(offsetof(CallContextData, function) == 0);
+// IMPORTANT: we cannot do offsetof(CallContextData, locals) in the JIT as the offset does not scale with
+// the pointer size. On 32-bit ARM the offset of the ValueArray is aligned to 8 bytes, on 32-bit x86 for
+// example it is not. Therefore we have a padding in place and always have a distance of 8 bytes.
+Q_STATIC_ASSERT(offsetof(CallContextData, locals) == offsetof(CallContextData, function) + 8);
+
+#define GlobalContextMembers(class, Member) \
+ Member(class, Pointer, Object *, global)
+
+DECLARE_HEAP_OBJECT(GlobalContext, ExecutionContext) {
+ DECLARE_MARK_TABLE(GlobalContext);
-struct GlobalContext : ExecutionContext {
void init(ExecutionEngine *engine);
- Pointer<Object> global;
};
V4_ASSERT_IS_TRIVIAL(GlobalContext)
-struct CatchContext : ExecutionContext {
+#define CatchContextMembers(class, Member) \
+ Member(class, Pointer, String *, exceptionVarName) \
+ Member(class, HeapValue, HeapValue, exceptionValue)
+
+DECLARE_HEAP_OBJECT(CatchContext, ExecutionContext) {
+ DECLARE_MARK_TABLE(CatchContext);
+
void init(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue);
- Pointer<String> exceptionVarName;
- Value exceptionValue;
};
V4_ASSERT_IS_TRIVIAL(CatchContext)
-struct WithContext : ExecutionContext {
- void init(ExecutionContext *outerContext, Object *with)
- {
- Heap::ExecutionContext::init(Heap::ExecutionContext::Type_WithContext);
- outer = outerContext;
- callData = outer->callData;
- lookups = outer->lookups;
- constantTable = outer->constantTable;
- compilationUnit = outer->compilationUnit;
-
- withObject = with;
- }
+#define WithContextMembers(class, Member) \
+ Member(class, Pointer, Object *, withObject)
+
+DECLARE_HEAP_OBJECT(WithContext, ExecutionContext) {
+ DECLARE_MARK_TABLE(WithContext);
- Pointer<Object> withObject;
+ void init(ExecutionContext *outerContext, Object *with);
};
V4_ASSERT_IS_TRIVIAL(WithContext)
@@ -236,15 +250,13 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
ReturnedValue getPropertyAndBase(String *name, Value *base);
bool deleteProperty(String *name);
- inline CallContext *asCallContext();
- inline const CallContext *asCallContext() const;
+ inline SimpleCallContext *asSimpleCallContext();
+ inline const SimpleCallContext *asSimpleCallContext() const;
inline const CatchContext *asCatchContext() const;
inline const WithContext *asWithContext() const;
Function *getFunction() const;
- static void markObjects(Heap::Base *m, ExecutionEngine *e);
-
Value &thisObject() const {
return d()->callData->thisObject;
}
@@ -262,10 +274,10 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
void simpleCall(Scope &scope, CallData *callData, QV4::Function *function);
};
-struct Q_QML_EXPORT CallContext : public ExecutionContext
+struct Q_QML_EXPORT SimpleCallContext : public ExecutionContext
{
- V4_MANAGED(CallContext, ExecutionContext)
- V4_INTERNALCLASS(CallContext)
+ V4_MANAGED(SimpleCallContext, ExecutionContext)
+ V4_INTERNALCLASS(SimpleCallContext)
// formals are in reverse order
Identifier * const *formals() const;
@@ -274,14 +286,17 @@ struct Q_QML_EXPORT CallContext : public ExecutionContext
unsigned int variableCount() const;
inline ReturnedValue argument(int i) const;
- bool needsOwnArguments() const;
-
};
-inline ReturnedValue CallContext::argument(int i) const {
+inline ReturnedValue SimpleCallContext::argument(int i) const {
return i < argc() ? args()[i].asReturnedValue() : Primitive::undefinedValue().asReturnedValue();
}
+struct Q_QML_EXPORT CallContext : public SimpleCallContext
+{
+ V4_MANAGED(CallContext, SimpleCallContext)
+};
+
struct GlobalContext : public ExecutionContext
{
V4_MANAGED(GlobalContext, ExecutionContext)
@@ -298,14 +313,14 @@ struct WithContext : public ExecutionContext
V4_MANAGED(WithContext, ExecutionContext)
};
-inline CallContext *ExecutionContext::asCallContext()
+inline SimpleCallContext *ExecutionContext::asSimpleCallContext()
{
- return d()->type >= Heap::ExecutionContext::Type_SimpleCallContext ? static_cast<CallContext *>(this) : 0;
+ return d()->type >= Heap::ExecutionContext::Type_SimpleCallContext ? static_cast<SimpleCallContext *>(this) : 0;
}
-inline const CallContext *ExecutionContext::asCallContext() const
+inline const SimpleCallContext *ExecutionContext::asSimpleCallContext() const
{
- return d()->type >= Heap::ExecutionContext::Type_SimpleCallContext ? static_cast<const CallContext *>(this) : 0;
+ return d()->type >= Heap::ExecutionContext::Type_SimpleCallContext ? static_cast<const SimpleCallContext *>(this) : 0;
}
inline const CatchContext *ExecutionContext::asCatchContext() const
diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp
index a810b38f24..f1405e08ee 100644
--- a/src/qml/jsruntime/qv4dataview.cpp
+++ b/src/qml/jsruntime/qv4dataview.cpp
@@ -73,7 +73,7 @@ void DataViewCtor::construct(const Managed *, Scope &scope, CallData *callData)
}
Scoped<DataView> a(scope, scope.engine->memoryManager->allocObject<DataView>());
- a->d()->buffer = buffer->d();
+ a->d()->buffer.set(scope.engine, buffer->d());
a->d()->byteLength = byteLength;
a->d()->byteOffset = byteOffset;
scope.result = a.asReturnedValue();
@@ -84,13 +84,6 @@ void DataViewCtor::call(const Managed *that, Scope &scope, CallData *callData)
construct(that, scope, callData);
}
-
-void DataView::markObjects(Heap::Base *that, ExecutionEngine *e)
-{
- DataView::Data *v = static_cast<DataView::Data *>(that);
- v->buffer->mark(e);
-}
-
void DataViewPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
diff --git a/src/qml/jsruntime/qv4dataview_p.h b/src/qml/jsruntime/qv4dataview_p.h
index 11cc0a6bd9..5c50df4655 100644
--- a/src/qml/jsruntime/qv4dataview_p.h
+++ b/src/qml/jsruntime/qv4dataview_p.h
@@ -63,11 +63,14 @@ struct DataViewCtor : FunctionObject {
void init(QV4::ExecutionContext *scope);
};
-struct DataView : Object {
+#define DataViewMembers(class, Member) \
+ Member(class, Pointer, ArrayBuffer *, buffer) \
+ Member(class, NoMark, uint, byteLength) \
+ Member(class, NoMark, uint, byteOffset)
+
+DECLARE_HEAP_OBJECT(DataView, Object) {
+ DECLARE_MARK_TABLE(DataView);
void init() { Object::init(); }
- Pointer<ArrayBuffer> buffer;
- uint byteLength;
- uint byteOffset;
};
}
@@ -84,8 +87,6 @@ struct DataView : Object
{
V4_OBJECT2(DataView, Object)
V4_PROTOTYPE(dataViewPrototype)
-
- static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
struct DataViewPrototype: Object
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index b90c335b1c..c56d007028 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -340,7 +340,9 @@ static inline double TimeClip(double t)
{
if (! qt_is_finite(t) || fabs(t) > 8.64e15)
return qt_qnan();
- return Primitive::toInteger(t);
+
+ // +0 looks weird, but is correct. See ES6 20.3.1.15. We must not return -0.
+ return Primitive::toInteger(t) + 0;
}
static inline double ParseString(const QString &s)
@@ -724,7 +726,7 @@ void DatePrototype::init(ExecutionEngine *engine, Object *ctor)
Scope scope(engine);
ScopedObject o(scope);
ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
- ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(7));
+ ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(7));
LocalTZA = getLocalTZA();
ctor->defineDefaultProperty(QStringLiteral("parse"), method_parse, 1);
@@ -774,8 +776,21 @@ void DatePrototype::init(ExecutionEngine *engine, Object *ctor)
defineDefaultProperty(QStringLiteral("setYear"), method_setYear, 1);
defineDefaultProperty(QStringLiteral("setFullYear"), method_setFullYear, 3);
defineDefaultProperty(QStringLiteral("setUTCFullYear"), method_setUTCFullYear, 3);
- defineDefaultProperty(QStringLiteral("toUTCString"), method_toUTCString, 0);
- defineDefaultProperty(QStringLiteral("toGMTString"), method_toUTCString, 0);
+
+ // ES6: B.2.4.3 & 20.3.4.43:
+ // We have to use the *same object* for toUTCString and toGMTString
+ {
+ QString toUtcString(QStringLiteral("toUTCString"));
+ QString toGmtString(QStringLiteral("toGMTString"));
+ ScopedString us(scope, engine->newIdentifier(toUtcString));
+ ScopedString gs(scope, engine->newIdentifier(toGmtString));
+ ExecutionContext *global = engine->rootContext();
+ ScopedFunctionObject toUtcGmtStringFn(scope, BuiltinFunction::create(global, us, method_toUTCString));
+ toUtcGmtStringFn->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(0));
+ defineDefaultProperty(us, toUtcGmtStringFn);
+ defineDefaultProperty(gs, toUtcGmtStringFn);
+ }
+
defineDefaultProperty(QStringLiteral("toISOString"), method_toISOString, 0);
defineDefaultProperty(QStringLiteral("toJSON"), method_toJSON, 1);
}
@@ -1025,6 +1040,7 @@ void DatePrototype::method_setTime(const BuiltinFunction *, Scope &scope, CallDa
THROW_TYPE_ERROR();
double t = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ CHECK_EXCEPTION();
self->setDate(TimeClip(t));
scope.result = Encode(self->date());
}
@@ -1036,7 +1052,9 @@ void DatePrototype::method_setMilliseconds(const BuiltinFunction *, Scope &scope
THROW_TYPE_ERROR();
double t = LocalTime(self->date());
+ CHECK_EXCEPTION();
double ms = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ CHECK_EXCEPTION();
self->setDate(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))));
scope.result = Encode(self->date());
}
@@ -1048,7 +1066,9 @@ void DatePrototype::method_setUTCMilliseconds(const BuiltinFunction *, Scope &sc
THROW_TYPE_ERROR();
double t = self->date();
+ CHECK_EXCEPTION();
double ms = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ CHECK_EXCEPTION();
self->setDate(TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))));
scope.result = Encode(self->date());
}
@@ -1060,8 +1080,11 @@ void DatePrototype::method_setSeconds(const BuiltinFunction *, Scope &scope, Cal
THROW_TYPE_ERROR();
double t = LocalTime(self->date());
+ CHECK_EXCEPTION();
double sec = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ CHECK_EXCEPTION();
double ms = (callData->argc < 2) ? msFromTime(t) : callData->args[1].toNumber();
+ CHECK_EXCEPTION();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms))));
self->setDate(t);
scope.result = Encode(self->date());
@@ -1088,9 +1111,13 @@ void DatePrototype::method_setMinutes(const BuiltinFunction *, Scope &scope, Cal
THROW_TYPE_ERROR();
double t = LocalTime(self->date());
+ CHECK_EXCEPTION();
double min = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ CHECK_EXCEPTION();
double sec = (callData->argc < 2) ? SecFromTime(t) : callData->args[1].toNumber();
+ CHECK_EXCEPTION();
double ms = (callData->argc < 3) ? msFromTime(t) : callData->args[2].toNumber();
+ CHECK_EXCEPTION();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms))));
self->setDate(t);
scope.result = Encode(self->date());
@@ -1118,10 +1145,15 @@ void DatePrototype::method_setHours(const BuiltinFunction *, Scope &scope, CallD
THROW_TYPE_ERROR();
double t = LocalTime(self->date());
+ CHECK_EXCEPTION();
double hour = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ CHECK_EXCEPTION();
double min = (callData->argc < 2) ? MinFromTime(t) : callData->args[1].toNumber();
+ CHECK_EXCEPTION();
double sec = (callData->argc < 3) ? SecFromTime(t) : callData->args[2].toNumber();
+ CHECK_EXCEPTION();
double ms = (callData->argc < 4) ? msFromTime(t) : callData->args[3].toNumber();
+ CHECK_EXCEPTION();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms))));
self->setDate(t);
scope.result = Encode(self->date());
@@ -1150,7 +1182,9 @@ void DatePrototype::method_setDate(const BuiltinFunction *, Scope &scope, CallDa
THROW_TYPE_ERROR();
double t = LocalTime(self->date());
+ CHECK_EXCEPTION();
double date = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ CHECK_EXCEPTION();
t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t))));
self->setDate(t);
scope.result = Encode(self->date());
@@ -1163,7 +1197,9 @@ void DatePrototype::method_setUTCDate(const BuiltinFunction *, Scope &scope, Cal
THROW_TYPE_ERROR();
double t = self->date();
+ CHECK_EXCEPTION();
double date = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ CHECK_EXCEPTION();
t = TimeClip(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t)));
self->setDate(t);
scope.result = Encode(self->date());
@@ -1176,8 +1212,11 @@ void DatePrototype::method_setMonth(const BuiltinFunction *, Scope &scope, CallD
THROW_TYPE_ERROR();
double t = LocalTime(self->date());
+ CHECK_EXCEPTION();
double month = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ CHECK_EXCEPTION();
double date = (callData->argc < 2) ? DateFromTime(t) : callData->args[1].toNumber();
+ CHECK_EXCEPTION();
t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t))));
self->setDate(t);
scope.result = Encode(self->date());
@@ -1245,11 +1284,15 @@ void DatePrototype::method_setFullYear(const BuiltinFunction *, Scope &scope, Ca
THROW_TYPE_ERROR();
double t = LocalTime(self->date());
+ CHECK_EXCEPTION();
if (std::isnan(t))
t = 0;
double year = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ CHECK_EXCEPTION();
double month = (callData->argc < 2) ? MonthFromTime(t) : callData->args[1].toNumber();
+ CHECK_EXCEPTION();
double date = (callData->argc < 3) ? DateFromTime(t) : callData->args[2].toNumber();
+ CHECK_EXCEPTION();
t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t))));
self->setDate(t);
scope.result = Encode(self->date());
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index ecd57bcd8d..b0373884dd 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -112,7 +112,7 @@ struct DateCtor: FunctionObject
static void call(const Managed *that, Scope &scope, CallData *);
};
-struct DatePrototype: DateObject
+struct DatePrototype: Object
{
V4_PROTOTYPE(objectPrototype)
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 0cb1b1ee13..019936767a 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -134,6 +134,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
, regExpAllocator(new QV4::ExecutableAllocator)
, bumperPointerAllocator(new WTF::BumpPointerAllocator)
, jsStack(new WTF::PageAllocation)
+ , gcStack(new WTF::PageAllocation)
, globalCode(0)
, v8Engine(0)
, argumentsAccessors(0)
@@ -186,18 +187,22 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
iselFactory.reset(factory);
// reserve space for the JS stack
- // we allow it to grow to 2 times JSStackLimit, as we can overshoot due to garbage collection
- // and ScopedValues allocated outside of JIT'ed methods.
- *jsStack = WTF::PageAllocation::allocate(2 * JSStackLimit, WTF::OSAllocator::JSVMStackPages,
+ // we allow it to grow to a bit more than JSStackLimit, as we can overshoot due to ScopedValues
+ // allocated outside of JIT'ed methods.
+ *jsStack = WTF::PageAllocation::allocate(JSStackLimit + 256*1024, WTF::OSAllocator::JSVMStackPages,
/* writable */ true, /* executable */ false,
/* includesGuardPages */ true);
jsStackBase = (Value *)jsStack->base();
#ifdef V4_USE_VALGRIND
- VALGRIND_MAKE_MEM_UNDEFINED(jsStackBase, 2*JSStackLimit);
+ VALGRIND_MAKE_MEM_UNDEFINED(jsStackBase, JSStackLimit + 256*1024);
#endif
jsStackTop = jsStackBase;
+ *gcStack = WTF::PageAllocation::allocate(GCStackLimit, WTF::OSAllocator::JSVMStackPages,
+ /* writable */ true, /* executable */ false,
+ /* includesGuardPages */ true);
+
exceptionValue = jsAlloca(1);
globalObject = static_cast<Object *>(jsAlloca(1));
jsObjects = jsAlloca(NJSObjects);
@@ -218,7 +223,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
internalClasses[Class_SimpleArrayData] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::SimpleArrayData::staticVTable());
internalClasses[Class_SparseArrayData] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::SparseArrayData::staticVTable());
internalClasses[Class_ExecutionContext] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::ExecutionContext::staticVTable());
- internalClasses[Class_CallContext] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::CallContext::staticVTable());
+ internalClasses[Class_SimpleCallContext] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::CallContext::staticVTable());
jsStrings[String_Empty] = newIdentifier(QString());
jsStrings[String_undefined] = newIdentifier(QStringLiteral("undefined"));
@@ -424,13 +429,14 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
//
// set up the global object
//
- rootContext()->d()->global = globalObject->d();
+ rootContext()->d()->global.set(scope.engine, globalObject->d());
rootContext()->d()->callData->thisObject = globalObject;
Q_ASSERT(globalObject->d()->vtable());
globalObject->defineDefaultProperty(QStringLiteral("Object"), *objectCtor());
globalObject->defineDefaultProperty(QStringLiteral("String"), *stringCtor());
- globalObject->defineDefaultProperty(QStringLiteral("Number"), *numberCtor());
+ FunctionObject *numberObject = numberCtor();
+ globalObject->defineDefaultProperty(QStringLiteral("Number"), *numberObject);
globalObject->defineDefaultProperty(QStringLiteral("Boolean"), *booleanCtor());
globalObject->defineDefaultProperty(QStringLiteral("Array"), *arrayCtor());
globalObject->defineDefaultProperty(QStringLiteral("Function"), *functionCtor());
@@ -460,8 +466,26 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
jsObjects[Eval_Function] = memoryManager->allocObject<EvalFunction>(global);
globalObject->defineDefaultProperty(QStringLiteral("eval"), *evalFunction());
- globalObject->defineDefaultProperty(QStringLiteral("parseInt"), GlobalFunctions::method_parseInt, 2);
- globalObject->defineDefaultProperty(QStringLiteral("parseFloat"), GlobalFunctions::method_parseFloat, 1);
+ // ES6: 20.1.2.12 & 20.1.2.13:
+ // parseInt and parseFloat must be the same FunctionObject on the global &
+ // Number object.
+ {
+ QString piString(QStringLiteral("parseInt"));
+ QString pfString(QStringLiteral("parseFloat"));
+ Scope scope(this);
+ ScopedString pi(scope, newIdentifier(piString));
+ ScopedString pf(scope, newIdentifier(pfString));
+ ExecutionContext *global = rootContext();
+ ScopedFunctionObject parseIntFn(scope, BuiltinFunction::create(global, pi, GlobalFunctions::method_parseInt));
+ ScopedFunctionObject parseFloatFn(scope, BuiltinFunction::create(global, pf, GlobalFunctions::method_parseFloat));
+ parseIntFn->defineReadonlyConfigurableProperty(id_length(), Primitive::fromInt32(2));
+ parseFloatFn->defineReadonlyConfigurableProperty(id_length(), Primitive::fromInt32(1));
+ globalObject->defineDefaultProperty(piString, parseIntFn);
+ globalObject->defineDefaultProperty(pfString, parseFloatFn);
+ numberObject->defineDefaultProperty(piString, parseIntFn);
+ numberObject->defineDefaultProperty(pfString, parseFloatFn);
+ }
+
globalObject->defineDefaultProperty(QStringLiteral("isNaN"), GlobalFunctions::method_isNaN, 1);
globalObject->defineDefaultProperty(QStringLiteral("isFinite"), GlobalFunctions::method_isFinite, 1);
globalObject->defineDefaultProperty(QStringLiteral("decodeURI"), GlobalFunctions::method_decodeURI, 1);
@@ -501,6 +525,8 @@ ExecutionEngine::~ExecutionEngine()
delete executableAllocator;
jsStack->deallocate();
delete jsStack;
+ gcStack->deallocate();
+ delete gcStack;
delete [] argumentsAccessors;
}
@@ -612,12 +638,14 @@ Heap::ArrayObject *ExecutionEngine::newArrayObject(const Value *values, int leng
size_t size = sizeof(Heap::ArrayData) + (length-1)*sizeof(Value);
Heap::SimpleArrayData *d = scope.engine->memoryManager->allocManaged<SimpleArrayData>(size);
d->init();
- d->alloc = length;
d->type = Heap::ArrayData::Simple;
d->offset = 0;
- d->len = length;
- memcpy(&d->arrayData, values, length*sizeof(Value));
- a->d()->arrayData = d;
+ d->values.alloc = length;
+ d->values.size = length;
+ // this doesn't require a write barrier, things will be ok, when the new array data gets inserted into
+ // the parent object
+ memcpy(&d->values.values, values, length*sizeof(Value));
+ a->d()->arrayData.set(this, d);
a->setArrayLengthUnchecked(length);
}
return a->d();
@@ -898,7 +926,7 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file)
QUrl base;
ExecutionContext *c = currentContext;
while (c) {
- CallContext *callCtx = c->asCallContext();
+ SimpleCallContext *callCtx = c->asSimpleCallContext();
if (callCtx && callCtx->d()->v4Function) {
base.setUrl(callCtx->d()->v4Function->sourceFile());
break;
@@ -941,23 +969,23 @@ void ExecutionEngine::requireArgumentsAccessors(int n)
}
}
-void ExecutionEngine::markObjects()
+void ExecutionEngine::markObjects(MarkStack *markStack)
{
- identifierTable->mark(this);
+ identifierTable->mark(markStack);
for (int i = 0; i < nArgumentsAccessors; ++i) {
const Property &pd = argumentsAccessors[i];
if (Heap::FunctionObject *getter = pd.getter())
- getter->mark(this);
+ getter->mark(markStack);
if (Heap::FunctionObject *setter = pd.setter())
- setter->mark(this);
+ setter->mark(markStack);
}
- classPool->markObjects(this);
+ classPool->markObjects(markStack);
for (QSet<CompiledData::CompilationUnit*>::ConstIterator it = compilationUnits.constBegin(), end = compilationUnits.constEnd();
it != end; ++it)
- (*it)->markObjects(this);
+ (*it)->markObjects(markStack);
}
ReturnedValue ExecutionEngine::throwError(const Value &value)
@@ -1151,9 +1179,9 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return QVariant::fromValue(QV4::JsonObject::toJsonObject(object));
} else if (QV4::QObjectWrapper *wrapper = object->as<QV4::QObjectWrapper>()) {
return qVariantFromValue<QObject *>(wrapper->object());
- } else if (object->as<QV4::QmlContextWrapper>()) {
+ } else if (object->as<QV4::QQmlContextWrapper>()) {
return QVariant();
- } else if (QV4::QmlTypeWrapper *w = object->as<QV4::QmlTypeWrapper>()) {
+ } else if (QV4::QQmlTypeWrapper *w = object->as<QV4::QQmlTypeWrapper>()) {
return w->toVariant();
} else if (QV4::QQmlValueTypeWrapper *v = object->as<QV4::QQmlValueTypeWrapper>()) {
return v->toVariant();
@@ -1575,12 +1603,6 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data)
return 0;
}
-void ExecutionEngine::assertObjectBelongsToEngine(const Heap::Base &baseObject)
-{
- Q_ASSERT(!baseObject.vtable()->isObject || static_cast<const Heap::Object&>(baseObject).internalClass->engine == this);
- Q_UNUSED(baseObject);
-}
-
void ExecutionEngine::failStackLimitCheck(Scope &scope)
{
scope.result = throwRangeError(QStringLiteral("Maximum call stack size exceeded."));
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index a569b8ddf9..16a043dda5 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -103,17 +103,13 @@ public:
WTF::BumpPointerAllocator *bumperPointerAllocator; // Used by Yarr Regex engine.
- enum { JSStackLimit = 4*1024*1024 };
+ enum {
+ JSStackLimit = 4*1024*1024,
+ GCStackLimit = 2*1024*1024
+ };
WTF::PageAllocation *jsStack;
- void pushForGC(Heap::Base *m) {
- *jsStackTop = m;
- ++jsStackTop;
- }
- Heap::Base *popForGC() {
- --jsStackTop;
- return jsStackTop->heapObject();
- }
+ WTF::PageAllocation *gcStack;
QML_NEARLY_ALWAYS_INLINE Value *jsAlloca(int nValues) {
Value *ptr = jsStackTop;
@@ -419,7 +415,7 @@ public:
void requireArgumentsAccessors(int n);
- void markObjects();
+ void markObjects(MarkStack *markStack);
void initRootContext();
@@ -456,8 +452,6 @@ public:
bool metaTypeFromJS(const Value *value, int type, void *data);
QV4::ReturnedValue metaTypeToJS(int type, const void *data);
- void assertObjectBelongsToEngine(const Heap::Base &baseObject);
-
bool checkStackLimits(Scope &scope);
private:
@@ -516,23 +510,32 @@ inline ExecutionContext *ExecutionEngine::parentContext(ExecutionContext *contex
}
inline
-void Heap::Base::mark(QV4::ExecutionEngine *engine)
+void Heap::Base::mark(QV4::MarkStack *markStack)
{
Q_ASSERT(inUse());
- if (isMarked())
- return;
-#ifndef QT_NO_DEBUG
- engine->assertObjectBelongsToEngine(*this);
-#endif
- setMarkBit();
- engine->pushForGC(this);
+ const HeapItem *h = reinterpret_cast<const HeapItem *>(this);
+ Chunk *c = h->chunk();
+ size_t index = h - c->realBase();
+ Q_ASSERT(!Chunk::testBit(c->extendsBitmap, index));
+ quintptr *bitmap = c->blackBitmap + Chunk::bitmapIndex(index);
+ quintptr bit = Chunk::bitForIndex(index);
+ if (!(*bitmap & bit)) {
+ *bitmap |= bit;
+ markStack->push(this);
+ }
}
-inline void Value::mark(ExecutionEngine *e)
+inline void Value::mark(MarkStack *markStack)
{
Heap::Base *o = heapObject();
if (o)
- o->mark(e);
+ o->mark(markStack);
+}
+
+inline void Managed::mark(MarkStack *markStack)
+{
+ Q_ASSERT(m());
+ m()->mark(markStack);
}
#define CHECK_STACK_LIMITS(v4, scope) if ((v4)->checkStackLimits(scope)) return; \
diff --git a/src/qml/jsruntime/qv4enginebase_p.h b/src/qml/jsruntime/qv4enginebase_p.h
index 06c346b3c0..88f9dfd85c 100644
--- a/src/qml/jsruntime/qv4enginebase_p.h
+++ b/src/qml/jsruntime/qv4enginebase_p.h
@@ -66,7 +66,9 @@ struct EngineBase {
Heap::ExecutionContext *current = 0;
Value *jsStackTop = 0;
- quint32 hasException = false;
+ quint8 hasException = false;
+ quint8 writeBarrierActive = false;
+ quint16 unused = 0;
#if QT_POINTER_SIZE == 8
quint8 padding[4];
#endif
@@ -88,7 +90,7 @@ struct EngineBase {
Class_SimpleArrayData,
Class_SparseArrayData,
Class_ExecutionContext,
- Class_CallContext,
+ Class_SimpleCallContext,
Class_Object,
Class_ArrayObject,
Class_FunctionObject,
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index 6811438915..b3bd28e18b 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -78,10 +78,10 @@ void Heap::ErrorObject::init()
if (internalClass == scope.engine->internalClasses[EngineBase::Class_ErrorProto])
return;
- *propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction();
- *propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined();
- *propertyData(QV4::ErrorObject::Index_FileName) = Encode::undefined();
- *propertyData(QV4::ErrorObject::Index_LineNumber) = Encode::undefined();
+ setProperty(scope.engine, QV4::ErrorObject::Index_Stack, scope.engine->getStackFunction()->d());
+ setProperty(scope.engine, QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset, Primitive::undefinedValue());
+ setProperty(scope.engine, QV4::ErrorObject::Index_FileName, Primitive::undefinedValue());
+ setProperty(scope.engine, QV4::ErrorObject::Index_LineNumber, Primitive::undefinedValue());
}
void Heap::ErrorObject::init(const Value &message, ErrorType t)
@@ -92,17 +92,17 @@ void Heap::ErrorObject::init(const Value &message, ErrorType t)
Scope scope(internalClass->engine);
Scoped<QV4::ErrorObject> e(scope, this);
- *propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction();
- *propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined();
+ setProperty(scope.engine, QV4::ErrorObject::Index_Stack, scope.engine->getStackFunction()->d());
+ setProperty(scope.engine, QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset, Primitive::undefinedValue());
e->d()->stackTrace = new StackTrace(scope.engine->stackTrace());
if (!e->d()->stackTrace->isEmpty()) {
- *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace->at(0).source);
- *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace->at(0).line);
+ setProperty(scope.engine, QV4::ErrorObject::Index_FileName, scope.engine->newString(e->d()->stackTrace->at(0).source));
+ setProperty(scope.engine, QV4::ErrorObject::Index_LineNumber, Primitive::fromInt32(e->d()->stackTrace->at(0).line));
}
if (!message.isUndefined())
- *propertyData(QV4::ErrorObject::Index_Message) = message;
+ setProperty(scope.engine, QV4::ErrorObject::Index_Message, message);
}
void Heap::ErrorObject::init(const Value &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t)
@@ -113,8 +113,8 @@ void Heap::ErrorObject::init(const Value &message, const QString &fileName, int
Scope scope(internalClass->engine);
Scoped<QV4::ErrorObject> e(scope, this);
- *propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction();
- *propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined();
+ setProperty(scope.engine, QV4::ErrorObject::Index_Stack, scope.engine->getStackFunction()->d());
+ setProperty(scope.engine, QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset, Primitive::undefinedValue());
e->d()->stackTrace = new StackTrace(scope.engine->stackTrace());
StackFrame frame;
@@ -124,12 +124,12 @@ void Heap::ErrorObject::init(const Value &message, const QString &fileName, int
e->d()->stackTrace->prepend(frame);
if (!e->d()->stackTrace->isEmpty()) {
- *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace->at(0).source);
- *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace->at(0).line);
+ setProperty(scope.engine, QV4::ErrorObject::Index_FileName, scope.engine->newString(e->d()->stackTrace->at(0).source));
+ setProperty(scope.engine, QV4::ErrorObject::Index_LineNumber, Primitive::fromInt32(e->d()->stackTrace->at(0).line));
}
if (!message.isUndefined())
- *propertyData(QV4::ErrorObject::Index_Message) = message;
+ setProperty(scope.engine, QV4::ErrorObject::Index_Message, message);
}
const char *ErrorObject::className(Heap::ErrorObject::ErrorType t)
@@ -168,19 +168,11 @@ void ErrorObject::method_get_stack(const BuiltinFunction *, Scope &scope, CallDa
if (frame.line >= 0)
trace += QLatin1Char(':') + QString::number(frame.line);
}
- This->d()->stack = scope.engine->newString(trace);
+ This->d()->stack.set(scope.engine, scope.engine->newString(trace));
}
scope.result = This->d()->stack;
}
-void ErrorObject::markObjects(Heap::Base *that, ExecutionEngine *e)
-{
- ErrorObject::Data *This = static_cast<ErrorObject::Data *>(that);
- if (This->stack)
- This->stack->mark(e);
- Object::markObjects(that, e);
-}
-
DEFINE_OBJECT_VTABLE(ErrorObject);
void Heap::SyntaxErrorObject::init(const Value &msg)
@@ -325,9 +317,9 @@ void ErrorPrototype::init(ExecutionEngine *engine, Object *ctor, Object *obj, He
ScopedObject o(scope);
ctor->defineReadonlyProperty(engine->id_prototype(), (o = obj));
ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
- *obj->propertyData(Index_Constructor) = ctor;
- *obj->propertyData(Index_Message) = engine->id_empty();
- *obj->propertyData(Index_Name) = engine->newString(QString::fromLatin1(ErrorObject::className(t)));
+ obj->setProperty(Index_Constructor, ctor->d());
+ obj->setProperty(Index_Message, engine->id_empty()->d());
+ obj->setProperty(Index_Name, engine->newString(QString::fromLatin1(ErrorObject::className(t))));
obj->defineDefaultProperty(engine->id_toString(), method_toString, 0);
}
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index 12531c9309..d556617b48 100644
--- a/src/qml/jsruntime/qv4errorobject_p.h
+++ b/src/qml/jsruntime/qv4errorobject_p.h
@@ -62,7 +62,12 @@ struct SyntaxErrorObject;
namespace Heap {
-struct ErrorObject : Object {
+
+#define ErrorObjectMembers(class, Member) \
+ Member(class, Pointer, String *, stack)
+
+DECLARE_HEAP_OBJECT(ErrorObject, Object) {
+ DECLARE_MARK_TABLE(ErrorObject);
enum ErrorType {
Error,
EvalError,
@@ -72,6 +77,8 @@ struct ErrorObject : Object {
TypeError,
URIError
};
+ StackTrace *stackTrace;
+ ErrorType errorType;
void init();
void init(const Value &message, ErrorType t = Error);
@@ -80,10 +87,6 @@ struct ErrorObject : Object {
delete stackTrace;
Object::destroy();
}
-
- ErrorType errorType;
- StackTrace *stackTrace;
- Pointer<String> stack;
};
struct EvalErrorObject : ErrorObject {
@@ -173,7 +176,6 @@ struct ErrorObject: Object {
static const char *className(Heap::ErrorObject::ErrorType t);
static void method_get_stack(const BuiltinFunction *, Scope &scope, CallData *callData);
- static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
template<>
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index 31b57b97e9..d1bdab1b3c 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -60,7 +60,7 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit,
Q_UNUSED(engine);
internalClass = engine->internalClasses[EngineBase::Class_Empty];
- const CompiledData::LEUInt32 *formalsIndices = compiledFunction->formalsTable();
+ const quint32_le *formalsIndices = compiledFunction->formalsTable();
// iterate backwards, so we get the right ordering for duplicate names
Scope scope(engine);
ScopedString arg(scope);
@@ -79,14 +79,11 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit,
}
nFormals = compiledFunction->nFormals;
- const CompiledData::LEUInt32 *localsIndices = compiledFunction->localsTable();
+ const quint32_le *localsIndices = compiledFunction->localsTable();
for (quint32 i = 0; i < compiledFunction->nLocals; ++i)
internalClass = internalClass->addMember(compilationUnit->runtimeStrings[localsIndices[i]]->identifier, Attr_NotConfigurable);
- activationRequired = compiledFunction->nInnerFunctions > 0 || (compiledFunction->flags & (CompiledData::Function::HasDirectEval | CompiledData::Function::UsesArgumentsObject));
-
- canUseSimpleCall = !needsActivation() && !(compiledFunction->flags & CompiledData::Function::HasCatchOrWith) &&
- !(compiledFunction->nFormals > QV4::Global::ReservedArgumentCount) && !isNamedExpression();
+ canUseSimpleCall = compiledFunction->flags & CompiledData::Function::CanUseSimpleCall;
}
Function::~Function()
@@ -114,11 +111,11 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArr
}
nFormals = parameters.size();
- const CompiledData::LEUInt32 *localsIndices = compiledFunction->localsTable();
+ const quint32_le *localsIndices = compiledFunction->localsTable();
for (quint32 i = 0; i < compiledFunction->nLocals; ++i)
internalClass = internalClass->addMember(compilationUnit->runtimeStrings[localsIndices[i]]->identifier, Attr_NotConfigurable);
- activationRequired = true;
+ canUseSimpleCall = false;
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index 54d0528c42..b11c8af94a 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -69,7 +69,6 @@ struct Q_QML_EXPORT Function {
// first nArguments names in internalClass are the actual arguments
InternalClass *internalClass;
uint nFormals;
- bool activationRequired;
bool hasQmlDependencies;
bool canUseSimpleCall;
@@ -89,9 +88,6 @@ struct Q_QML_EXPORT Function {
inline bool isStrict() const { return compiledFunction->flags & CompiledData::Function::IsStrict; }
inline bool isNamedExpression() const { return compiledFunction->flags & CompiledData::Function::IsNamedExpression; }
- inline bool needsActivation() const
- { return activationRequired; }
-
inline bool canUseSimpleFunction() const { return canUseSimpleCall; }
QQmlSourceLocation sourceLocation() const
@@ -102,7 +98,7 @@ struct Q_QML_EXPORT Function {
};
-inline unsigned int Heap::CallContext::formalParameterCount() const
+inline unsigned int Heap::SimpleCallContext::formalParameterCount() const
{
return v4Function ? v4Function->nFormals : 0;
}
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 9eb9d2ad36..45fdde98f7 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -69,11 +69,13 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(FunctionObject);
+Q_STATIC_ASSERT((Heap::FunctionObject::markTable & Heap::Object::markTable) == Heap::Object::markTable);
+
void Heap::FunctionObject::init(QV4::ExecutionContext *scope, QV4::String *name, bool createProto)
{
Object::init();
function = nullptr;
- this->scope = scope->d();
+ this->scope.set(scope->engine(), scope->d());
Scope s(scope->engine());
ScopedFunctionObject f(s, this);
f->init(name, createProto);
@@ -84,7 +86,7 @@ void Heap::FunctionObject::init(QV4::ExecutionContext *scope, Function *function
Object::init();
this->function = function;
function->compilationUnit->addref();
- this->scope = scope->d();
+ this->scope.set(scope->engine(), scope->d());
Scope s(scope->engine());
ScopedString name(s, function->name());
ScopedFunctionObject f(s, this);
@@ -102,9 +104,9 @@ void Heap::FunctionObject::init()
{
Object::init();
function = nullptr;
- this->scope = internalClass->engine->rootContext()->d();
+ this->scope.set(internalClass->engine, internalClass->engine->rootContext()->d());
Q_ASSERT(internalClass && internalClass->find(internalClass->engine->id_prototype()) == Index_Prototype);
- *propertyData(Index_Prototype) = Encode::undefined();
+ setProperty(internalClass->engine, Index_Prototype, Primitive::undefinedValue());
}
@@ -124,14 +126,14 @@ void FunctionObject::init(String *n, bool createProto)
if (createProto) {
ScopedObject proto(s, s.engine->newObject(s.engine->internalClasses[EngineBase::Class_ObjectProto], s.engine->objectPrototype()));
Q_ASSERT(s.engine->internalClasses[EngineBase::Class_ObjectProto]->find(s.engine->id_constructor()) == Heap::FunctionObject::Index_ProtoConstructor);
- *proto->propertyData(Heap::FunctionObject::Index_ProtoConstructor) = this->asReturnedValue();
- *propertyData(Heap::FunctionObject::Index_Prototype) = proto.asReturnedValue();
+ proto->setProperty(Heap::FunctionObject::Index_ProtoConstructor, d());
+ setProperty(Heap::FunctionObject::Index_Prototype, proto);
} else {
- *propertyData(Heap::FunctionObject::Index_Prototype) = Encode::undefined();
+ setProperty(Heap::FunctionObject::Index_Prototype, Primitive::undefinedValue());
}
if (n)
- defineReadonlyProperty(s.engine->id_name(), *n);
+ defineReadonlyConfigurableProperty(s.engine->id_name(), *n);
}
ReturnedValue FunctionObject::name() const
@@ -149,15 +151,6 @@ void FunctionObject::call(const Managed *, Scope &scope, CallData *)
scope.result = Encode::undefined();
}
-void FunctionObject::markObjects(Heap::Base *that, ExecutionEngine *e)
-{
- Heap::FunctionObject *o = static_cast<Heap::FunctionObject *>(that);
- if (o->scope)
- o->scope->mark(e);
-
- Object::markObjects(that, e);
-}
-
Heap::FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *scope, Function *function)
{
return scope->engine()->memoryManager->allocObject<ScriptFunction>(scope, function);
@@ -258,10 +251,10 @@ void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor)
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(1));
ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
- defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(0));
+ defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(0));
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("apply"), method_apply, 2);
@@ -309,7 +302,7 @@ void FunctionPrototype::method_apply(const BuiltinFunction *, Scope &scope, Call
cData->args[i] = Primitive::undefinedValue();
} else if (arr->arrayType() == Heap::ArrayData::Simple && !arr->protoHasArray()) {
auto sad = static_cast<Heap::SimpleArrayData *>(arr->arrayData());
- uint alen = sad ? sad->len : 0;
+ uint alen = sad ? sad->values.size : 0;
if (alen > len)
alen = len;
for (uint i = 0; i < alen; ++i)
@@ -352,8 +345,9 @@ void FunctionPrototype::method_bind(const BuiltinFunction *, Scope &scope, CallD
Scoped<MemberData> boundArgs(scope, (Heap::MemberData *)0);
if (callData->argc > 1) {
boundArgs = MemberData::allocate(scope.engine, callData->argc - 1);
- boundArgs->d()->size = callData->argc - 1;
- memcpy(boundArgs->data(), callData->args + 1, (callData->argc - 1)*sizeof(Value));
+ boundArgs->d()->values.size = callData->argc - 1;
+ for (uint i = 0; i < static_cast<uint>(callData->argc - 1); ++i)
+ boundArgs->set(scope.engine, i, callData->args[i + 1]);
}
ExecutionContext *global = scope.engine->rootContext();
@@ -420,7 +414,7 @@ void ScriptFunction::call(const Managed *that, Scope &scope, CallData *callData)
void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function)
{
FunctionObject::init();
- this->scope = scope->d();
+ this->scope.set(scope->engine(), scope->d());
this->function = function;
function->compilationUnit->addref();
@@ -433,7 +427,7 @@ void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function
ScopedString name(s, function->name());
f->init(name, true);
Q_ASSERT(internalClass && internalClass->find(s.engine->id_length()) == Index_Length);
- *propertyData(Index_Length) = Primitive::fromInt32(f->formalParameterCount());
+ setProperty(s.engine, Index_Length, Primitive::fromInt32(f->formalParameterCount()));
if (scope->d()->strictMode) {
ScopedProperty pd(s);
@@ -459,7 +453,6 @@ InternalClass *ScriptFunction::classForConstructor() const
return ic;
}
-
DEFINE_OBJECT_VTABLE(BuiltinFunction);
void Heap::BuiltinFunction::init(QV4::ExecutionContext *scope, QV4::String *name, void (*code)(const QV4::BuiltinFunction *, Scope &, CallData *))
@@ -497,7 +490,7 @@ void IndexedBuiltinFunction::call(const Managed *that, Scope &scope, CallData *c
ExecutionContextSaver ctxSaver(scope);
- CallContext::Data *ctx = v4->memoryManager->allocSimpleCallContext();
+ SimpleCallContext::Data *ctx = v4->memoryManager->allocSimpleCallContext();
ctx->strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
ctx->callData = callData;
v4->pushContext(ctx);
@@ -514,12 +507,12 @@ DEFINE_OBJECT_VTABLE(BoundFunction);
void Heap::BoundFunction::init(QV4::ExecutionContext *scope, QV4::FunctionObject *target,
const Value &boundThis, QV4::MemberData *boundArgs)
{
+ Scope s(scope);
Heap::FunctionObject::init(scope, QStringLiteral("__bound function__"));
- this->target = target->d();
- this->boundArgs = boundArgs ? boundArgs->d() : 0;
- this->boundThis = boundThis;
+ this->target.set(s.engine, target->d());
+ this->boundArgs.set(s.engine, boundArgs ? boundArgs->d() : 0);
+ this->boundThis.set(scope->engine(), boundThis);
- Scope s(scope);
ScopedObject f(s, this);
ScopedValue l(s, target->get(s.engine->id_length()));
@@ -528,7 +521,7 @@ void Heap::BoundFunction::init(QV4::ExecutionContext *scope, QV4::FunctionObject
len -= boundArgs->size();
if (len < 0)
len = 0;
- f->defineReadonlyProperty(s.engine->id_length(), Primitive::fromInt32(len));
+ f->defineReadonlyConfigurableProperty(s.engine->id_length(), Primitive::fromInt32(len));
ScopedProperty pd(s);
pd->value = s.engine->thrower();
@@ -577,14 +570,3 @@ void BoundFunction::construct(const Managed *that, Scope &scope, CallData *dd)
ScopedFunctionObject t(scope, f->target());
t->construct(scope, callData);
}
-
-void BoundFunction::markObjects(Heap::Base *that, ExecutionEngine *e)
-{
- BoundFunction::Data *o = static_cast<BoundFunction::Data *>(that);
- if (o->target)
- o->target->mark(e);
- o->boundThis.mark(e);
- if (o->boundArgs)
- o->boundArgs->mark(e);
- FunctionObject::markObjects(that, e);
-}
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index d691b869fe..6ce5734b6d 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -65,7 +65,12 @@ struct BuiltinFunction;
namespace Heap {
-struct Q_QML_PRIVATE_EXPORT FunctionObject : Object {
+#define FunctionObjectMembers(class, Member) \
+ Member(class, Pointer, ExecutionContext *, scope) \
+ Member(class, NoMark, Function *, function)
+
+DECLARE_HEAP_OBJECT(FunctionObject, Object) {
+ DECLARE_MARK_TABLE(FunctionObject);
enum {
Index_Prototype = 0,
Index_ProtoConstructor = 0
@@ -79,12 +84,8 @@ struct Q_QML_PRIVATE_EXPORT FunctionObject : Object {
unsigned int formalParameterCount() { return function ? function->nFormals : 0; }
unsigned int varCount() { return function ? function->compiledFunction->nLocals : 0; }
- bool needsActivation() const { return function ? function->needsActivation() : false; }
const QV4::Object *protoProperty() const { return propertyData(Index_Prototype)->as<QV4::Object>(); }
-
- Pointer<ExecutionContext> scope;
- Function *function;
};
struct FunctionCtor : FunctionObject {
@@ -121,11 +122,15 @@ struct ScriptFunction : FunctionObject {
QV4::InternalClass *cachedClassForConstructor;
};
-struct BoundFunction : FunctionObject {
+#define BoundFunctionMembers(class, Member) \
+ Member(class, Pointer, FunctionObject *, target) \
+ Member(class, HeapValue, HeapValue, boundThis) \
+ Member(class, Pointer, MemberData *, boundArgs)
+
+DECLARE_HEAP_OBJECT(BoundFunction, FunctionObject) {
+ DECLARE_MARK_TABLE(BoundFunction);
+
void init(QV4::ExecutionContext *scope, QV4::FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs);
- Pointer<FunctionObject> target;
- Value boundThis;
- Pointer<MemberData> boundArgs;
};
}
@@ -156,14 +161,11 @@ struct Q_QML_EXPORT FunctionObject: Object {
static Heap::FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function);
- bool needsActivation() const { return d()->needsActivation(); }
bool strictMode() const { return d()->function ? d()->function->isStrict() : false; }
bool isBinding() const;
bool isBoundFunction() const;
QQmlSourceLocation sourceLocation() const;
-
- static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
template<>
@@ -251,8 +253,6 @@ struct BoundFunction: FunctionObject {
static void construct(const Managed *, Scope &scope, CallData *d);
static void call(const Managed *that, Scope &scope, CallData *dd);
-
- static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
}
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index 3abda68ae6..8769519a59 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -178,6 +178,7 @@ namespace Heap {
struct DataView;
struct TypedArray;
+ template <typename T, size_t> struct Pointer;
}
class MemoryManager;
@@ -192,9 +193,12 @@ struct ScriptFunction;
struct InternalClass;
struct Property;
struct Value;
+template<size_t> struct HeapValue;
+template<size_t> struct ValueArray;
struct Lookup;
struct ArrayData;
struct VTable;
+struct Function;
struct BooleanObject;
struct NumberObject;
@@ -252,6 +256,7 @@ enum PropertyFlag {
Attr_NotEnumerable = 0x4,
Attr_NotConfigurable = 0x8,
Attr_ReadOnly = Attr_NotWritable|Attr_NotEnumerable|Attr_NotConfigurable,
+ Attr_ReadOnly_ButConfigurable = Attr_NotWritable|Attr_NotEnumerable,
Attr_Invalid = 0xff
};
diff --git a/src/qml/jsruntime/qv4identifiertable_p.h b/src/qml/jsruntime/qv4identifiertable_p.h
index 89af5db731..b0b08f1e54 100644
--- a/src/qml/jsruntime/qv4identifiertable_p.h
+++ b/src/qml/jsruntime/qv4identifiertable_p.h
@@ -93,14 +93,14 @@ public:
Heap::String *stringFromIdentifier(Identifier *i);
- void mark(ExecutionEngine *e) {
+ void mark(MarkStack *markStack) {
for (int i = 0; i < alloc; ++i) {
Heap::String *entry = entries[i];
if (!entry || entry->isMarked())
continue;
entry->setMarkBit();
Q_ASSERT(entry->vtable()->markObjects);
- entry->vtable()->markObjects(entry, e);
+ entry->vtable()->markObjects(entry, markStack);
}
}
};
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index 0bcd510541..603da1df7b 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -133,48 +133,20 @@ InternalClass::InternalClass(const QV4::InternalClass &other)
static void insertHoleIntoPropertyData(Object *object, int idx)
{
- int inlineSize = object->d()->vtable()->nInlineProperties;
- int icSize = object->internalClass()->size;
- int from = qMax(idx, inlineSize);
- int to = from + 1;
- if (from < icSize) {
- memmove(object->propertyData(to), object->propertyData(from),
- (icSize - from - 1) * sizeof(Value));
- }
- if (from == idx)
- return;
- if (inlineSize < icSize)
- *object->propertyData(inlineSize) = *object->propertyData(inlineSize - 1);
- from = idx;
- to = from + 1;
- if (from < inlineSize - 1) {
- memmove(object->propertyData(to), object->propertyData(from),
- (inlineSize - from - 1) * sizeof(Value));
- }
+ Heap::Object *o = object->d();
+ ExecutionEngine *v4 = o->internalClass->engine;
+ int size = o->internalClass->size;
+ for (int i = size - 1; i > idx; --i)
+ o->setProperty(v4, i, *o->propertyData(i - 1));
}
static void removeFromPropertyData(Object *object, int idx, bool accessor = false)
{
- int inlineSize = object->d()->vtable()->nInlineProperties;
- int delta = (accessor ? 2 : 1);
- int oldSize = object->internalClass()->size + delta;
- int to = idx;
- int from = to + delta;
- if (from < inlineSize) {
- memmove(object->propertyData(to), object->d()->propertyData(from), (inlineSize - from)*sizeof(Value));
- to = inlineSize - delta;
- from = inlineSize;
- }
- if (to < inlineSize && from < oldSize) {
- Q_ASSERT(from >= inlineSize);
- memcpy(object->propertyData(to), object->d()->propertyData(from), (inlineSize - to)*sizeof(Value));
- to = inlineSize;
- from = inlineSize + delta;
- }
- if (from < oldSize) {
- Q_ASSERT(to >= inlineSize && from > to);
- memmove(object->propertyData(to), object->d()->propertyData(from), (oldSize - to)*sizeof(Value));
- }
+ Heap::Object *o = object->d();
+ ExecutionEngine *v4 = o->internalClass->engine;
+ int size = o->internalClass->size;
+ for (int i = idx; i < size; ++i)
+ o->setProperty(v4, i, *o->propertyData(i + (accessor ? 2 : 1)));
}
void InternalClass::changeMember(Object *object, String *string, PropertyAttributes data, uint *index)
@@ -188,7 +160,7 @@ void InternalClass::changeMember(Object *object, String *string, PropertyAttribu
object->setInternalClass(newClass);
if (newClass->size > oldClass->size) {
Q_ASSERT(newClass->size == oldClass->size + 1);
- insertHoleIntoPropertyData(object, idx + 1);
+ insertHoleIntoPropertyData(object, idx);
} else if (newClass->size < oldClass->size) {
Q_ASSERT(newClass->size == oldClass->size - 1);
removeFromPropertyData(object, idx + 1);
@@ -506,9 +478,9 @@ void InternalClass::destroy()
}
}
-void InternalClassPool::markObjects(ExecutionEngine *engine)
+void InternalClassPool::markObjects(MarkStack *markStack)
{
- InternalClass *ic = engine->internalClasses[EngineBase::Class_Empty];
+ InternalClass *ic = markStack->engine->internalClasses[EngineBase::Class_Empty];
Q_ASSERT(!ic->prototype);
// only need to go two levels into the IC hierarchy, as prototype changes
@@ -519,10 +491,10 @@ void InternalClassPool::markObjects(ExecutionEngine *engine)
InternalClass *ic2 = t.lookup;
for (auto &t2 : ic2->transitions) {
if (t2.flags == InternalClassTransition::PrototypeChange)
- t2.lookup->prototype->mark(engine);
+ t2.lookup->prototype->mark(markStack);
}
} else if (t.flags == InternalClassTransition::PrototypeChange) {
- t.lookup->prototype->mark(engine);
+ t.lookup->prototype->mark(markStack);
}
}
}
diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h
index 9e8ab9e73e..df17074e72 100644
--- a/src/qml/jsruntime/qv4internalclass_p.h
+++ b/src/qml/jsruntime/qv4internalclass_p.h
@@ -64,6 +64,7 @@ struct String;
struct Object;
struct Identifier;
struct VTable;
+struct MarkStack;
struct PropertyHashData;
struct PropertyHash
@@ -305,7 +306,7 @@ private:
struct InternalClassPool : public QQmlJS::MemoryPool
{
- void markObjects(ExecutionEngine *engine);
+ void markObjects(MarkStack *markStack);
};
}
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index 1d571f53f3..0f021c8bd0 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -705,7 +705,7 @@ QString Stringify::Str(const QString &key, const Value &v)
if (replacerFunction) {
ScopedObject holder(scope, v4->newObject());
- holder->put(scope.engine, QString(), scope.result);
+ holder->put(scope.engine->id_empty(), scope.result);
ScopedCallData callData(scope, 2);
callData->args[0] = v4->newString(key);
callData->args[1] = scope.result;
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index faaa5539ab..d943ae1340 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -59,7 +59,7 @@ ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttribu
if (index != UINT_MAX) {
level = i;
*attrs = obj->internalClass->propertyData.at(index);
- Value *v = obj->propertyData(index);
+ const Value *v = obj->propertyData(index);
return !attrs->isAccessor() ? v->asReturnedValue() : Object::getValue(thisObject, *v, *attrs);
}
@@ -72,7 +72,7 @@ ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttribu
index = obj->internalClass->find(name);
if (index != UINT_MAX) {
*attrs = obj->internalClass->propertyData.at(index);
- Value *v = obj->propertyData(index);
+ const Value *v = obj->propertyData(index);
return !attrs->isAccessor() ? v->asReturnedValue() : Object::getValue(thisObject, *v, *attrs);
}
@@ -94,7 +94,7 @@ ReturnedValue Lookup::lookup(const Object *thisObject, PropertyAttributes *attrs
if (index != UINT_MAX) {
level = i;
*attrs = obj->internalClass->propertyData.at(index);
- Value *v = obj->propertyData(index);
+ const Value *v = obj->propertyData(index);
return !attrs->isAccessor() ? v->asReturnedValue() : thisObject->getValue(*v, *attrs);
}
@@ -107,7 +107,7 @@ ReturnedValue Lookup::lookup(const Object *thisObject, PropertyAttributes *attrs
index = obj->internalClass->find(name);
if (index != UINT_MAX) {
*attrs = obj->internalClass->propertyData.at(index);
- Value *v = obj->propertyData(index);
+ const Value *v = obj->propertyData(index);
return !attrs->isAccessor() ? v->asReturnedValue() : thisObject->getValue(*v, *attrs);
}
@@ -116,20 +116,20 @@ ReturnedValue Lookup::lookup(const Object *thisObject, PropertyAttributes *attrs
return Primitive::emptyValue().asReturnedValue();
}
-ReturnedValue Lookup::indexedGetterGeneric(Lookup *l, const Value &object, const Value &index)
+ReturnedValue Lookup::indexedGetterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &index)
{
uint idx;
if (object.isObject() && index.asArrayIndex(idx)) {
l->indexedGetter = indexedGetterObjectInt;
- return indexedGetterObjectInt(l, object, index);
+ return indexedGetterObjectInt(l, engine, object, index);
}
- return indexedGetterFallback(l, object, index);
+ return indexedGetterFallback(l, engine, object, index);
}
-ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const Value &object, const Value &index)
+ReturnedValue Lookup::indexedGetterFallback(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &index)
{
Q_UNUSED(l);
- Scope scope(l->engine);
+ Scope scope(engine);
uint idx = 0;
bool isInt = index.asArrayIndex(idx);
@@ -147,7 +147,7 @@ ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const Value &object, cons
if (object.isNullOrUndefined()) {
QString message = QStringLiteral("Cannot read property '%1' of %2").arg(index.toQStringNoThrow()).arg(object.toQStringNoThrow());
- return l->engine->throwTypeError(message);
+ return engine->throwTypeError(message);
}
o = RuntimeHelpers::convertToObject(scope.engine, object);
@@ -173,7 +173,7 @@ ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const Value &object, cons
}
-ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const Value &object, const Value &index)
+ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &index)
{
uint idx;
if (index.asArrayIndex(idx)) {
@@ -182,7 +182,7 @@ ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const Value &object, con
Heap::Object *o = static_cast<Heap::Object *>(b);
if (o->arrayData && o->arrayData->type == Heap::ArrayData::Simple) {
Heap::SimpleArrayData *s = o->arrayData.cast<Heap::SimpleArrayData>();
- if (idx < s->len)
+ if (idx < s->values.size)
if (!s->data(idx).isEmpty())
return s->data(idx).asReturnedValue();
}
@@ -190,25 +190,25 @@ ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const Value &object, con
}
}
- return indexedGetterFallback(l, object, index);
+ return indexedGetterFallback(l, engine, object, index);
}
-void Lookup::indexedSetterGeneric(Lookup *l, const Value &object, const Value &index, const Value &v)
+void Lookup::indexedSetterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &index, const Value &v)
{
if (Object *o = object.objectValue()) {
uint idx;
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple && index.asArrayIndex(idx)) {
l->indexedSetter = indexedSetterObjectInt;
- indexedSetterObjectInt(l, object, index, v);
+ indexedSetterObjectInt(l, engine, object, index, v);
return;
}
}
- indexedSetterFallback(l, object, index, v);
+ indexedSetterFallback(l, engine, object, index, v);
}
-void Lookup::indexedSetterFallback(Lookup *l, const Value &object, const Value &index, const Value &value)
+void Lookup::indexedSetterFallback(Lookup *, ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)
{
- Scope scope(l->engine);
+ Scope scope(engine);
ScopedObject o(scope, object.toObject(scope.engine));
if (scope.engine->hasException)
return;
@@ -217,8 +217,8 @@ void Lookup::indexedSetterFallback(Lookup *l, const Value &object, const Value &
if (index.asArrayIndex(idx)) {
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>();
- if (idx < s->len) {
- s->data(idx) = value;
+ if (idx < s->values.size) {
+ s->setData(engine, idx, value);
return;
}
}
@@ -230,7 +230,7 @@ void Lookup::indexedSetterFallback(Lookup *l, const Value &object, const Value &
o->put(name, value);
}
-void Lookup::indexedSetterObjectInt(Lookup *l, const Value &object, const Value &index, const Value &v)
+void Lookup::indexedSetterObjectInt(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &index, const Value &v)
{
uint idx;
if (index.asArrayIndex(idx)) {
@@ -239,15 +239,15 @@ void Lookup::indexedSetterObjectInt(Lookup *l, const Value &object, const Value
Heap::Object *o = static_cast<Heap::Object *>(b);
if (o->arrayData && o->arrayData->type == Heap::ArrayData::Simple) {
Heap::SimpleArrayData *s = o->arrayData.cast<Heap::SimpleArrayData>();
- if (idx < s->len) {
- s->data(idx) = v;
+ if (idx < s->values.size) {
+ s->setData(engine, idx, v);
return;
}
}
}
}
}
- indexedSetterFallback(l, object, index, v);
+ indexedSetterFallback(l, engine, object, index, v);
}
ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object)
@@ -379,7 +379,7 @@ ReturnedValue Lookup::getter0MemberData(Lookup *l, ExecutionEngine *engine, cons
Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
if (o) {
if (l->classList[0] == o->internalClass)
- return o->memberData->data[l->index].asReturnedValue();
+ return o->memberData->values.data()[l->index].asReturnedValue();
}
return getterTwoClasses(l, engine, object);
}
@@ -451,7 +451,7 @@ ReturnedValue Lookup::getter0Inlinegetter0MemberData(Lookup *l, ExecutionEngine
if (l->classList[0] == o->internalClass)
return o->inlinePropertyData(l->index)->asReturnedValue();
if (l->classList[2] == o->internalClass)
- return o->memberData->data[l->index2].asReturnedValue();
+ return o->memberData->values.data()[l->index2].asReturnedValue();
}
l->getter = getterFallback;
return getterFallback(l, engine, object);
@@ -464,9 +464,9 @@ ReturnedValue Lookup::getter0MemberDatagetter0MemberData(Lookup *l, ExecutionEng
Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
if (o) {
if (l->classList[0] == o->internalClass)
- return o->memberData->data[l->index].asReturnedValue();
+ return o->memberData->values.data()[l->index].asReturnedValue();
if (l->classList[2] == o->internalClass)
- return o->memberData->data[l->index2].asReturnedValue();
+ return o->memberData->values.data()[l->index2].asReturnedValue();
}
l->getter = getterFallback;
return getterFallback(l, engine, object);
@@ -494,7 +494,7 @@ ReturnedValue Lookup::getter0MemberDatagetter1(Lookup *l, ExecutionEngine *engin
Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
if (o) {
if (l->classList[0] == o->internalClass)
- return o->memberData->data[l->index].asReturnedValue();
+ return o->memberData->values.data()[l->index].asReturnedValue();
if (l->classList[2] == o->internalClass && l->classList[3] == o->prototype()->internalClass)
return o->prototype()->propertyData(l->index2)->asReturnedValue();
}
@@ -610,7 +610,7 @@ ReturnedValue Lookup::primitiveGetter0MemberData(Lookup *l, ExecutionEngine *eng
if (object.type() == l->type) {
Heap::Object *o = l->proto;
if (l->classList[0] == o->internalClass)
- return o->memberData->data[l->index].asReturnedValue();
+ return o->memberData->values.data()[l->index].asReturnedValue();
}
l->getter = getterGeneric;
return getterGeneric(l, engine, object);
@@ -737,7 +737,7 @@ ReturnedValue Lookup::globalGetter0MemberData(Lookup *l, ExecutionEngine *engine
{
Object *o = engine->globalObject;
if (l->classList[0] == o->internalClass())
- return o->d()->memberData->data[l->index].asReturnedValue();
+ return o->d()->memberData->values.data()[l->index].asReturnedValue();
l->globalGetter = globalGetterGeneric;
return globalGetterGeneric(l, engine);
@@ -879,7 +879,7 @@ void Lookup::setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Va
{
Object *o = static_cast<Object *>(object.managed());
if (o && o->internalClass() == l->classList[0]) {
- *o->propertyData(l->index) = value;
+ o->setProperty(engine, l->index, value);
return;
}
@@ -890,7 +890,7 @@ void Lookup::setter0Inline(Lookup *l, ExecutionEngine *engine, Value &object, co
{
Object *o = static_cast<Object *>(object.managed());
if (o && o->internalClass() == l->classList[0]) {
- *o->d()->inlinePropertyData(l->index) = value;
+ o->d()->setInlineProperty(engine, l->index, value);
return;
}
@@ -903,7 +903,7 @@ void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, Value &object, co
if (o && o->internalClass() == l->classList[0]) {
Q_ASSERT(!o->prototype());
o->setInternalClass(l->classList[3]);
- *o->propertyData(l->index) = value;
+ o->setProperty(l->index, value);
return;
}
@@ -920,7 +920,7 @@ void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, co
if (p->internalClass == l->classList[1]) {
Q_ASSERT(!p->prototype());
o->setInternalClass(l->classList[3]);
- *o->propertyData(l->index) = value;
+ o->setProperty(l->index, value);
return;
}
}
@@ -941,7 +941,7 @@ void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, co
if (p->internalClass == l->classList[2]) {
Q_ASSERT(!p->prototype());
o->setInternalClass(l->classList[3]);
- *o->propertyData(l->index) = value;
+ o->setProperty(l->index, value);
return;
}
}
@@ -956,11 +956,11 @@ void Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, c
Object *o = static_cast<Object *>(object.managed());
if (o) {
if (o->internalClass() == l->classList[0]) {
- *o->propertyData(l->index) = value;
+ o->setProperty(l->index, value);
return;
}
if (o->internalClass() == l->classList[1]) {
- *o->propertyData(l->index2) = value;
+ o->setProperty(l->index2, value);
return;
}
}
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index 151231991f..ce5189a780 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -67,14 +67,13 @@ namespace QV4 {
struct Lookup {
enum { Size = 4 };
union {
- ReturnedValue (*indexedGetter)(Lookup *l, const Value &object, const Value &index);
- void (*indexedSetter)(Lookup *l, const Value &object, const Value &index, const Value &v);
+ ReturnedValue (*indexedGetter)(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &index);
+ void (*indexedSetter)(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &index, const Value &v);
ReturnedValue (*getter)(Lookup *l, ExecutionEngine *engine, const Value &object);
ReturnedValue (*globalGetter)(Lookup *l, ExecutionEngine *engine);
void (*setter)(Lookup *l, ExecutionEngine *engine, Value &object, const Value &v);
};
union {
- ExecutionEngine *engine;
InternalClass *classList[Size];
struct {
void *dummy0;
@@ -91,13 +90,13 @@ struct Lookup {
uint index;
uint nameIndex;
- static ReturnedValue indexedGetterGeneric(Lookup *l, const Value &object, const Value &index);
- static ReturnedValue indexedGetterFallback(Lookup *l, const Value &object, const Value &index);
- static ReturnedValue indexedGetterObjectInt(Lookup *l, const Value &object, const Value &index);
+ static ReturnedValue indexedGetterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &index);
+ static ReturnedValue indexedGetterFallback(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &index);
+ static ReturnedValue indexedGetterObjectInt(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &index);
- static void indexedSetterGeneric(Lookup *l, const Value &object, const Value &index, const Value &v);
- static void indexedSetterFallback(Lookup *l, const Value &object, const Value &index, const Value &value);
- static void indexedSetterObjectInt(Lookup *l, const Value &object, const Value &index, const Value &v);
+ static void indexedSetterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &index, const Value &v);
+ static void indexedSetterFallback(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &index, const Value &value);
+ static void indexedSetterObjectInt(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &index, const Value &v);
static ReturnedValue getterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object);
static ReturnedValue getterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object);
@@ -154,7 +153,6 @@ Q_STATIC_ASSERT(std::is_standard_layout<Lookup>::value);
// across 32-bit and 64-bit (matters when cross-compiling).
Q_STATIC_ASSERT(offsetof(Lookup, indexedGetter) == 0);
Q_STATIC_ASSERT(offsetof(Lookup, getter) == 0);
-Q_STATIC_ASSERT(offsetof(Lookup, engine) == offsetof(Lookup, getter) + QT_POINTER_SIZE);
}
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index 200380eda0..e00eaa0d9b 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -49,6 +49,7 @@ const VTable Managed::static_vtbl =
0,
0,
0,
+ 0,
Managed::IsExecutionContext,
Managed::IsString,
Managed::IsObject,
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index 6859334797..40dfc244ea 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -54,6 +54,7 @@
#include "qv4value_p.h"
#include "qv4enginebase_p.h"
#include <private/qv4heap_p.h>
+#include <private/qv4writebarrier_p.h>
QT_BEGIN_NAMESPACE
@@ -92,6 +93,7 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
dptr->_checkIsInitialized(); \
return dptr; \
} \
+ static Q_CONSTEXPR quint64 markTable = QV4::Heap::DataClass::markTable; \
V4_ASSERT_IS_TRIVIAL(QV4::Heap::DataClass)
#define V4_MANAGED(DataClass, superClass) \
@@ -130,6 +132,7 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
#define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \
{ \
parentVTable, \
+ markTable, \
(sizeof(classname::Data) + sizeof(QV4::Value) - 1)/sizeof(QV4::Value), \
(sizeof(classname::Data) + (std::is_same<classname, Object>::value ? 2*sizeof(QV4::Value) : 0) + QV4::Chunk::SlotSize - 1)/QV4::Chunk::SlotSize*QV4::Chunk::SlotSize/sizeof(QV4::Value) \
- (sizeof(classname::Data) + sizeof(QV4::Value) - 1)/sizeof(QV4::Value), \
@@ -143,7 +146,7 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
classname::MyType, \
#classname, \
Q_VTABLE_FUNCTION(classname, destroy), \
- markObjects, \
+ Q_VTABLE_FUNCTION(classname, markObjects), \
isEqualTo \
}
@@ -215,8 +218,10 @@ public:
bool inUse() const { return d()->inUse(); }
bool markBit() const { return d()->isMarked(); }
+ inline void mark(MarkStack *markStack);
static void destroy(Heap::Base *) {}
+ static void markObjects(Heap::Base *, MarkStack *) {}
Q_ALWAYS_INLINE Heap::Base *heapObject() const {
return m();
diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp
index db45c77472..8f862d63e9 100644
--- a/src/qml/jsruntime/qv4memberdata.cpp
+++ b/src/qml/jsruntime/qv4memberdata.cpp
@@ -45,24 +45,19 @@ using namespace QV4;
DEFINE_MANAGED_VTABLE(MemberData);
-void MemberData::markObjects(Heap::Base *that, ExecutionEngine *e)
-{
- Heap::MemberData *m = static_cast<Heap::MemberData *>(that);
- for (uint i = 0; i < m->size; ++i)
- m->data[i].mark(e);
-}
-
Heap::MemberData *MemberData::allocate(ExecutionEngine *e, uint n, Heap::MemberData *old)
{
- Q_ASSERT(!old || old->size < n);
+ Q_ASSERT(!old || old->values.size < n);
Q_ASSERT(n);
size_t alloc = MemoryManager::align(sizeof(Heap::MemberData) + (n - 1)*sizeof(Value));
Heap::MemberData *m = e->memoryManager->allocManaged<MemberData>(alloc);
if (old)
- memcpy(m, old, sizeof(Heap::MemberData) + (old->size - 1)* sizeof(Value));
+ // no write barrier required here
+ memcpy(m, old, sizeof(Heap::MemberData) + (old->values.size - 1) * sizeof(Value));
else
m->init();
- m->size = static_cast<uint>((alloc - sizeof(Heap::MemberData) + sizeof(Value))/sizeof(Value));
+ m->values.alloc = static_cast<uint>((alloc - sizeof(Heap::MemberData) + sizeof(Value))/sizeof(Value));
+ m->values.size = m->values.alloc;
return m;
}
diff --git a/src/qml/jsruntime/qv4memberdata_p.h b/src/qml/jsruntime/qv4memberdata_p.h
index e239458849..bae524d088 100644
--- a/src/qml/jsruntime/qv4memberdata_p.h
+++ b/src/qml/jsruntime/qv4memberdata_p.h
@@ -59,12 +59,11 @@ namespace QV4 {
namespace Heap {
-struct MemberData : Base {
- union {
- uint size;
- double _dummy;
- };
- Value data[1];
+#define MemberDataMembers(class, Member) \
+ Member(class, ValueArray, ValueArray, values)
+
+DECLARE_HEAP_OBJECT(MemberData, Base) {
+ DECLARE_MARK_TABLE(MemberData);
};
V4_ASSERT_IS_TRIVIAL(MemberData)
@@ -75,14 +74,26 @@ struct MemberData : Managed
V4_MANAGED(MemberData, Managed)
V4_INTERNALCLASS(MemberData)
- Value &operator[] (uint idx) { return d()->data[idx]; }
- const Value *data() const { return d()->data; }
- Value *data() { return d()->data; }
- inline uint size() const { return d()->size; }
+ struct Index {
+ Heap::Base *base;
+ Value *slot;
- static Heap::MemberData *allocate(QV4::ExecutionEngine *e, uint n, Heap::MemberData *old = 0);
+ void set(EngineBase *e, Value newVal) {
+ WriteBarrier::write(e, base, slot, newVal);
+ }
+ const Value *operator->() const { return slot; }
+ const Value &operator*() const { return *slot; }
+ bool isNull() const { return !slot; }
+ };
- static void markObjects(Heap::Base *that, ExecutionEngine *e);
+ const Value &operator[] (uint idx) const { return d()->values[idx]; }
+ const Value *data() const { return d()->values.data(); }
+ void set(EngineBase *e, uint index, Value v) { d()->values.set(e, index, v); }
+ void set(EngineBase *e, uint index, Heap::Base *b) { d()->values.set(e, index, b); }
+
+ inline uint size() const { return d()->values.size; }
+
+ static Heap::MemberData *allocate(QV4::ExecutionEngine *e, uint n, Heap::MemberData *old = 0);
};
}
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp
index 09644c161d..8cfa930888 100644
--- a/src/qml/jsruntime/qv4numberobject.cpp
+++ b/src/qml/jsruntime/qv4numberobject.cpp
@@ -102,6 +102,8 @@ void NumberPrototype::init(ExecutionEngine *engine, Object *ctor)
ctor->defineReadonlyProperty(QStringLiteral("POSITIVE_INFINITY"), Primitive::fromDouble(qInf()));
ctor->defineReadonlyProperty(QStringLiteral("MAX_VALUE"), Primitive::fromDouble(1.7976931348623158e+308));
ctor->defineReadonlyProperty(QStringLiteral("EPSILON"), Primitive::fromDouble(std::numeric_limits<double>::epsilon()));
+ ctor->defineReadonlyProperty(QStringLiteral("MAX_SAFE_INTEGER"), Primitive::fromDouble(9007199254740991));
+ ctor->defineReadonlyProperty(QStringLiteral("MIN_SAFE_INTEGER"), Primitive::fromDouble(-9007199254740991));
QT_WARNING_PUSH
QT_WARNING_DISABLE_INTEL(239)
@@ -109,15 +111,17 @@ QT_WARNING_DISABLE_INTEL(239)
QT_WARNING_POP
ctor->defineDefaultProperty(QStringLiteral("isFinite"), method_isFinite, 1);
+ ctor->defineDefaultProperty(QStringLiteral("isInteger"), method_isInteger, 1);
+ ctor->defineDefaultProperty(QStringLiteral("isSafeInteger"), method_isSafeInteger, 1);
ctor->defineDefaultProperty(QStringLiteral("isNaN"), method_isNaN, 1);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString(), method_toString);
+ defineDefaultProperty(engine->id_toString(), method_toString, 1);
defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
defineDefaultProperty(engine->id_valueOf(), method_valueOf);
defineDefaultProperty(QStringLiteral("toFixed"), method_toFixed, 1);
- defineDefaultProperty(QStringLiteral("toExponential"), method_toExponential);
- defineDefaultProperty(QStringLiteral("toPrecision"), method_toPrecision);
+ defineDefaultProperty(QStringLiteral("toExponential"), method_toExponential, 1);
+ defineDefaultProperty(QStringLiteral("toPrecision"), method_toPrecision, 1);
}
inline ReturnedValue thisNumberValue(Scope &scope, CallData *callData)
@@ -155,6 +159,52 @@ void NumberPrototype::method_isFinite(const BuiltinFunction *, Scope &scope, Cal
scope.result = Encode(!std::isnan(v) && !qt_is_inf(v));
}
+void NumberPrototype::method_isInteger(const BuiltinFunction *, Scope &scope, CallData *callData)
+{
+ if (!callData->argc) {
+ scope.result = Encode(false);
+ return;
+ }
+
+ const Value &v = callData->args[0];
+ if (!v.isNumber()) {
+ scope.result = Encode(false);
+ return;
+ }
+
+ double dv = v.toNumber();
+ if (std::isnan(dv) || qt_is_inf(dv)) {
+ scope.result = Encode(false);
+ return;
+ }
+
+ double iv = v.toInteger();
+ scope.result = Encode(dv == iv);
+}
+
+void NumberPrototype::method_isSafeInteger(const BuiltinFunction *, Scope &scope, CallData *callData)
+{
+ if (!callData->argc) {
+ scope.result = Encode(false);
+ return;
+ }
+
+ const Value &v = callData->args[0];
+ if (!v.isNumber()) {
+ scope.result = Encode(false);
+ return;
+ }
+
+ double dv = v.toNumber();
+ if (std::isnan(dv) || qt_is_inf(dv)) {
+ scope.result = Encode(false);
+ return;
+ }
+
+ double iv = v.toInteger();
+ scope.result = Encode(dv == iv && std::fabs(iv) <= (2^53)-1);
+}
+
void NumberPrototype::method_isNaN(const BuiltinFunction *, Scope &scope, CallData *callData)
{
if (!callData->argc) {
diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h
index 85d306020c..0bc2cd8c65 100644
--- a/src/qml/jsruntime/qv4numberobject_p.h
+++ b/src/qml/jsruntime/qv4numberobject_p.h
@@ -89,6 +89,8 @@ struct NumberPrototype: NumberObject
void init(ExecutionEngine *engine, Object *ctor);
static void method_isFinite(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_isInteger(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_isSafeInteger(const BuiltinFunction *, Scope &scope, CallData *callData);
static void method_isNaN(const BuiltinFunction *, Scope &scope, CallData *callData);
static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData);
static void method_toLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData);
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 98f5c7464f..94d5a74fe5 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -67,8 +67,8 @@ void Object::setInternalClass(InternalClass *ic)
return;
bool hasMD = d()->memberData != nullptr;
uint requiredSize = ic->size - nInline;
- if (!hasMD || (hasMD && d()->memberData->size < requiredSize))
- d()->memberData = MemberData::allocate(ic->engine, requiredSize, d()->memberData);
+ if (!(hasMD && requiredSize) || (hasMD && d()->memberData->values.size < requiredSize))
+ d()->memberData.set(ic->engine, MemberData::allocate(ic->engine, requiredSize, d()->memberData));
}
void Object::getProperty(uint index, Property *p, PropertyAttributes *attrs) const
@@ -81,9 +81,9 @@ void Object::getProperty(uint index, Property *p, PropertyAttributes *attrs) con
void Object::setProperty(uint index, const Property *p)
{
- *propertyData(index) = p->value;
+ setProperty(index, p->value);
if (internalClass()->propertyData.at(index).isAccessor())
- *propertyData(index + SetterOffset) = p->set;
+ setProperty(index + SetterOffset, p->set);
}
bool Object::setPrototype(Object *proto)
@@ -99,13 +99,6 @@ bool Object::setPrototype(Object *proto)
return true;
}
-void Object::put(ExecutionEngine *engine, const QString &name, const Value &value)
-{
- Scope scope(engine);
- ScopedString n(scope, engine->newString(name));
- put(n, value);
-}
-
ReturnedValue Object::getValue(const Value &thisObject, const Value &v, PropertyAttributes attrs)
{
if (!attrs.isAccessor())
@@ -121,16 +114,16 @@ ReturnedValue Object::getValue(const Value &thisObject, const Value &v, Property
return scope.result.asReturnedValue();
}
-void Object::putValue(uint memberIndex, const Value &value)
+bool Object::putValue(uint memberIndex, const Value &value)
{
QV4::InternalClass *ic = internalClass();
if (ic->engine->hasException)
- return;
+ return false;
PropertyAttributes attrs = ic->propertyData[memberIndex];
if (attrs.isAccessor()) {
- FunctionObject *set = propertyData(memberIndex + SetterOffset)->as<FunctionObject>();
+ const FunctionObject *set = propertyData(memberIndex + SetterOffset)->as<FunctionObject>();
if (set) {
Scope scope(ic->engine);
ScopedFunctionObject setter(scope, set);
@@ -138,7 +131,7 @@ void Object::putValue(uint memberIndex, const Value &value)
callData->args[0] = value;
callData->thisObject = this;
setter->call(scope, callData);
- return;
+ return !ic->engine->hasException;
}
goto reject;
}
@@ -146,12 +139,13 @@ void Object::putValue(uint memberIndex, const Value &value)
if (!attrs.isWritable())
goto reject;
- *propertyData(memberIndex) = value;
- return;
+ setProperty(memberIndex, value);
+ return true;
reject:
if (engine()->current->strictMode)
engine()->throwTypeError();
+ return false;
}
void Object::defineDefaultProperty(const QString &name, const Value &value)
@@ -169,7 +163,7 @@ void Object::defineDefaultProperty(const QString &name, void (*code)(const Built
ScopedString s(scope, e->newIdentifier(name));
ExecutionContext *global = e->rootContext();
ScopedFunctionObject function(scope, BuiltinFunction::create(global, s, code));
- function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount));
+ function->defineReadonlyConfigurableProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(s, function);
}
@@ -179,7 +173,7 @@ void Object::defineDefaultProperty(String *name, void (*code)(const BuiltinFunct
Scope scope(e);
ExecutionContext *global = e->rootContext();
ScopedFunctionObject function(scope, BuiltinFunction::create(global, name, code));
- function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount));
+ function->defineReadonlyConfigurableProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(name, function);
}
@@ -217,19 +211,27 @@ void Object::defineReadonlyProperty(String *name, const Value &value)
insertMember(name, value, Attr_ReadOnly);
}
-void Object::markObjects(Heap::Base *that, ExecutionEngine *e)
+void Object::defineReadonlyConfigurableProperty(const QString &name, const Value &value)
{
- Heap::Object *o = static_cast<Heap::Object *>(that);
+ QV4::ExecutionEngine *e = engine();
+ Scope scope(e);
+ ScopedString s(scope, e->newIdentifier(name));
+ defineReadonlyConfigurableProperty(s, value);
+}
- if (o->memberData)
- o->memberData->mark(e);
- if (o->arrayData)
- o->arrayData->mark(e);
+void Object::defineReadonlyConfigurableProperty(String *name, const Value &value)
+{
+ insertMember(name, value, Attr_ReadOnly_ButConfigurable);
+}
+
+void Object::markObjects(Heap::Base *b, MarkStack *stack)
+{
+ Heap::Object *o = static_cast<Heap::Object *>(b);
uint nInline = o->vtable()->nInlineProperties;
Value *v = reinterpret_cast<Value *>(o) + o->vtable()->inlinePropertyOffset;
const Value *end = v + nInline;
while (v < end) {
- v->mark(e);
+ v->mark(stack);
++v;
}
}
@@ -240,10 +242,10 @@ void Object::insertMember(String *s, const Property *p, PropertyAttributes attri
InternalClass::addMember(this, s, attributes, &idx);
if (attributes.isAccessor()) {
- *propertyData(idx + GetterOffset) = p->value;
- *propertyData(idx + SetterOffset) = p->set;
+ setProperty(idx + GetterOffset, p->value);
+ setProperty(idx + SetterOffset, p->set);
} else {
- *propertyData(idx) = p->value;
+ setProperty(idx, p->value);
}
}
@@ -275,12 +277,9 @@ void Object::getOwnProperty(String *name, PropertyAttributes *attrs, Property *p
void Object::getOwnProperty(uint index, PropertyAttributes *attrs, Property *p)
{
- Property *pd = arrayData() ? arrayData()->getProperty(index) : 0;
- if (pd) {
- *attrs = arrayData()->attributes(index);
- if (p)
- p->copy(pd, *attrs);
- return;
+ if (arrayData()) {
+ if (arrayData()->getProperty(index, p, attrs))
+ return;
}
if (isStringObject()) {
*attrs = Attr_NotConfigurable|Attr_NotWritable;
@@ -295,7 +294,7 @@ void Object::getOwnProperty(uint index, PropertyAttributes *attrs, Property *p)
}
// Section 8.12.2
-Value *Object::getValueOrSetter(String *name, PropertyAttributes *attrs)
+MemberData::Index Object::getValueOrSetter(String *name, PropertyAttributes *attrs)
{
Q_ASSERT(name->asArrayIndex() == UINT_MAX);
@@ -307,36 +306,38 @@ Value *Object::getValueOrSetter(String *name, PropertyAttributes *attrs)
uint idx = o->internalClass->find(id);
if (idx < UINT_MAX) {
*attrs = o->internalClass->propertyData[idx];
- return o->propertyData(attrs->isAccessor() ? idx + SetterOffset : idx);
+ return o->writablePropertyData(attrs->isAccessor() ? idx + SetterOffset : idx );
}
o = o->prototype();
}
*attrs = Attr_Invalid;
- return 0;
+ return { 0, 0 };
}
-Value *Object::getValueOrSetter(uint index, PropertyAttributes *attrs)
+ArrayData::Index Object::getValueOrSetter(uint index, PropertyAttributes *attrs)
{
Heap::Object *o = d();
while (o) {
- Property *p = o->arrayData ? o->arrayData->getProperty(index) : 0;
- if (p) {
- *attrs = o->arrayData->attributes(index);
- return attrs->isAccessor() ? &p->set : &p->value;
+ if (o->arrayData) {
+ uint idx = o->arrayData->mappedIndex(index);
+ if (idx != UINT_MAX) {
+ *attrs = o->arrayData->attributes(index);
+ return { o->arrayData , attrs->isAccessor() ? idx + SetterOffset : idx };
+ }
}
if (o->vtable()->type == Type_StringObject) {
if (index < static_cast<const Heap::StringObject *>(o)->length()) {
// this is an evil hack, but it works, as the method is only ever called from putIndexed,
// where we don't use the returned pointer there for non writable attributes
*attrs = (Attr_NotWritable|Attr_NotConfigurable);
- return reinterpret_cast<Value *>(0x1);
+ return { reinterpret_cast<Heap::ArrayData *>(0x1), 0 };
}
}
o = o->prototype();
}
*attrs = Attr_Invalid;
- return 0;
+ return { 0, 0 };
}
bool Object::hasProperty(String *name) const
@@ -421,14 +422,14 @@ ReturnedValue Object::getIndexed(const Managed *m, uint index, bool *hasProperty
return static_cast<const Object *>(m)->internalGetIndexed(index, hasProperty);
}
-void Object::put(Managed *m, String *name, const Value &value)
+bool Object::put(Managed *m, String *name, const Value &value)
{
- static_cast<Object *>(m)->internalPut(name, value);
+ return static_cast<Object *>(m)->internalPut(name, value);
}
-void Object::putIndexed(Managed *m, uint index, const Value &value)
+bool Object::putIndexed(Managed *m, uint index, const Value &value)
{
- static_cast<Object *>(m)->internalPutIndexed(index, value);
+ return static_cast<Object *>(m)->internalPutIndexed(index, value);
}
PropertyAttributes Object::query(const Managed *m, String *name)
@@ -524,7 +525,7 @@ void Object::setLookup(Managed *m, Lookup *l, const Value &value)
l->classList[0] = o->internalClass();
l->index = idx;
l->setter = idx < o->d()->vtable()->nInlineProperties ? Lookup::setter0Inline : Lookup::setter0;
- *o->propertyData(idx) = value;
+ o->setProperty(idx, value);
return;
}
@@ -579,7 +580,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *
int k = it->arrayNode->key();
uint pidx = it->arrayNode->value;
Heap::SparseArrayData *sa = o->d()->arrayData.cast<Heap::SparseArrayData>();
- Property *p = reinterpret_cast<Property *>(sa->arrayData + pidx);
+ const Property *p = reinterpret_cast<const Property *>(sa->values.data() + pidx);
it->arrayNode = it->arrayNode->nextNode();
PropertyAttributes a = sa->attrs ? sa->attrs[pidx] : Attr_Data;
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
@@ -594,9 +595,9 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *
it->arrayIndex = UINT_MAX;
}
// dense arrays
- while (it->arrayIndex < o->d()->arrayData->len) {
+ while (it->arrayIndex < o->d()->arrayData->values.size) {
Heap::SimpleArrayData *sa = o->d()->arrayData.cast<Heap::SimpleArrayData>();
- Value &val = sa->data(it->arrayIndex);
+ const Value &val = sa->data(it->arrayIndex);
PropertyAttributes a = o->arrayData()->attributes(it->arrayIndex);
++it->arrayIndex;
if (!val.isEmpty()
@@ -663,15 +664,14 @@ ReturnedValue Object::internalGet(String *name, bool *hasProperty) const
ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) const
{
- Property *pd = 0;
PropertyAttributes attrs;
Scope scope(engine());
ScopedObject o(scope, this);
+ ScopedProperty pd(scope);
+ bool exists = false;
while (o) {
- Property *p = o->arrayData() ? o->arrayData()->getProperty(index) : 0;
- if (p) {
- pd = p;
- attrs = o->arrayData()->attributes(index);
+ if (o->arrayData() && o->arrayData()->getProperty(index, pd, &attrs)) {
+ exists = true;
break;
}
if (o->isStringObject()) {
@@ -686,7 +686,7 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) const
o = o->prototype();
}
- if (pd) {
+ if (exists) {
if (hasProperty)
*hasProperty = true;
return getValue(pd->value, attrs);
@@ -699,10 +699,11 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) const
// Section 8.12.5
-void Object::internalPut(String *name, const Value &value)
+bool Object::internalPut(String *name, const Value &value)
{
- if (internalClass()->engine->hasException)
- return;
+ ExecutionEngine *engine = this->engine();
+ if (engine->hasException)
+ return false;
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
@@ -711,45 +712,46 @@ void Object::internalPut(String *name, const Value &value)
name->makeIdentifier();
Identifier *id = name->identifier();
+ MemberData::Index memberIndex{0, 0};
uint member = internalClass()->find(id);
- Value *v = 0;
PropertyAttributes attrs;
if (member < UINT_MAX) {
attrs = internalClass()->propertyData[member];
- v = propertyData(attrs.isAccessor() ? member + SetterOffset : member);
+ memberIndex = d()->writablePropertyData(attrs.isAccessor() ? member + SetterOffset : member);
}
// clause 1
- if (v) {
+ if (!memberIndex.isNull()) {
if (attrs.isAccessor()) {
- if (v->as<FunctionObject>())
+ if (memberIndex->as<FunctionObject>())
goto cont;
goto reject;
} else if (!attrs.isWritable())
goto reject;
- else if (isArrayObject() && name->equals(engine()->id_length())) {
+ else if (isArrayObject() && name->equals(engine->id_length())) {
bool ok;
uint l = value.asArrayLength(&ok);
if (!ok) {
- engine()->throwRangeError(value);
- return;
+ engine->throwRangeError(value);
+ return false;
}
ok = setArrayLength(l);
if (!ok)
goto reject;
} else {
- *v = value;
+ memberIndex.set(engine, value);
}
- return;
+ return true;
} else if (!prototype()) {
if (!isExtensible())
goto reject;
} else {
// clause 4
- Scope scope(engine());
- if ((v = ScopedObject(scope, prototype())->getValueOrSetter(name, &attrs))) {
+ Scope scope(engine);
+ memberIndex = ScopedObject(scope, prototype())->getValueOrSetter(name, &attrs);
+ if (!memberIndex.isNull()) {
if (attrs.isAccessor()) {
- if (!v->as<FunctionObject>())
+ if (!memberIndex->as<FunctionObject>())
goto reject;
} else if (!isExtensible() || !attrs.isWritable()) {
goto reject;
@@ -762,64 +764,68 @@ void Object::internalPut(String *name, const Value &value)
cont:
// Clause 5
- if (v && attrs.isAccessor()) {
- Q_ASSERT(v->as<FunctionObject>());
+ if (!memberIndex.isNull() && attrs.isAccessor()) {
+ Q_ASSERT(memberIndex->as<FunctionObject>());
- Scope scope(engine());
- ScopedFunctionObject setter(scope, *v);
+ Scope scope(engine);
+ ScopedFunctionObject setter(scope, *memberIndex);
ScopedCallData callData(scope, 1);
callData->args[0] = value;
callData->thisObject = this;
setter->call(scope, callData);
- return;
+ return !internalClass()->engine->hasException;
}
insertMember(name, value);
- return;
+ return true;
reject:
- if (engine()->current->strictMode) {
+ // ### this should be removed once everything is ported to use Object::set()
+ if (engine->current->strictMode) {
QString message = QLatin1String("Cannot assign to read-only property \"") +
name->toQString() + QLatin1Char('\"');
- engine()->throwTypeError(message);
+ engine->throwTypeError(message);
}
+ return false;
}
-void Object::internalPutIndexed(uint index, const Value &value)
+bool Object::internalPutIndexed(uint index, const Value &value)
{
- if (internalClass()->engine->hasException)
- return;
+ ExecutionEngine *engine = this->engine();
+ if (engine->hasException)
+ return false;
PropertyAttributes attrs;
- Value *v = arrayData() ? arrayData()->getValueOrSetter(index, &attrs) : 0;
+ ArrayData::Index arrayIndex = arrayData() ? arrayData()->getValueOrSetter(index, &attrs) : ArrayData::Index{ 0, 0 };
- if (!v && isStringObject()) {
+ if (arrayIndex.isNull() && isStringObject()) {
if (index < static_cast<StringObject *>(this)->length())
// not writable
goto reject;
}
// clause 1
- if (v) {
+ if (!arrayIndex.isNull()) {
if (attrs.isAccessor()) {
- if (v->as<FunctionObject>())
+ if (arrayIndex->as<FunctionObject>())
goto cont;
goto reject;
} else if (!attrs.isWritable())
goto reject;
- else
- *v = value;
- return;
+
+ arrayIndex.set(engine, value);
+ return true;
} else if (!prototype()) {
if (!isExtensible())
goto reject;
} else {
// clause 4
- Scope scope(engine());
- if ((v = ScopedObject(scope, prototype())->getValueOrSetter(index, &attrs))) {
+ Scope scope(engine);
+ arrayIndex = ScopedObject(scope, prototype())->getValueOrSetter(index, &attrs);
+ if (!arrayIndex.isNull()) {
if (attrs.isAccessor()) {
- if (!v->as<FunctionObject>())
+ if (!arrayIndex->as<FunctionObject>())
goto reject;
} else if (!isExtensible() || !attrs.isWritable()) {
goto reject;
@@ -832,24 +838,26 @@ void Object::internalPutIndexed(uint index, const Value &value)
cont:
// Clause 5
- if (v && attrs.isAccessor()) {
- Q_ASSERT(v->as<FunctionObject>());
+ if (!arrayIndex.isNull() && attrs.isAccessor()) {
+ Q_ASSERT(arrayIndex->as<FunctionObject>());
- Scope scope(engine());
- ScopedFunctionObject setter(scope, *v);
+ Scope scope(engine);
+ ScopedFunctionObject setter(scope, *arrayIndex);
ScopedCallData callData(scope, 1);
callData->args[0] = value;
callData->thisObject = this;
setter->call(scope, callData);
- return;
+ return !internalClass()->engine->hasException;
}
arraySet(index, value);
- return;
+ return true;
reject:
- if (engine()->current->strictMode)
- engine()->throwTypeError();
+ // ### this should be removed once everything is ported to use Object::setIndexed()
+ if (engine->current->strictMode)
+ engine->throwTypeError();
+ return false;
}
// Section 8.12.7
@@ -978,8 +986,8 @@ bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Prope
// Clause 1
if (arrayData()) {
- hasProperty = arrayData()->getProperty(index);
- if (!hasProperty && isStringObject())
+ hasProperty = arrayData()->mappedIndex(index) != UINT_MAX;
+ if (!hasProperty && isStringObject())
hasProperty = (index < static_cast<StringObject *>(this)->length());
}
@@ -1091,7 +1099,7 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
setProperty(index, current);
} else {
setArrayAttributes(index, cattrs);
- arrayData()->setProperty(index, current);
+ arrayData()->setProperty(scope.engine, index, current);
}
return true;
reject:
@@ -1127,7 +1135,8 @@ void Object::copyArrayData(Object *other)
;
} else {
Q_ASSERT(!arrayData() && other->arrayData());
- ArrayData::realloc(this, other->d()->arrayData->type, other->d()->arrayData->alloc, false);
+ ArrayData::realloc(this, static_cast<ArrayData::Type>(other->d()->arrayData->type),
+ other->d()->arrayData->values.alloc, false);
if (other->arrayType() == Heap::ArrayData::Sparse) {
Heap::ArrayData *od = other->d()->arrayData;
Heap::ArrayData *dd = d()->arrayData;
@@ -1135,10 +1144,11 @@ void Object::copyArrayData(Object *other)
dd->freeList = od->freeList;
} else {
Heap::ArrayData *dd = d()->arrayData;
- dd->len = other->d()->arrayData->len;
+ dd->values.size = other->d()->arrayData->values.size;
dd->offset = other->d()->arrayData->offset;
}
- memcpy(d()->arrayData->arrayData, other->d()->arrayData->arrayData, other->d()->arrayData->alloc*sizeof(Value));
+ // ### need a write barrier
+ memcpy(d()->arrayData->values.values, other->d()->arrayData->values.values, other->d()->arrayData->values.alloc*sizeof(Value));
}
setArrayLengthUnchecked(other->getLength());
}
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index 9592ff5d1b..066a93cc61 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -67,7 +67,12 @@ struct BuiltinFunction;
namespace Heap {
-struct Object : Base {
+#define ObjectMembers(class, Member) \
+ Member(class, Pointer, MemberData *, memberData) \
+ Member(class, Pointer, ArrayData *, arrayData)
+
+DECLARE_HEAP_OBJECT(Object, Base) {
+ DECLARE_MARK_TABLE(Object);
void init() { Base::init(); }
void destroy() { Base::destroy(); }
@@ -75,9 +80,23 @@ struct Object : Base {
Q_ASSERT(index < vtable()->nInlineProperties);
return reinterpret_cast<const Value *>(this) + vtable()->inlinePropertyOffset + index;
}
- Value *inlinePropertyData(uint index) {
+ void setInlineProperty(ExecutionEngine *e, uint index, Value v) {
+ Q_ASSERT(index < vtable()->nInlineProperties);
+ Value *prop = reinterpret_cast<Value *>(this) + vtable()->inlinePropertyOffset + index;
+ WriteBarrier::write(e, this, prop, v);
+ }
+ void setInlineProperty(ExecutionEngine *e, uint index, Heap::Base *b) {
Q_ASSERT(index < vtable()->nInlineProperties);
- return reinterpret_cast<Value *>(this) + vtable()->inlinePropertyOffset + index;
+ Value *prop = reinterpret_cast<Value *>(this) + vtable()->inlinePropertyOffset + index;
+ WriteBarrier::write(e, this, prop, b);
+ }
+
+ QV4::MemberData::Index writablePropertyData(uint index) {
+ uint nInline = vtable()->nInlineProperties;
+ if (index < nInline)
+ return { this, reinterpret_cast<Value *>(this) + vtable()->inlinePropertyOffset + index};
+ index -= nInline;
+ return { memberData, memberData->values.values + index };
}
const Value *propertyData(uint index) const {
@@ -85,21 +104,32 @@ struct Object : Base {
if (index < nInline)
return reinterpret_cast<const Value *>(this) + vtable()->inlinePropertyOffset + index;
index -= nInline;
- return memberData->data + index;
+ return memberData->values.data() + index;
}
- Value *propertyData(uint index) {
+ void setProperty(ExecutionEngine *e, uint index, Value v) {
uint nInline = vtable()->nInlineProperties;
- if (index < nInline)
- return reinterpret_cast<Value *>(this) + vtable()->inlinePropertyOffset + index;
+ if (index < nInline) {
+ setInlineProperty(e, index, v);
+ return;
+ }
+ index -= nInline;
+ memberData->values.set(e, index, v);
+ }
+ void setProperty(ExecutionEngine *e, uint index, Heap::Base *b) {
+ uint nInline = vtable()->nInlineProperties;
+ if (index < nInline) {
+ setInlineProperty(e, index, b);
+ return;
+ }
index -= nInline;
- return memberData->data + index;
+ memberData->values.set(e, index, b);
}
Heap::Object *prototype() const { return internalClass->prototype; }
- Pointer<MemberData> memberData;
- Pointer<ArrayData> arrayData;
};
+Q_STATIC_ASSERT(Object::markTable == ((2 << 2) | (2 << 4)));
+
}
#define V4_OBJECT(superClass) \
@@ -134,7 +164,8 @@ struct Object : Base {
dptr->_checkIsInitialized(); \
return dptr; \
} \
- V4_ASSERT_IS_TRIVIAL(QV4::Heap::DataClass);
+ V4_ASSERT_IS_TRIVIAL(QV4::Heap::DataClass); \
+ static Q_CONSTEXPR quint64 markTable = QV4::Heap::DataClass::markTable;
#define V4_PROTOTYPE(p) \
static QV4::Object *defaultPrototype(QV4::ExecutionEngine *e) \
@@ -147,8 +178,8 @@ struct ObjectVTable
void (*construct)(const Managed *, Scope &scope, CallData *data);
ReturnedValue (*get)(const Managed *, String *name, bool *hasProperty);
ReturnedValue (*getIndexed)(const Managed *, uint index, bool *hasProperty);
- void (*put)(Managed *, String *name, const Value &value);
- void (*putIndexed)(Managed *, uint index, const Value &value);
+ bool (*put)(Managed *, String *name, const Value &value);
+ bool (*putIndexed)(Managed *, uint index, const Value &value);
PropertyAttributes (*query)(const Managed *, String *name);
PropertyAttributes (*queryIndexed)(const Managed *, uint index);
bool (*deleteProperty)(Managed *m, String *name);
@@ -206,13 +237,16 @@ struct Q_QML_EXPORT Object: Managed {
void setInternalClass(InternalClass *ic);
const Value *propertyData(uint index) const { return d()->propertyData(index); }
- Value *propertyData(uint index) { return d()->propertyData(index); }
Heap::ArrayData *arrayData() const { return d()->arrayData; }
- void setArrayData(ArrayData *a) { d()->arrayData = a->d(); }
+ void setArrayData(ArrayData *a) { d()->arrayData.set(engine(), a->d()); }
void getProperty(uint index, Property *p, PropertyAttributes *attrs) const;
void setProperty(uint index, const Property *p);
+ void setProperty(uint index, Value v) const { d()->setProperty(engine(), index, v); }
+ void setProperty(uint index, Heap::Base *b) const { d()->setProperty(engine(), index, b); }
+ void setProperty(ExecutionEngine *engine, uint index, Value v) const { d()->setProperty(engine, index, v); }
+ void setProperty(ExecutionEngine *engine, uint index, Heap::Base *b) const { d()->setProperty(engine, index, b); }
const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(d()->vtable()); }
Heap::Object *prototype() const { return d()->prototype(); }
@@ -221,8 +255,8 @@ struct Q_QML_EXPORT Object: Managed {
void getOwnProperty(String *name, PropertyAttributes *attrs, Property *p = 0);
void getOwnProperty(uint index, PropertyAttributes *attrs, Property *p = 0);
- Value *getValueOrSetter(String *name, PropertyAttributes *attrs);
- Value *getValueOrSetter(uint index, PropertyAttributes *attrs);
+ MemberData::Index getValueOrSetter(String *name, PropertyAttributes *attrs);
+ ArrayData::Index getValueOrSetter(uint index, PropertyAttributes *attrs);
bool hasProperty(String *name) const;
bool hasProperty(uint index) const;
@@ -239,8 +273,6 @@ struct Q_QML_EXPORT Object: Managed {
//
// helpers
//
- void put(ExecutionEngine *engine, const QString &name, const Value &value);
-
static ReturnedValue getValue(const Value &thisObject, const Value &v, PropertyAttributes attrs);
ReturnedValue getValue(const Value &v, PropertyAttributes attrs) const {
Scope scope(this->engine());
@@ -248,7 +280,7 @@ struct Q_QML_EXPORT Object: Managed {
return getValue(t, v, attrs);
}
- void putValue(uint memberIndex, const Value &value);
+ bool putValue(uint memberIndex, const Value &value);
/* The spec default: Writable: true, Enumerable: false, Configurable: true */
void defineDefaultProperty(String *name, const Value &value) {
@@ -265,6 +297,10 @@ struct Q_QML_EXPORT Object: Managed {
void defineReadonlyProperty(const QString &name, const Value &value);
void defineReadonlyProperty(String *name, const Value &value);
+ /* Fixed: Writable: false, Enumerable: false, Configurable: true */
+ void defineReadonlyConfigurableProperty(const QString &name, const Value &value);
+ void defineReadonlyConfigurableProperty(String *name, const Value &value);
+
void insertMember(String *s, const Value &v, PropertyAttributes attributes = Attr_Data) {
Scope scope(engine());
ScopedProperty p(scope);
@@ -304,7 +340,7 @@ public:
void push_back(const Value &v);
ArrayData::Type arrayType() const {
- return arrayData() ? d()->arrayData->type : Heap::ArrayData::Simple;
+ return arrayData() ? static_cast<ArrayData::Type>(d()->arrayData->type) : Heap::ArrayData::Simple;
}
// ### remove me
void setArrayType(ArrayData::Type t) {
@@ -344,10 +380,47 @@ public:
{ return vtable()->get(this, name, hasProperty); }
inline ReturnedValue getIndexed(uint idx, bool *hasProperty = 0) const
{ return vtable()->getIndexed(this, idx, hasProperty); }
- inline void put(String *name, const Value &v)
- { vtable()->put(this, name, v); }
- inline void putIndexed(uint idx, const Value &v)
- { vtable()->putIndexed(this, idx, v); }
+
+ // use the set variants instead, to customize throw behavior
+ inline bool put(String *name, const Value &v)
+ { return vtable()->put(this, name, v); }
+ inline bool putIndexed(uint idx, const Value &v)
+ { return vtable()->putIndexed(this, idx, v); }
+
+ enum ThrowOnFailure {
+ DoThrowOnRejection,
+ DoNotThrow
+ };
+
+ // ES6: 7.3.3 Set (O, P, V, Throw)
+ inline bool set(String *name, const Value &v, ThrowOnFailure shouldThrow)
+ {
+ bool ret = vtable()->put(this, name, v);
+ // ES6: 7.3.3, 6: If success is false and Throw is true, throw a TypeError exception.
+ if (!ret && shouldThrow == ThrowOnFailure::DoThrowOnRejection) {
+ ExecutionEngine *e = engine();
+ if (!e->hasException) { // allow a custom set impl to throw itself
+ QString message = QLatin1String("Cannot assign to read-only property \"") +
+ name->toQString() + QLatin1Char('\"');
+ e->throwTypeError(message);
+ }
+ }
+ return ret;
+ }
+
+ inline bool setIndexed(uint idx, const Value &v, ThrowOnFailure shouldThrow)
+ {
+ bool ret = vtable()->putIndexed(this, idx, v);
+ if (!ret && shouldThrow == ThrowOnFailure::DoThrowOnRejection) {
+ ExecutionEngine *e = engine();
+ if (!e->hasException) { // allow a custom set impl to throw itself
+ e->throwTypeError();
+ }
+ }
+ return ret;
+ }
+
+
PropertyAttributes query(String *name) const
{ return vtable()->query(this, name); }
PropertyAttributes queryIndexed(uint index) const
@@ -371,13 +444,12 @@ public:
inline void call(Scope &scope, CallData *d) const
{ vtable()->call(this, scope, d); }
protected:
- static void markObjects(Heap::Base *that, ExecutionEngine *e);
static void construct(const Managed *m, Scope &scope, CallData *);
static void call(const Managed *m, Scope &scope, CallData *);
static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
- static void put(Managed *m, String *name, const Value &value);
- static void putIndexed(Managed *m, uint index, const Value &value);
+ static bool put(Managed *m, String *name, const Value &value);
+ static bool putIndexed(Managed *m, uint index, const Value &value);
static PropertyAttributes query(const Managed *m, String *name);
static PropertyAttributes queryIndexed(const Managed *m, uint index);
static bool deleteProperty(Managed *m, String *name);
@@ -387,12 +459,13 @@ protected:
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static uint getLength(const Managed *m);
static ReturnedValue instanceOf(const Object *typeObject, const Value &var);
+ static void markObjects(Heap::Base *, MarkStack *);
private:
ReturnedValue internalGet(String *name, bool *hasProperty) const;
ReturnedValue internalGetIndexed(uint index, bool *hasProperty) const;
- void internalPut(String *name, const Value &value);
- void internalPutIndexed(uint index, const Value &value);
+ bool internalPut(String *name, const Value &value);
+ bool internalPutIndexed(uint index, const Value &value);
bool internalDeleteProperty(String *name);
bool internalDeleteIndexedProperty(uint index);
@@ -436,7 +509,7 @@ struct ArrayObject : Object {
private:
void commonInit()
- { *propertyData(LengthPropertyIndex) = Primitive::fromInt32(0); }
+ { setProperty(internalClass->engine, LengthPropertyIndex, Primitive::fromInt32(0)); }
};
}
@@ -476,7 +549,7 @@ struct ArrayObject: Object {
inline void Object::setArrayLengthUnchecked(uint l)
{
if (isArrayObject())
- *propertyData(Heap::ArrayObject::LengthPropertyIndex) = Primitive::fromUInt32(l);
+ setProperty(Heap::ArrayObject::LengthPropertyIndex, Primitive::fromUInt32(l));
}
inline void Object::push_back(const Value &v)
@@ -493,7 +566,7 @@ inline void Object::arraySet(uint index, const Property *p, PropertyAttributes a
{
// ### Clean up
arrayCreate();
- if (attributes.isAccessor() || (index > 0x1000 && index > 2*d()->arrayData->alloc)) {
+ if (attributes.isAccessor() || (index > 0x1000 && index > 2*d()->arrayData->values.alloc)) {
initSparseArray();
} else {
arrayData()->vtable()->reallocate(this, index + 1, false);
@@ -508,7 +581,7 @@ inline void Object::arraySet(uint index, const Property *p, PropertyAttributes a
inline void Object::arraySet(uint index, const Value &value)
{
arrayCreate();
- if (index > 0x1000 && index > 2*d()->arrayData->alloc) {
+ if (index > 0x1000 && index > 2*d()->arrayData->values.alloc) {
initSparseArray();
}
ArrayData::insert(this, index, &value);
diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index 59115dfe21..3427ee89fe 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -177,10 +177,10 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString()
DEFINE_OBJECT_VTABLE(ForEachIteratorObject);
-void ForEachIteratorObject::markObjects(Heap::Base *that, ExecutionEngine *e)
+void ForEachIteratorObject::markObjects(Heap::Base *that, MarkStack *markStack)
{
ForEachIteratorObject::Data *o = static_cast<ForEachIteratorObject::Data *>(that);
- o->workArea[0].mark(e);
- o->workArea[1].mark(e);
- Object::markObjects(that, e);
+ o->workArea[0].mark(markStack);
+ o->workArea[1].mark(markStack);
+ Object::markObjects(that, markStack);
}
diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h
index 98e94a95ea..6168d59914 100644
--- a/src/qml/jsruntime/qv4objectiterator_p.h
+++ b/src/qml/jsruntime/qv4objectiterator_p.h
@@ -129,7 +129,7 @@ struct ForEachIteratorObject: Object {
ReturnedValue nextPropertyName() { return d()->it().nextPropertyNameAsString(); }
protected:
- static void markObjects(Heap::Base *that, ExecutionEngine *e);
+ static void markObjects(Heap::Base *that, MarkStack *markStack);
};
inline
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index 97dbe24339..2e72c0f13f 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2017 Crimson AS <info@crimson.no>
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
@@ -89,10 +90,11 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
ScopedObject o(scope, this);
ctor->defineReadonlyProperty(v4->id_prototype(), o);
- ctor->defineReadonlyProperty(v4->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyConfigurableProperty(v4->id_length(), Primitive::fromInt32(1));
ctor->defineDefaultProperty(QStringLiteral("getPrototypeOf"), method_getPrototypeOf, 1);
ctor->defineDefaultProperty(QStringLiteral("getOwnPropertyDescriptor"), method_getOwnPropertyDescriptor, 2);
ctor->defineDefaultProperty(QStringLiteral("getOwnPropertyNames"), method_getOwnPropertyNames, 1);
+ ctor->defineDefaultProperty(QStringLiteral("assign"), method_assign, 2);
ctor->defineDefaultProperty(QStringLiteral("create"), method_create, 2);
ctor->defineDefaultProperty(QStringLiteral("defineProperty"), method_defineProperty, 3);
ctor->defineDefaultProperty(QStringLiteral("defineProperties"), method_defineProperties, 2);
@@ -123,9 +125,8 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
void ObjectPrototype::method_getPrototypeOf(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- ScopedObject o(scope, callData->argument(0));
- if (!o)
- THROW_TYPE_ERROR();
+ ScopedObject o(scope, callData->args[0].toObject(scope.engine));
+ CHECK_EXCEPTION();
ScopedObject p(scope, o->prototype());
scope.result = !!p ? p->asReturnedValue() : Encode::null();
@@ -133,11 +134,8 @@ void ObjectPrototype::method_getPrototypeOf(const BuiltinFunction *, Scope &scop
void ObjectPrototype::method_getOwnPropertyDescriptor(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- ScopedObject O(scope, callData->argument(0));
- if (!O) {
- scope.result = scope.engine->throwTypeError();
- return;
- }
+ ScopedObject O(scope, callData->args[0].toObject(scope.engine));
+ CHECK_EXCEPTION();
if (ArgumentsObject::isNonStrictArgumentsObject(O))
static_cast<ArgumentsObject *>(O.getPointer())->fullyCreate();
@@ -154,13 +152,54 @@ void ObjectPrototype::method_getOwnPropertyDescriptor(const BuiltinFunction *, S
void ObjectPrototype::method_getOwnPropertyNames(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- ScopedObject O(scope, callData->argument(0));
- if (!O) {
- scope.result = scope.engine->throwTypeError();
+ ScopedObject O(scope, callData->args[0].toObject(scope.engine));
+ CHECK_EXCEPTION();
+
+ scope.result = getOwnPropertyNames(scope.engine, callData->args[0]);
+}
+
+// 19.1.2.1
+void ObjectPrototype::method_assign(const BuiltinFunction *, Scope &scope, CallData *callData)
+{
+ ScopedObject to(scope, callData->args[0].toObject(scope.engine));
+ CHECK_EXCEPTION();
+
+ if (callData->argc == 1) {
+ scope.result = to;
return;
}
- scope.result = getOwnPropertyNames(scope.engine, callData->args[0]);
+ for (int i = 1; i < callData->argc; ++i) {
+ if (callData->args[i].isUndefined() || callData->args[i].isNull())
+ continue;
+
+ ScopedObject from(scope, callData->args[i].toObject(scope.engine));
+ CHECK_EXCEPTION();
+ QV4::ScopedArrayObject keys(scope, QV4::ObjectPrototype::getOwnPropertyNames(scope.engine, from));
+ quint32 length = keys->getLength();
+
+ ScopedString nextKey(scope);
+ ScopedValue propValue(scope);
+ for (quint32 i = 0; i < length; ++i) {
+ nextKey = Value::fromReturnedValue(keys->getIndexed(i)).toString(scope.engine);
+
+ PropertyAttributes attrs;
+ ScopedProperty prop(scope);
+ from->getOwnProperty(nextKey, &attrs, prop);
+
+ if (attrs == PropertyFlag::Attr_Invalid)
+ continue;
+
+ if (!attrs.isEnumerable())
+ continue;
+
+ propValue = from->get(nextKey);
+ to->set(nextKey, propValue, Object::DoThrowOnRejection);
+ CHECK_EXCEPTION();
+ }
+ }
+
+ scope.result = to;
}
void ObjectPrototype::method_create(const BuiltinFunction *builtin, Scope &scope, CallData *callData)
@@ -246,14 +285,17 @@ void ObjectPrototype::method_defineProperties(const BuiltinFunction *, Scope &sc
void ObjectPrototype::method_seal(const BuiltinFunction *, Scope &scope, CallData *callData)
{
ScopedObject o(scope, callData->argument(0));
- if (!o)
- THROW_TYPE_ERROR();
+ if (!o) {
+ // 19.1.2.17, 1
+ scope.result = callData->argument(0);
+ return;
+ }
o->setInternalClass(o->internalClass()->sealed());
if (o->arrayData()) {
ArrayData::ensureAttributes(o);
- for (uint i = 0; i < o->d()->arrayData->alloc; ++i) {
+ for (uint i = 0; i < o->d()->arrayData->values.alloc; ++i) {
if (!o->arrayData()->isEmpty(i))
o->d()->arrayData->attrs[i].setConfigurable(false);
}
@@ -265,8 +307,11 @@ void ObjectPrototype::method_seal(const BuiltinFunction *, Scope &scope, CallDat
void ObjectPrototype::method_freeze(const BuiltinFunction *, Scope &scope, CallData *callData)
{
ScopedObject o(scope, callData->argument(0));
- if (!o)
- THROW_TYPE_ERROR();
+ if (!o) {
+ // 19.1.2.5, 1
+ scope.result = callData->argument(0);
+ return;
+ }
if (ArgumentsObject::isNonStrictArgumentsObject(o))
static_cast<ArgumentsObject *>(o.getPointer())->fullyCreate();
@@ -275,7 +320,7 @@ void ObjectPrototype::method_freeze(const BuiltinFunction *, Scope &scope, CallD
if (o->arrayData()) {
ArrayData::ensureAttributes(o);
- for (uint i = 0; i < o->arrayData()->alloc; ++i) {
+ for (uint i = 0; i < o->arrayData()->values.alloc; ++i) {
if (!o->arrayData()->isEmpty(i))
o->arrayData()->attrs[i].setConfigurable(false);
if (o->arrayData()->attrs[i].isData())
@@ -287,9 +332,11 @@ void ObjectPrototype::method_freeze(const BuiltinFunction *, Scope &scope, CallD
void ObjectPrototype::method_preventExtensions(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- ScopedObject o(scope, callData->argument(0));
- if (!o)
- THROW_TYPE_ERROR();
+ ScopedObject o(scope, callData->args[0].toObject(scope.engine));
+ if (!o) {
+ scope.result = callData->argument(0);
+ return;
+ }
o->setInternalClass(o->internalClass()->nonExtensible());
scope.result = o;
@@ -297,9 +344,11 @@ void ObjectPrototype::method_preventExtensions(const BuiltinFunction *, Scope &s
void ObjectPrototype::method_isSealed(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- ScopedObject o(scope, callData->argument(0));
- if (!o)
- THROW_TYPE_ERROR();
+ ScopedObject o(scope, callData->args[0].toObject(scope.engine));
+ if (!o) {
+ scope.result = Encode(true);
+ return;
+ }
if (o->isExtensible()) {
scope.result = Encode(false);
@@ -322,7 +371,7 @@ void ObjectPrototype::method_isSealed(const BuiltinFunction *, Scope &scope, Cal
return;
}
- for (uint i = 0; i < o->arrayData()->alloc; ++i) {
+ for (uint i = 0; i < o->arrayData()->values.alloc; ++i) {
if (!o->arrayData()->isEmpty(i))
if (o->arrayData()->attributes(i).isConfigurable()) {
scope.result = Encode(false);
@@ -335,9 +384,11 @@ void ObjectPrototype::method_isSealed(const BuiltinFunction *, Scope &scope, Cal
void ObjectPrototype::method_isFrozen(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- ScopedObject o(scope, callData->argument(0));
- if (!o)
- THROW_TYPE_ERROR();
+ ScopedObject o(scope, callData->args[0].toObject(scope.engine));
+ if (!o) {
+ scope.result = Encode(true);
+ return;
+ }
if (o->isExtensible()) {
scope.result = Encode(false);
@@ -360,7 +411,7 @@ void ObjectPrototype::method_isFrozen(const BuiltinFunction *, Scope &scope, Cal
return;
}
- for (uint i = 0; i < o->arrayData()->alloc; ++i) {
+ for (uint i = 0; i < o->arrayData()->values.alloc; ++i) {
if (!o->arrayData()->isEmpty(i))
if (o->arrayData()->attributes(i).isConfigurable() || o->arrayData()->attributes(i).isWritable()) {
scope.result = Encode(false);
@@ -373,18 +424,19 @@ void ObjectPrototype::method_isFrozen(const BuiltinFunction *, Scope &scope, Cal
void ObjectPrototype::method_isExtensible(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- ScopedObject o(scope, callData->argument(0));
- if (!o)
- THROW_TYPE_ERROR();
+ ScopedObject o(scope, callData->args[0].toObject(scope.engine));
+ if (!o) {
+ scope.result = Encode(false);
+ return;
+ }
scope.result = Encode((bool)o->isExtensible());
}
void ObjectPrototype::method_keys(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- ScopedObject o(scope, callData->argument(0));
- if (!o)
- THROW_TYPE_ERROR();
+ ScopedObject o(scope, callData->args[0].toObject(scope.engine));
+ CHECK_EXCEPTION();
ScopedArrayObject a(scope, scope.engine->newArrayObject());
@@ -670,12 +722,12 @@ ReturnedValue ObjectPrototype::fromPropertyDescriptor(ExecutionEngine *engine, c
return o.asReturnedValue();
}
-
+// es6: GetOwnPropertyKeys
Heap::ArrayObject *ObjectPrototype::getOwnPropertyNames(ExecutionEngine *v4, const Value &o)
{
Scope scope(v4);
ScopedArrayObject array(scope, v4->newArrayObject());
- ScopedObject O(scope, o);
+ ScopedObject O(scope, o.toObject(v4));
if (O) {
ObjectIterator it(scope, O, ObjectIterator::NoFlags);
ScopedValue name(scope);
diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h
index 1db8615511..44b54267f3 100644
--- a/src/qml/jsruntime/qv4objectproto_p.h
+++ b/src/qml/jsruntime/qv4objectproto_p.h
@@ -81,6 +81,7 @@ struct ObjectPrototype: Object
static void method_getPrototypeOf(const BuiltinFunction *, Scope &scope, CallData *callData);
static void method_getOwnPropertyDescriptor(const BuiltinFunction *, Scope &scope, CallData *callData);
static void method_getOwnPropertyNames(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_assign(const BuiltinFunction *, Scope &scope, CallData *callData);
static void method_create(const BuiltinFunction *, Scope &scope, CallData *callData);
static void method_defineProperty(const BuiltinFunction *, Scope &scope, CallData *callData);
static void method_defineProperties(const BuiltinFunction *, Scope &scope, CallData *callData);
diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp
index 987c322e47..0b31c971f9 100644
--- a/src/qml/jsruntime/qv4persistent.cpp
+++ b/src/qml/jsruntime/qv4persistent.cpp
@@ -215,26 +215,15 @@ void PersistentValueStorage::free(Value *v)
freePage(p);
}
-static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase)
+void PersistentValueStorage::mark(MarkStack *markStack)
{
- while (engine->jsStackTop > markBase) {
- Heap::Base *h = engine->popForGC();
- Q_ASSERT (h->vtable()->markObjects);
- h->vtable()->markObjects(h, engine);
- }
-}
-
-void PersistentValueStorage::mark(ExecutionEngine *e)
-{
- Value *markBase = e->jsStackTop;
-
Page *p = static_cast<Page *>(firstPage);
while (p) {
for (int i = 0; i < kEntriesPerPage; ++i) {
if (Managed *m = p->values[i].as<Managed>())
- m->mark(e);
+ m->mark(markStack);
}
- drainMarkStack(e, markBase);
+ markStack->drain();
p = p->header.next;
}
@@ -393,11 +382,11 @@ void WeakValue::allocVal(ExecutionEngine *engine)
val = engine->memoryManager->m_weakValues->allocate();
}
-void WeakValue::markOnce(ExecutionEngine *e)
+void WeakValue::markOnce(MarkStack *markStack)
{
if (!val)
return;
- val->mark(e);
+ val->mark(markStack);
}
void WeakValue::free()
diff --git a/src/qml/jsruntime/qv4persistent_p.h b/src/qml/jsruntime/qv4persistent_p.h
index c1cd1f34df..1f838f5531 100644
--- a/src/qml/jsruntime/qv4persistent_p.h
+++ b/src/qml/jsruntime/qv4persistent_p.h
@@ -65,7 +65,7 @@ struct Q_QML_EXPORT PersistentValueStorage
Value *allocate();
static void free(Value *e);
- void mark(ExecutionEngine *e);
+ void mark(MarkStack *markStack);
struct Iterator {
Iterator(void *p, int idx);
@@ -203,7 +203,7 @@ public:
bool isNullOrUndefined() const { return !val || val->isNullOrUndefined(); }
void clear() { free(); }
- void markOnce(ExecutionEngine *e);
+ void markOnce(MarkStack *markStack);
private:
Value *val;
diff --git a/src/qml/jsruntime/qv4property_p.h b/src/qml/jsruntime/qv4property_p.h
index 5069d7690b..2a5b6f7f74 100644
--- a/src/qml/jsruntime/qv4property_p.h
+++ b/src/qml/jsruntime/qv4property_p.h
@@ -78,12 +78,6 @@ struct Property {
attrs->resolve();
}
- static Property genericDescriptor() {
- Property pd;
- pd.value = Primitive::emptyValue();
- return pd;
- }
-
inline bool isSubset(const PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs) const;
inline void merge(PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs);
@@ -99,19 +93,12 @@ struct Property {
}
explicit Property() { value = Encode::undefined(); set = Value::fromHeapObject(0); }
- explicit Property(Value v) : value(v) { set = Value::fromHeapObject(0); }
- Property(FunctionObject *getter, FunctionObject *setter) {
- value = reinterpret_cast<Managed *>(getter);
- set = reinterpret_cast<Managed *>(setter);
- }
Property(Heap::FunctionObject *getter, Heap::FunctionObject *setter) {
value.setM(reinterpret_cast<Heap::Base *>(getter));
set.setM(reinterpret_cast<Heap::Base *>(setter));
}
- Property &operator=(Value v) { value = v; return *this; }
private:
- Property(const Property &);
- Property &operator=(const Property &);
+ Q_DISABLE_COPY(Property)
};
inline bool Property::isSubset(const PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs) const
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp
index 91d65a70c9..89770d269a 100644
--- a/src/qml/jsruntime/qv4qmlcontext.cpp
+++ b/src/qml/jsruntime/qv4qmlcontext.cpp
@@ -59,10 +59,10 @@ QT_BEGIN_NAMESPACE
using namespace QV4;
-DEFINE_OBJECT_VTABLE(QmlContextWrapper);
+DEFINE_OBJECT_VTABLE(QQmlContextWrapper);
DEFINE_MANAGED_VTABLE(QmlContext);
-void Heap::QmlContextWrapper::init(QQmlContextData *context, QObject *scopeObject, bool ownsContext)
+void Heap::QQmlContextWrapper::init(QQmlContextData *context, QObject *scopeObject, bool ownsContext)
{
Object::init();
readOnly = true;
@@ -72,7 +72,7 @@ void Heap::QmlContextWrapper::init(QQmlContextData *context, QObject *scopeObjec
this->scopeObject.init(scopeObject);
}
-void Heap::QmlContextWrapper::destroy()
+void Heap::QQmlContextWrapper::destroy()
{
if (*context && ownsContext)
(*context)->destroy();
@@ -81,10 +81,10 @@ void Heap::QmlContextWrapper::destroy()
Object::destroy();
}
-ReturnedValue QmlContextWrapper::get(const Managed *m, String *name, bool *hasProperty)
+ReturnedValue QQmlContextWrapper::get(const Managed *m, String *name, bool *hasProperty)
{
- Q_ASSERT(m->as<QmlContextWrapper>());
- const QmlContextWrapper *resource = static_cast<const QmlContextWrapper *>(m);
+ Q_ASSERT(m->as<QQmlContextWrapper>());
+ const QQmlContextWrapper *resource = static_cast<const QQmlContextWrapper *>(m);
QV4::ExecutionEngine *v4 = resource->engine();
QV4::Scope scope(v4);
@@ -134,7 +134,7 @@ ReturnedValue QmlContextWrapper::get(const Managed *m, String *name, bool *hasPr
if (context->imports && name->startsWithUpper()) {
// Search for attached properties, enums and imported scripts
- QQmlTypeNameCache::Result r = context->imports->query(name);
+ QQmlTypeNameCache::Result r = context->imports->query(name, QQmlImport::AllowRecursion);
if (r.isValid()) {
if (hasProperty)
@@ -143,9 +143,9 @@ ReturnedValue QmlContextWrapper::get(const Managed *m, String *name, bool *hasPr
QV4::ScopedObject scripts(scope, context->importedScripts.valueRef());
return scripts->getIndexed(r.scriptIndex);
} else if (r.type) {
- return QmlTypeWrapper::create(v4, scopeObject, r.type);
+ return QQmlTypeWrapper::create(v4, scopeObject, r.type);
} else if (r.importNamespace) {
- return QmlTypeWrapper::create(v4, scopeObject, context->imports, r.importNamespace);
+ return QQmlTypeWrapper::create(v4, scopeObject, context->imports, r.importNamespace);
}
Q_ASSERT(!"Unreachable");
}
@@ -225,21 +225,19 @@ ReturnedValue QmlContextWrapper::get(const Managed *m, String *name, bool *hasPr
return Encode::undefined();
}
-void QmlContextWrapper::put(Managed *m, String *name, const Value &value)
+bool QQmlContextWrapper::put(Managed *m, String *name, const Value &value)
{
- Q_ASSERT(m->as<QmlContextWrapper>());
- QmlContextWrapper *resource = static_cast<QmlContextWrapper *>(m);
+ Q_ASSERT(m->as<QQmlContextWrapper>());
+ QQmlContextWrapper *resource = static_cast<QQmlContextWrapper *>(m);
ExecutionEngine *v4 = resource->engine();
QV4::Scope scope(v4);
if (scope.hasException())
- return;
- QV4::Scoped<QmlContextWrapper> wrapper(scope, resource);
+ return false;
+ QV4::Scoped<QQmlContextWrapper> wrapper(scope, resource);
uint member = wrapper->internalClass()->find(name);
- if (member < UINT_MAX) {
- wrapper->putValue(member, value);
- return;
- }
+ if (member < UINT_MAX)
+ return wrapper->putValue(member, value);
if (wrapper->d()->isNullWrapper) {
if (wrapper && wrapper->d()->readOnly) {
@@ -247,11 +245,10 @@ void QmlContextWrapper::put(Managed *m, String *name, const Value &value)
QLatin1Char('"');
ScopedString e(scope, v4->newString(error));
v4->throwError(e);
- return;
+ return false;
}
- Object::put(m, name, value);
- return;
+ return Object::put(m, name, value);
}
// Its possible we could delay the calculation of the "actual" context (in the case
@@ -260,7 +257,7 @@ void QmlContextWrapper::put(Managed *m, String *name, const Value &value)
QQmlContextData *expressionContext = context;
if (!context)
- return;
+ return false;
// See QV8ContextWrapper::Getter for resolution order
@@ -270,18 +267,18 @@ void QmlContextWrapper::put(Managed *m, String *name, const Value &value)
const QV4::IdentifierHash<int> &properties = context->propertyNames();
// Search context properties
if (properties.count() && properties.value(name) != -1)
- return;
+ return false;
// Search scope object
if (scopeObject &&
QV4::QObjectWrapper::setQmlProperty(v4, context, scopeObject, name, QV4::QObjectWrapper::CheckRevision, value))
- return;
+ return true;
scopeObject = 0;
// Search context object
if (context->contextObject &&
QV4::QObjectWrapper::setQmlProperty(v4, context, context->contextObject, name, QV4::QObjectWrapper::CheckRevision, value))
- return;
+ return true;
context = context->parent;
}
@@ -292,23 +289,23 @@ void QmlContextWrapper::put(Managed *m, String *name, const Value &value)
QString error = QLatin1String("Invalid write to global property \"") + name->toQString() +
QLatin1Char('"');
v4->throwError(error);
- return;
+ return false;
}
- Object::put(m, name, value);
+ return Object::put(m, name, value);
}
-void Heap::QmlContext::init(QV4::ExecutionContext *outerContext, QV4::QmlContextWrapper *qml)
+void Heap::QmlContext::init(QV4::ExecutionContext *outerContext, QV4::QQmlContextWrapper *qml)
{
Heap::ExecutionContext::init(Heap::ExecutionContext::Type_QmlContext);
- outer = outerContext->d();
+ outer.set(internalClass->engine, outerContext->d());
strictMode = false;
callData = outer->callData;
lookups = outer->lookups;
constantTable = outer->constantTable;
compilationUnit = outer->compilationUnit;
- this->qml = qml->d();
+ this->qml.set(internalClass->engine, qml->d());
}
Heap::QmlContext *QmlContext::createWorkerContext(ExecutionContext *parent, const QUrl &source, Value *sendFunction)
@@ -321,7 +318,7 @@ Heap::QmlContext *QmlContext::createWorkerContext(ExecutionContext *parent, cons
context->isInternal = true;
context->isJSContext = true;
- Scoped<QmlContextWrapper> qml(scope, scope.engine->memoryManager->allocObject<QmlContextWrapper>(context, (QObject*)0, true));
+ Scoped<QQmlContextWrapper> qml(scope, scope.engine->memoryManager->allocObject<QQmlContextWrapper>(context, (QObject*)0, true));
qml->d()->isNullWrapper = true;
qml->setReadOnly(false);
@@ -339,7 +336,7 @@ Heap::QmlContext *QmlContext::create(ExecutionContext *parent, QQmlContextData *
{
Scope scope(parent);
- Scoped<QmlContextWrapper> qml(scope, scope.engine->memoryManager->allocObject<QmlContextWrapper>(context, scopeObject));
+ Scoped<QQmlContextWrapper> qml(scope, scope.engine->memoryManager->allocObject<QQmlContextWrapper>(context, scopeObject));
Heap::QmlContext *c = scope.engine->memoryManager->alloc<QmlContext>(parent, qml);
Q_ASSERT(c->vtable() == staticVTable());
return c;
diff --git a/src/qml/jsruntime/qv4qmlcontext_p.h b/src/qml/jsruntime/qv4qmlcontext_p.h
index 9aec7467da..2f1dbabaf2 100644
--- a/src/qml/jsruntime/qv4qmlcontext_p.h
+++ b/src/qml/jsruntime/qv4qmlcontext_p.h
@@ -62,11 +62,11 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-struct QmlContextWrapper;
+struct QQmlContextWrapper;
namespace Heap {
-struct QmlContextWrapper : Object {
+struct QQmlContextWrapper : Object {
void init(QQmlContextData *context, QObject *scopeObject, bool ownsContext = false);
void destroy();
bool readOnly;
@@ -77,17 +77,20 @@ struct QmlContextWrapper : Object {
QQmlQPointer<QObject> scopeObject;
};
-struct QmlContext : ExecutionContext {
- void init(QV4::ExecutionContext *outerContext, QV4::QmlContextWrapper *qml);
+#define QmlContextMembers(class, Member) \
+ Member(class, Pointer, QQmlContextWrapper *, qml)
- Pointer<QmlContextWrapper> qml;
+DECLARE_HEAP_OBJECT(QmlContext, ExecutionContext) {
+ DECLARE_MARK_TABLE(QmlContext);
+
+ void init(QV4::ExecutionContext *outerContext, QV4::QQmlContextWrapper *qml);
};
}
-struct Q_QML_EXPORT QmlContextWrapper : Object
+struct Q_QML_EXPORT QQmlContextWrapper : Object
{
- V4_OBJECT2(QmlContextWrapper, Object)
+ V4_OBJECT2(QQmlContextWrapper, Object)
V4_NEEDS_DESTROY
void takeContextOwnership() {
@@ -100,7 +103,7 @@ struct Q_QML_EXPORT QmlContextWrapper : Object
void setReadOnly(bool b) { d()->readOnly = b; }
static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
- static void put(Managed *m, String *name, const Value &value);
+ static bool put(Managed *m, String *name, const Value &value);
};
struct Q_QML_EXPORT QmlContext : public ExecutionContext
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index d7978cc212..91650f16e2 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -74,9 +74,14 @@
#include <QtCore/qtimer.h>
#include <QtCore/qatomic.h>
#include <QtCore/qmetaobject.h>
+#include <QtCore/qabstractitemmodel.h>
+#include <QtCore/qloggingcategory.h>
+#include <vector>
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcBindingRemoval, "qt.qml.binding.removal", QtWarningMsg)
+
// The code in this file does not violate strict aliasing, but GCC thinks it does
// so turn off the warnings for us to have a clean build
QT_WARNING_DISABLE_GCC("-Wstrict-aliasing")
@@ -202,19 +207,61 @@ void QObjectWrapper::initializeBindings(ExecutionEngine *engine)
QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const
{
+ QObject *o = d()->object();
+ return findProperty(engine, o, qmlContext, name, revisionMode, local);
+}
+
+QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QObject *o, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local)
+{
Q_UNUSED(revisionMode);
- QQmlData *ddata = QQmlData::get(d()->object(), false);
- if (!ddata)
- return 0;
+ QQmlData *ddata = QQmlData::get(o, false);
QQmlPropertyData *result = 0;
if (ddata && ddata->propertyCache)
- result = ddata->propertyCache->property(name, d()->object(), qmlContext);
+ result = ddata->propertyCache->property(name, o, qmlContext);
else
- result = QQmlPropertyCache::property(engine->jsEngine(), d()->object(), name, qmlContext, *local);
+ result = QQmlPropertyCache::property(engine->jsEngine(), o, name, qmlContext, *local);
return result;
}
+ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, bool captureRequired)
+{
+ QQmlData::flushPendingBinding(object, QQmlPropertyIndex(property->coreIndex()));
+
+ if (property->isFunction() && !property->isVarProperty()) {
+ if (property->isVMEFunction()) {
+ QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
+ Q_ASSERT(vmemo);
+ return vmemo->vmeMethod(property->coreIndex());
+ } else if (property->isV4Function()) {
+ Scope scope(engine);
+ ScopedContext global(scope, engine->qmlContext());
+ if (!global)
+ global = engine->rootContext();
+ return QV4::QObjectMethod::create(global, object, property->coreIndex());
+ } else if (property->isSignalHandler()) {
+ QmlSignalHandler::initProto(engine);
+ return engine->memoryManager->allocObject<QV4::QmlSignalHandler>(object, property->coreIndex())->asReturnedValue();
+ } else {
+ ExecutionContext *global = engine->rootContext();
+ return QV4::QObjectMethod::create(global, object, property->coreIndex());
+ }
+ }
+
+ QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
+
+ if (captureRequired && ep && ep->propertyCapture && !property->isConstant())
+ ep->propertyCapture->captureProperty(object, property->coreIndex(), property->notifyIndex());
+
+ if (property->isVarProperty()) {
+ QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
+ Q_ASSERT(vmemo);
+ return vmemo->vmeProperty(property->coreIndex());
+ } else {
+ return loadProperty(engine, object, *property);
+ }
+}
+
ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String *name, QObjectWrapper::RevisionMode revisionMode,
bool *hasProperty, bool includeImports) const
{
@@ -250,11 +297,11 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
if (r.scriptIndex != -1) {
return QV4::Encode::undefined();
} else if (r.type) {
- return QmlTypeWrapper::create(v4, d()->object(),
- r.type, Heap::QmlTypeWrapper::ExcludeEnums);
+ return QQmlTypeWrapper::create(v4, d()->object(),
+ r.type, Heap::QQmlTypeWrapper::ExcludeEnums);
} else if (r.importNamespace) {
- return QmlTypeWrapper::create(v4, d()->object(),
- qmlContext->imports, r.importNamespace, Heap::QmlTypeWrapper::ExcludeEnums);
+ return QQmlTypeWrapper::create(v4, d()->object(),
+ qmlContext->imports, r.importNamespace, Heap::QQmlTypeWrapper::ExcludeEnums);
}
Q_ASSERT(!"Unreachable");
}
@@ -279,42 +326,19 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
return getProperty(v4, d()->object(), result);
}
-ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, bool captureRequired)
+ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, bool captureRequired)
{
- QQmlData::flushPendingBinding(object, QQmlPropertyIndex(property->coreIndex()));
-
- if (property->isFunction() && !property->isVarProperty()) {
- if (property->isVMEFunction()) {
- QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
- Q_ASSERT(vmemo);
- return vmemo->vmeMethod(property->coreIndex());
- } else if (property->isV4Function()) {
- Scope scope(engine);
- ScopedContext global(scope, engine->qmlContext());
- if (!global)
- global = engine->rootContext();
- return QV4::QObjectMethod::create(global, object, property->coreIndex());
- } else if (property->isSignalHandler()) {
- QmlSignalHandler::initProto(engine);
- return engine->memoryManager->allocObject<QV4::QmlSignalHandler>(object, property->coreIndex())->asReturnedValue();
- } else {
- ExecutionContext *global = engine->rootContext();
- return QV4::QObjectMethod::create(global, object, property->coreIndex());
- }
- }
-
- QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
-
- if (captureRequired && ep && ep->propertyCapture && !property->isConstant())
- ep->propertyCapture->captureProperty(object, property->coreIndex(), property->notifyIndex());
+ if (QQmlData::wasDeleted(object))
+ return QV4::Encode::null();
+ QQmlData *ddata = QQmlData::get(object, /*create*/false);
+ if (!ddata)
+ return QV4::Encode::undefined();
- if (property->isVarProperty()) {
- QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
- Q_ASSERT(vmemo);
- return vmemo->vmeProperty(property->coreIndex());
- } else {
- return loadProperty(engine, object, *property);
- }
+ QQmlPropertyCache *cache = ddata->propertyCache;
+ Q_ASSERT(cache);
+ QQmlPropertyData *property = cache->property(propertyIndex);
+ Q_ASSERT(property); // We resolved this property earlier, so it better exist!
+ return getProperty(engine, object, property, captureRequired);
}
ReturnedValue QObjectWrapper::getQmlProperty(QV4::ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, QObjectWrapper::RevisionMode revisionMode, bool *hasProperty)
@@ -325,12 +349,49 @@ ReturnedValue QObjectWrapper::getQmlProperty(QV4::ExecutionEngine *engine, QQmlC
return QV4::Encode::null();
}
- if (!QQmlData::get(object, true)) {
+ if (name->equals(engine->id_destroy()) || name->equals(engine->id_toString())) {
+ int index = name->equals(engine->id_destroy()) ? QV4::QObjectMethod::DestroyMethod : QV4::QObjectMethod::ToStringMethod;
if (hasProperty)
- *hasProperty = false;
- return QV4::Encode::null();
+ *hasProperty = true;
+ ExecutionContext *global = engine->rootContext();
+ return QV4::QObjectMethod::create(global, object, index);
+ }
+
+ QQmlData *ddata = QQmlData::get(object, false);
+ QQmlPropertyData local;
+ QQmlPropertyData *result = findProperty(engine, object, qmlContext, name, revisionMode, &local);
+
+ if (result) {
+ if (revisionMode == QV4::QObjectWrapper::CheckRevision && result->hasRevision()) {
+ if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result)) {
+ if (hasProperty)
+ *hasProperty = false;
+ return QV4::Encode::undefined();
+ }
+ }
+
+ if (hasProperty)
+ *hasProperty = true;
+
+ return getProperty(engine, object, result);
+ } else {
+ // Check if this object is already wrapped.
+ if (!ddata || (ddata->jsWrapper.isUndefined() &&
+ (ddata->jsEngineId == 0 || // Nobody owns the QObject
+ !ddata->hasTaintedV4Object))) { // Someone else has used the QObject, but it isn't tainted
+
+ // Not wrapped. Last chance: try query QObjectWrapper's prototype.
+ // If it can't handle this, then there is no point
+ // to wrap the QObject just to look at an empty set of JS props.
+ QV4::Object *proto = QObjectWrapper::defaultPrototype(engine);
+ return proto->get(name, hasProperty);
+ }
}
+ // If we get here, we must already be wrapped (which implies a ddata).
+ // There's no point wrapping again, as there wouldn't be any new props.
+ Q_ASSERT(ddata);
+
QV4::Scope scope(engine);
QV4::Scoped<QObjectWrapper> wrapper(scope, wrap(engine, object));
if (!wrapper) {
@@ -341,6 +402,7 @@ ReturnedValue QObjectWrapper::getQmlProperty(QV4::ExecutionEngine *engine, QQmlC
return wrapper->getQmlProperty(qmlContext, name, revisionMode, hasProperty);
}
+
bool QObjectWrapper::setQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name,
QObjectWrapper::RevisionMode revisionMode, const Value &value)
{
@@ -399,10 +461,23 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
}
}
- if (newBinding)
+ if (newBinding) {
QQmlPropertyPrivate::setBinding(newBinding);
- else
+ } else {
+ if (Q_UNLIKELY(lcBindingRemoval().isInfoEnabled())) {
+ if (auto binding = QQmlPropertyPrivate::binding(object, QQmlPropertyIndex(property->coreIndex()))) {
+ Q_ASSERT(!binding->isValueTypeProxy());
+ const auto qmlBinding = static_cast<const QQmlBinding*>(binding);
+ const auto stackFrame = engine->currentStackFrame();
+ qCInfo(lcBindingRemoval,
+ "Overwriting binding on %s::%s at %s:%d that was initially bound at %s",
+ object->metaObject()->className(), qPrintable(property->name(object)),
+ qPrintable(stackFrame.source), stackFrame.line,
+ qPrintable(qmlBinding->expressionIdentifier()));
+ }
+ }
QQmlPropertyPrivate::removeBinding(object, QQmlPropertyIndex(property->coreIndex()));
+ }
if (!newBinding && property->isVarProperty()) {
// allow assignment of "special" values (null, undefined, function) to var properties
@@ -539,7 +614,7 @@ ReturnedValue QObjectWrapper::wrap_slowPath(ExecutionEngine *engine, QObject *ob
}
}
-void QObjectWrapper::markWrapper(QObject *object, ExecutionEngine *engine)
+void QObjectWrapper::markWrapper(QObject *object, MarkStack *markStack)
{
if (QQmlData::wasDeleted(object))
return;
@@ -548,25 +623,10 @@ void QObjectWrapper::markWrapper(QObject *object, ExecutionEngine *engine)
if (!ddata)
return;
- if (ddata->jsEngineId == engine->m_engineId)
- ddata->jsWrapper.markOnce(engine);
- else if (engine->m_multiplyWrappedQObjects && ddata->hasTaintedV4Object)
- engine->m_multiplyWrappedQObjects->mark(object, engine);
-}
-
-ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, bool captureRequired)
-{
- if (QQmlData::wasDeleted(object))
- return QV4::Encode::null();
- QQmlData *ddata = QQmlData::get(object, /*create*/false);
- if (!ddata)
- return QV4::Encode::undefined();
-
- QQmlPropertyCache *cache = ddata->propertyCache;
- Q_ASSERT(cache);
- QQmlPropertyData *property = cache->property(propertyIndex);
- Q_ASSERT(property); // We resolved this property earlier, so it better exist!
- return getProperty(engine, object, property, captureRequired);
+ if (ddata->jsEngineId == markStack->engine->m_engineId)
+ ddata->jsWrapper.markOnce(markStack);
+ else if (markStack->engine->m_multiplyWrappedQObjects && ddata->hasTaintedV4Object)
+ markStack->engine->m_multiplyWrappedQObjects->mark(object, markStack);
}
void QObjectWrapper::setProperty(ExecutionEngine *engine, int propertyIndex, const Value &value)
@@ -598,7 +658,7 @@ bool QObjectWrapper::isEqualTo(Managed *a, Managed *b)
QV4::QObjectWrapper *qobjectWrapper = static_cast<QV4::QObjectWrapper *>(a);
QV4::Object *o = b->as<Object>();
if (o) {
- if (QV4::QmlTypeWrapper *qmlTypeWrapper = o->as<QV4::QmlTypeWrapper>())
+ if (QV4::QQmlTypeWrapper *qmlTypeWrapper = o->as<QV4::QQmlTypeWrapper>())
return qmlTypeWrapper->toVariant().value<QObject*>() == qobjectWrapper->object();
}
@@ -625,13 +685,13 @@ QV4::ReturnedValue QObjectWrapper::get(const Managed *m, String *name, bool *has
return that->getQmlProperty(qmlContext, name, IgnoreRevision, hasProperty, /*includeImports*/ true);
}
-void QObjectWrapper::put(Managed *m, String *name, const Value &value)
+bool QObjectWrapper::put(Managed *m, String *name, const Value &value)
{
QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
ExecutionEngine *v4 = that->engine();
if (v4->hasException || QQmlData::wasDeleted(that->d()->object()))
- return;
+ return false;
QQmlContextData *qmlContext = v4->callingQmlContext();
if (!setQmlProperty(v4, qmlContext, that->d()->object(), name, QV4::QObjectWrapper::IgnoreRevision, value)) {
@@ -642,10 +702,13 @@ void QObjectWrapper::put(Managed *m, String *name, const Value &value)
QString error = QLatin1String("Cannot assign to non-existent property \"") +
name->toQString() + QLatin1Char('\"');
v4->throwError(error);
+ return false;
} else {
- QV4::Object::put(m, name, value);
+ return QV4::Object::put(m, name, value);
}
}
+
+ return true;
}
PropertyAttributes QObjectWrapper::query(const Managed *m, String *name)
@@ -935,36 +998,36 @@ void QObjectWrapper::method_disconnect(const BuiltinFunction *, Scope &scope, Ca
RETURN_UNDEFINED();
}
-static void markChildQObjectsRecursively(QObject *parent, QV4::ExecutionEngine *e)
+static void markChildQObjectsRecursively(QObject *parent, QV4::MarkStack *markStack)
{
const QObjectList &children = parent->children();
for (int i = 0; i < children.count(); ++i) {
QObject *child = children.at(i);
if (!child)
continue;
- QObjectWrapper::markWrapper(child, e);
- markChildQObjectsRecursively(child, e);
+ QObjectWrapper::markWrapper(child, markStack);
+ markChildQObjectsRecursively(child, markStack);
}
}
-void QObjectWrapper::markObjects(Heap::Base *that, QV4::ExecutionEngine *e)
+void QObjectWrapper::markObjects(Heap::Base *that, QV4::MarkStack *markStack)
{
QObjectWrapper::Data *This = static_cast<QObjectWrapper::Data *>(that);
if (QObject *o = This->object()) {
QQmlVMEMetaObject *vme = QQmlVMEMetaObject::get(o);
if (vme)
- vme->mark(e);
+ vme->mark(markStack);
// Children usually don't need to be marked, the gc keeps them alive.
// But in the rare case of a "floating" QObject without a parent that
// _gets_ marked (we've been called here!) then we also need to
// propagate the marking down to the children recursively.
if (!o->parent())
- markChildQObjectsRecursively(o, e);
+ markChildQObjectsRecursively(o, markStack);
}
- QV4::Object::markObjects(that, e);
+ QV4::Object::markObjects(that, markStack);
}
void QObjectWrapper::destroyObject(bool lastCall)
@@ -1030,12 +1093,21 @@ private:
inline void cleanup();
+ template <class T, class M>
+ void fromContainerValue(const QV4::Object *object, int type, M CallArgument::*member, bool &queryEngine);
+
union {
float floatValue;
double doubleValue;
quint32 intValue;
bool boolValue;
QObject *qobjectPtr;
+ std::vector<int> *stdVectorIntPtr;
+ std::vector<qreal> *stdVectorRealPtr;
+ std::vector<bool> *stdVectorBoolPtr;
+ std::vector<QString> *stdVectorQStringPtr;
+ std::vector<QUrl> *stdVectorQUrlPtr;
+ std::vector<QModelIndex> *stdVectorQModelIndexPtr;
char allocData[MaxSizeOf8<QVariant,
QString,
@@ -1465,6 +1537,18 @@ void *CallArgument::dataPtr()
{
if (type == -1)
return qvariantPtr->data();
+ else if (type == qMetaTypeId<std::vector<int>>())
+ return stdVectorIntPtr;
+ else if (type == qMetaTypeId<std::vector<qreal>>())
+ return stdVectorRealPtr;
+ else if (type == qMetaTypeId<std::vector<bool>>())
+ return stdVectorBoolPtr;
+ else if (type == qMetaTypeId<std::vector<QString>>())
+ return stdVectorQStringPtr;
+ else if (type == qMetaTypeId<std::vector<QUrl>>())
+ return stdVectorQUrlPtr;
+ else if (type == qMetaTypeId<std::vector<QModelIndex>>())
+ return stdVectorQModelIndexPtr;
else if (type != 0)
return (void *)&allocData;
return 0;
@@ -1514,6 +1598,19 @@ void CallArgument::initAsType(int callType)
}
}
+template <class T, class M>
+void CallArgument::fromContainerValue(const QV4::Object *object, int callType, M CallArgument::*member, bool &queryEngine)
+{
+ if (object && object->isListType()) {
+ T* ptr = static_cast<T*>(QV4::SequencePrototype::getRawContainerPtr(object, callType));
+ if (ptr) {
+ (this->*member) = ptr;
+ type = callType;
+ queryEngine = false;
+ }
+ }
+}
+
void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const QV4::Value &value)
{
if (type != 0) {
@@ -1552,7 +1649,7 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
qobjectPtr = 0;
if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
qobjectPtr = qobjectWrapper->object();
- else if (const QV4::QmlTypeWrapper *qmlTypeWrapper = value.as<QV4::QmlTypeWrapper>())
+ else if (const QV4::QQmlTypeWrapper *qmlTypeWrapper = value.as<QV4::QQmlTypeWrapper>())
queryEngine = qmlTypeWrapper->isSingleton();
type = callType;
} else if (callType == qMetaTypeId<QVariant>()) {
@@ -1595,6 +1692,33 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
type = callType;
} else if (callType == QMetaType::Void) {
*qvariantPtr = QVariant();
+ } else if (callType == qMetaTypeId<std::vector<int>>()
+ || callType == qMetaTypeId<std::vector<qreal>>()
+ || callType == qMetaTypeId<std::vector<bool>>()
+ || callType == qMetaTypeId<std::vector<QString>>()
+ || callType == qMetaTypeId<std::vector<QUrl>>()
+ || callType == qMetaTypeId<std::vector<QModelIndex>>()) {
+ queryEngine = true;
+ const QV4::Object* object = value.as<Object>();
+ if (callType == qMetaTypeId<std::vector<int>>()) {
+ stdVectorIntPtr = nullptr;
+ fromContainerValue<std::vector<int>>(object, callType, &CallArgument::stdVectorIntPtr, queryEngine);
+ } else if (callType == qMetaTypeId<std::vector<qreal>>()) {
+ stdVectorRealPtr = nullptr;
+ fromContainerValue<std::vector<qreal>>(object, callType, &CallArgument::stdVectorRealPtr, queryEngine);
+ } else if (callType == qMetaTypeId<std::vector<bool>>()) {
+ stdVectorBoolPtr = nullptr;
+ fromContainerValue<std::vector<bool>>(object, callType, &CallArgument::stdVectorBoolPtr, queryEngine);
+ } else if (callType == qMetaTypeId<std::vector<QString>>()) {
+ stdVectorQStringPtr = nullptr;
+ fromContainerValue<std::vector<QString>>(object, callType, &CallArgument::stdVectorQStringPtr, queryEngine);
+ } else if (callType == qMetaTypeId<std::vector<QUrl>>()) {
+ stdVectorQUrlPtr = nullptr;
+ fromContainerValue<std::vector<QUrl>>(object, callType, &CallArgument::stdVectorQUrlPtr, queryEngine);
+ } else if (callType == qMetaTypeId<std::vector<QModelIndex>>()) {
+ stdVectorQModelIndexPtr = nullptr;
+ fromContainerValue<std::vector<QModelIndex>>(object, callType, &CallArgument::stdVectorQModelIndexPtr, queryEngine);
+ }
} else {
queryEngine = true;
}
@@ -1704,7 +1828,7 @@ ReturnedValue QObjectMethod::create(ExecutionContext *scope, const QQmlValueType
Scoped<QObjectMethod> method(valueScope, valueScope.engine->memoryManager->allocObject<QObjectMethod>(scope));
method->d()->setPropertyCache(valueType->d()->propertyCache());
method->d()->index = index;
- method->d()->valueTypeWrapper = valueType->d();
+ method->d()->valueTypeWrapper.set(valueScope.engine, valueType->d());
return method.asReturnedValue();
}
@@ -1841,15 +1965,6 @@ void QObjectMethod::callInternal(CallData *callData, Scope &scope) const
}
}
-void QObjectMethod::markObjects(Heap::Base *that, ExecutionEngine *e)
-{
- QObjectMethod::Data *This = static_cast<QObjectMethod::Data*>(that);
- if (This->valueTypeWrapper)
- This->valueTypeWrapper->mark(e);
-
- FunctionObject::markObjects(that, e);
-}
-
DEFINE_OBJECT_VTABLE(QObjectMethod);
@@ -2075,12 +2190,12 @@ void MultiplyWrappedQObjectMap::remove(QObject *key)
erase(it);
}
-void MultiplyWrappedQObjectMap::mark(QObject *key, ExecutionEngine *engine)
+void MultiplyWrappedQObjectMap::mark(QObject *key, MarkStack *markStack)
{
Iterator it = find(key);
if (it == end())
return;
- it->markOnce(engine);
+ it->markOnce(markStack);
}
void MultiplyWrappedQObjectMap::removeDestroyedObject(QObject *object)
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 6494c20bd2..018e444f7c 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -95,7 +95,15 @@ private:
QQmlQPointer<QObject> qObj;
};
-struct QObjectMethod : FunctionObject {
+#define QObjectMethodMembers(class, Member) \
+ Member(class, Pointer, QQmlValueTypeWrapper *, valueTypeWrapper) \
+ Member(class, NoMark, QQmlQPointer<QObject>, qObj) \
+ Member(class, NoMark, QQmlPropertyCache *, _propertyCache) \
+ Member(class, NoMark, int, index)
+
+DECLARE_HEAP_OBJECT(QObjectMethod, FunctionObject) {
+ DECLARE_MARK_TABLE(QObjectMethod);
+
void init(QV4::ExecutionContext *scope);
void destroy()
{
@@ -113,18 +121,10 @@ struct QObjectMethod : FunctionObject {
_propertyCache = c;
}
- Pointer<QQmlValueTypeWrapper> valueTypeWrapper;
-
const QMetaObject *metaObject();
QObject *object() const { return qObj.data(); }
void setObject(QObject *o) { qObj = o; }
-private:
- QQmlQPointer<QObject> qObj;
- QQmlPropertyCache *_propertyCache;
-
-public:
- int index;
};
struct QMetaObjectWrapper : FunctionObject {
@@ -171,7 +171,7 @@ struct Q_QML_EXPORT QObjectWrapper : public Object
static bool setQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, const Value &value);
static ReturnedValue wrap(ExecutionEngine *engine, QObject *object);
- static void markWrapper(QObject *object, ExecutionEngine *engine);
+ static void markWrapper(QObject *object, MarkStack *markStack);
using Object::get;
@@ -189,13 +189,14 @@ protected:
static ReturnedValue create(ExecutionEngine *engine, QObject *object);
+ static QQmlPropertyData *findProperty(ExecutionEngine *engine, QObject *o, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local);
QQmlPropertyData *findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const;
static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
- static void put(Managed *m, String *name, const Value &value);
+ static bool put(Managed *m, String *name, const Value &value);
static PropertyAttributes query(const Managed *, String *name);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
- static void markObjects(Heap::Base *that, QV4::ExecutionEngine *e);
+ static void markObjects(Heap::Base *that, QV4::MarkStack *markStack);
static void method_connect(const BuiltinFunction *, Scope &scope, CallData *callData);
static void method_disconnect(const BuiltinFunction *, Scope &scope, CallData *callData);
@@ -240,8 +241,6 @@ struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject
void callInternal(CallData *callData, Scope &scope) const;
- static void markObjects(Heap::Base *that, QV4::ExecutionEngine *e);
-
static QPair<QObject *, int> extractQtMethod(const QV4::FunctionObject *function);
};
@@ -294,7 +293,7 @@ public:
ReturnedValue value(QObject *key) const { return QHash<QObject*, QV4::WeakValue>::value(key).value(); }
Iterator erase(Iterator it);
void remove(QObject *key);
- void mark(QObject *key, ExecutionEngine *engine);
+ void mark(QObject *key, MarkStack *markStack);
private Q_SLOTS:
void removeDestroyedObject(QObject*);
diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp
index 9e94c58432..6778145ff1 100644
--- a/src/qml/jsruntime/qv4regexp.cpp
+++ b/src/qml/jsruntime/qv4regexp.cpp
@@ -126,9 +126,3 @@ void Heap::RegExp::destroy()
delete pattern;
Base::destroy();
}
-
-void RegExp::markObjects(Heap::Base *that, ExecutionEngine *e)
-{
- Q_UNUSED(that);
- Q_UNUSED(e);
-}
diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h
index 04cdb468bf..7ab12fe245 100644
--- a/src/qml/jsruntime/qv4regexp_p.h
+++ b/src/qml/jsruntime/qv4regexp_p.h
@@ -120,8 +120,6 @@ struct RegExp : public Managed
int captureCount() const { return subPatternCount() + 1; }
- static void markObjects(Heap::Base *that, QV4::ExecutionEngine *e);
-
friend class RegExpCache;
};
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 1f758e36f6..735951e085 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -74,17 +74,17 @@ void Heap::RegExpObject::init()
Object::init();
Scope scope(internalClass->engine);
Scoped<QV4::RegExpObject> o(scope, this);
- o->d()->value = QV4::RegExp::create(scope.engine, QString(), false, false);
- o->d()->global = false;
+ value.set(scope.engine, QV4::RegExp::create(scope.engine, QString(), false, false));
+ global = false;
o->initProperties();
}
void Heap::RegExpObject::init(QV4::RegExp *value, bool global)
{
Object::init();
- this->global = global;
- this->value = value->d();
Scope scope(internalClass->engine);
+ this->global = global;
+ this->value.set(scope.engine, value->d());
Scoped<QV4::RegExpObject> o(scope, this);
o->initProperties();
}
@@ -137,14 +137,15 @@ void Heap::RegExpObject::init(const QRegExp &re)
Scope scope(internalClass->engine);
Scoped<QV4::RegExpObject> o(scope, this);
- o->d()->value = QV4::RegExp::create(scope.engine, pattern, re.caseSensitivity() == Qt::CaseInsensitive, false);
+ o->d()->value.set(scope.engine,
+ QV4::RegExp::create(scope.engine, pattern, re.caseSensitivity() == Qt::CaseInsensitive, false));
o->initProperties();
}
void RegExpObject::initProperties()
{
- *propertyData(Index_LastIndex) = Primitive::fromInt32(0);
+ setProperty(Index_LastIndex, Primitive::fromInt32(0));
Q_ASSERT(value());
@@ -156,25 +157,10 @@ void RegExpObject::initProperties()
p.replace('/', QLatin1String("\\/"));
}
- *propertyData(Index_Source) = engine()->newString(p);
- *propertyData(Index_Global) = Primitive::fromBoolean(global());
- *propertyData(Index_IgnoreCase) = Primitive::fromBoolean(value()->ignoreCase);
- *propertyData(Index_Multiline) = Primitive::fromBoolean(value()->multiLine);
-}
-
-
-void RegExpObject::markObjects(Heap::Base *that, ExecutionEngine *e)
-{
- RegExpObject::Data *re = static_cast<RegExpObject::Data *>(that);
- if (re->value)
- re->value->mark(e);
- Object::markObjects(that, e);
-}
-
-Value *RegExpObject::lastIndexProperty()
-{
- Q_ASSERT(0 == internalClass()->find(engine()->id_lastIndex()));
- return propertyData(0);
+ setProperty(Index_Source, engine()->newString(p));
+ setProperty(Index_Global, Primitive::fromBoolean(global()));
+ setProperty(Index_IgnoreCase, Primitive::fromBoolean(value()->ignoreCase));
+ setProperty(Index_Multiline, Primitive::fromBoolean(value()->multiLine));
}
// Converts a JS RegExp to a QRegExp.
@@ -228,8 +214,8 @@ void Heap::RegExpCtor::init(QV4::ExecutionContext *scope)
void Heap::RegExpCtor::clearLastMatch()
{
- lastMatch = Primitive::nullValue();
- lastInput = internalClass->engine->id_empty()->d();
+ lastMatch.set(internalClass->engine, Primitive::nullValue());
+ lastInput.set(internalClass->engine, internalClass->engine->id_empty()->d());
lastMatchStart = 0;
lastMatchEnd = 0;
}
@@ -303,15 +289,6 @@ void RegExpCtor::call(const Managed *that, Scope &scope, CallData *callData)
construct(that, scope, callData);
}
-void RegExpCtor::markObjects(Heap::Base *that, ExecutionEngine *e)
-{
- RegExpCtor::Data *This = static_cast<RegExpCtor::Data *>(that);
- This->lastMatch.mark(e);
- if (This->lastInput)
- This->lastInput->mark(e);
- FunctionObject::markObjects(that, e);
-}
-
void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor)
{
Scope scope(engine);
@@ -361,9 +338,9 @@ void RegExpPrototype::method_exec(const BuiltinFunction *, Scope &scope, CallDat
RETURN_UNDEFINED();
QString s = str->toQString();
- int offset = r->global() ? r->lastIndexProperty()->toInt32() : 0;
+ int offset = r->global() ? r->lastIndex() : 0;
if (offset < 0 || offset > s.length()) {
- *r->lastIndexProperty() = Primitive::fromInt32(0);
+ r->setLastIndex(0);
RETURN_RESULT(Encode::null());
}
@@ -374,7 +351,7 @@ void RegExpPrototype::method_exec(const BuiltinFunction *, Scope &scope, CallDat
regExpCtor->d()->clearLastMatch();
if (result == -1) {
- *r->lastIndexProperty() = Primitive::fromInt32(0);
+ r->setLastIndex(0);
RETURN_RESULT(Encode::null());
}
@@ -390,17 +367,17 @@ void RegExpPrototype::method_exec(const BuiltinFunction *, Scope &scope, CallDat
array->arrayPut(i, v);
}
array->setArrayLengthUnchecked(len);
- *array->propertyData(Index_ArrayIndex) = Primitive::fromInt32(result);
- *array->propertyData(Index_ArrayInput) = str;
+ array->setProperty(Index_ArrayIndex, Primitive::fromInt32(result));
+ array->setProperty(Index_ArrayInput, str);
RegExpCtor::Data *dd = regExpCtor->d();
- dd->lastMatch = array;
- dd->lastInput = str->d();
+ dd->lastMatch.set(scope.engine, array);
+ dd->lastInput.set(scope.engine, str->d());
dd->lastMatchStart = matchOffsets[0];
dd->lastMatchEnd = matchOffsets[1];
if (r->global())
- *r->lastIndexProperty() = Primitive::fromInt32(matchOffsets[1]);
+ r->setLastIndex(matchOffsets[1]);
scope.result = array;
}
@@ -432,7 +409,7 @@ void RegExpPrototype::method_compile(const BuiltinFunction *, Scope &scope, Call
scope.engine->regExpCtor()->as<FunctionObject>()->construct(scope, cData);
Scoped<RegExpObject> re(scope, scope.result.asReturnedValue());
- r->d()->value = re->value();
+ r->d()->value.set(scope.engine, re->value());
r->d()->global = re->global();
RETURN_UNDEFINED();
}
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index 54731cef14..6f54a4ab92 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -73,21 +73,28 @@ namespace QV4 {
namespace Heap {
-struct RegExpObject : Object {
+#define RegExpObjectMembers(class, Member) \
+ Member(class, Pointer, RegExp *, value) \
+ Member(class, NoMark, bool, global)
+
+DECLARE_HEAP_OBJECT(RegExpObject, Object) {
+ DECLARE_MARK_TABLE(RegExpObject);
+
void init();
void init(QV4::RegExp *value, bool global);
void init(const QRegExp &re);
-
- Pointer<RegExp> value;
- bool global;
};
-struct RegExpCtor : FunctionObject {
+#define RegExpCtorMembers(class, Member) \
+ Member(class, HeapValue, HeapValue, lastMatch) \
+ Member(class, Pointer, String *, lastInput) \
+ Member(class, NoMark, int, lastMatchStart) \
+ Member(class, NoMark, int, lastMatchEnd)
+
+DECLARE_HEAP_OBJECT(RegExpCtor, FunctionObject) {
+ DECLARE_MARK_TABLE(RegExpCtor);
+
void init(QV4::ExecutionContext *scope);
- Value lastMatch;
- Pointer<String> lastInput;
- int lastMatchStart;
- int lastMatchEnd;
void clearLastMatch();
};
@@ -121,14 +128,19 @@ struct RegExpObject: Object {
void initProperties();
- Value *lastIndexProperty();
+ int lastIndex() const {
+ Q_ASSERT(Index_LastIndex == internalClass()->find(engine()->id_lastIndex()));
+ return propertyData(Index_LastIndex)->toInt32();
+ }
+ void setLastIndex(int index) {
+ Q_ASSERT(Index_LastIndex == internalClass()->find(engine()->id_lastIndex()));
+ return setProperty(Index_LastIndex, Primitive::fromInt32(index));
+ }
+
QRegExp toQRegExp() const;
QString toString() const;
QString source() const;
uint flags() const;
-
-protected:
- static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
struct RegExpCtor: FunctionObject
@@ -142,7 +154,6 @@ struct RegExpCtor: FunctionObject
static void construct(const Managed *m, Scope &scope, CallData *callData);
static void call(const Managed *that, Scope &scope, CallData *callData);
- static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
struct RegExpPrototype: RegExpObject
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index ecf2fd8b11..9737a18812 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -663,7 +663,7 @@ ReturnedValue Runtime::method_getElement(ExecutionEngine *engine, const Value &o
Heap::Object *o = static_cast<Heap::Object *>(b);
if (o->arrayData && o->arrayData->type == Heap::ArrayData::Simple) {
Heap::SimpleArrayData *s = o->arrayData.cast<Heap::SimpleArrayData>();
- if (idx < s->len)
+ if (idx < s->values.size)
if (!s->data(idx).isEmpty())
return s->data(idx).asReturnedValue();
}
@@ -686,8 +686,8 @@ static Q_NEVER_INLINE void setElementFallback(ExecutionEngine *engine, const Val
if (index.asArrayIndex(idx)) {
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>();
- if (idx < s->len) {
- s->data(idx) = value;
+ if (idx < s->values.size) {
+ s->setData(engine, idx, value);
return;
}
}
@@ -708,8 +708,8 @@ void Runtime::method_setElement(ExecutionEngine *engine, const Value &object, co
Heap::Object *o = static_cast<Heap::Object *>(b);
if (o->arrayData && o->arrayData->type == Heap::ArrayData::Simple) {
Heap::SimpleArrayData *s = o->arrayData.cast<Heap::SimpleArrayData>();
- if (idx < s->len) {
- s->data(idx) = value;
+ if (idx < s->values.size) {
+ s->setData(engine, idx, value);
return;
}
}
@@ -1375,7 +1375,7 @@ ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, const QV4::
}
for (uint i = 0; i < klass->size; ++i)
- *o->propertyData(i) = *args++;
+ o->setProperty(i, *args++);
if (arrayValueCount > 0) {
ScopedValue entry(scope);
@@ -1516,7 +1516,7 @@ ReturnedValue Runtime::method_getQmlContextObjectProperty(ExecutionEngine *engin
ReturnedValue Runtime::method_getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired)
{
Scope scope(engine);
- QV4::Scoped<QmlTypeWrapper> wrapper(scope, object);
+ QV4::Scoped<QQmlTypeWrapper> wrapper(scope, object);
if (!wrapper) {
scope.engine->throwTypeError(QStringLiteral("Cannot read property of null"));
return Encode::undefined();
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index 8ce10e326d..8afc672aa2 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -78,13 +78,22 @@ static void generateWarning(QV4::ExecutionEngine *v4, const QString& description
F(int, IntVector, QVector<int>, 0) \
F(qreal, RealVector, QVector<qreal>, 0.0) \
F(bool, BoolVector, QVector<bool>, false) \
+ F(int, IntStdVector, std::vector<int>, 0) \
+ F(qreal, RealStdVector, std::vector<qreal>, 0.0) \
+ F(bool, BoolStdVector, std::vector<bool>, false) \
F(int, Int, QList<int>, 0) \
F(qreal, Real, QList<qreal>, 0.0) \
F(bool, Bool, QList<bool>, false) \
F(QString, String, QList<QString>, QString()) \
F(QString, QString, QStringList, QString()) \
+ F(QString, StringVector, QVector<QString>, QString()) \
+ F(QString, StringStdVector, std::vector<QString>, QString()) \
F(QUrl, Url, QList<QUrl>, QUrl()) \
+ F(QUrl, UrlVector, QVector<QUrl>, QUrl()) \
+ F(QUrl, UrlStdVector, std::vector<QUrl>, QUrl()) \
F(QModelIndex, QModelIndex, QModelIndexList, QModelIndex()) \
+ F(QModelIndex, QModelIndexVector, QVector<QModelIndex>, QModelIndex()) \
+ F(QModelIndex, QModelIndexStdVector, std::vector<QModelIndex>, QModelIndex()) \
F(QItemSelectionRange, QItemSelectionRange, QItemSelection, QItemSelectionRange())
static QV4::ReturnedValue convertElementToValue(QV4::ExecutionEngine *engine, const QString &element)
@@ -263,56 +272,54 @@ public:
}
loadReference();
}
- qint32 signedIdx = static_cast<qint32>(index);
- if (signedIdx < d()->container->count()) {
+ if (index < size_t(d()->container->size())) {
if (hasProperty)
*hasProperty = true;
- return convertElementToValue(engine(), d()->container->at(signedIdx));
+ return convertElementToValue(engine(), qAsConst(*(d()->container))[index]);
}
if (hasProperty)
*hasProperty = false;
return Encode::undefined();
}
- void containerPutIndexed(uint index, const QV4::Value &value)
+ bool containerPutIndexed(uint index, const QV4::Value &value)
{
if (internalClass()->engine->hasException)
- return;
+ return false;
/* Qt containers have int (rather than uint) allowable indexes. */
if (index > INT_MAX) {
generateWarning(engine(), QLatin1String("Index out of range during indexed set"));
- return;
+ return false;
}
if (d()->isReference) {
if (!d()->object)
- return;
+ return false;
loadReference();
}
- qint32 signedIdx = static_cast<qint32>(index);
-
- int count = d()->container->count();
+ size_t count = size_t(d()->container->size());
typename Container::value_type element = convertValueToElement<typename Container::value_type>(value);
- if (signedIdx == count) {
- d()->container->append(element);
- } else if (signedIdx < count) {
- (*d()->container)[signedIdx] = element;
+ if (index == count) {
+ d()->container->push_back(element);
+ } else if (index < count) {
+ (*d()->container)[index] = element;
} else {
/* according to ECMA262r3 we need to insert */
/* the value at the given index, increasing length to index+1. */
- d()->container->reserve(signedIdx + 1);
- while (signedIdx > count++) {
- d()->container->append(typename Container::value_type());
+ d()->container->reserve(index + 1);
+ while (index > count++) {
+ d()->container->push_back(typename Container::value_type());
}
- d()->container->append(element);
+ d()->container->push_back(element);
}
if (d()->isReference)
storeReference();
+ return true;
}
QV4::PropertyAttributes containerQueryIndexed(uint index) const
@@ -327,8 +334,7 @@ public:
return QV4::Attr_Invalid;
loadReference();
}
- qint32 signedIdx = static_cast<qint32>(index);
- return (signedIdx < d()->container->count()) ? QV4::Attr_Data : QV4::Attr_Invalid;
+ return (index < size_t(d()->container->size())) ? QV4::Attr_Data : QV4::Attr_Invalid;
}
void containerAdvanceIterator(ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
@@ -344,7 +350,7 @@ public:
loadReference();
}
- if (it->arrayIndex < static_cast<uint>(d()->container->count())) {
+ if (it->arrayIndex < static_cast<uint>(d()->container->size())) {
*index = it->arrayIndex;
++it->arrayIndex;
*attrs = QV4::Attr_Data;
@@ -364,14 +370,13 @@ public:
return false;
loadReference();
}
- qint32 signedIdx = static_cast<qint32>(index);
- if (signedIdx >= d()->container->count())
+ if (index >= size_t(d()->container->size()))
return false;
/* according to ECMA262r3 it should be Undefined, */
/* but we cannot, so we insert a default-value instead. */
- d()->container->replace(signedIdx, typename Container::value_type());
+ (*d()->container)[index] = typename Container::value_type();
if (d()->isReference)
storeReference();
@@ -456,7 +461,7 @@ public:
RETURN_RESULT(Encode(0));
This->loadReference();
}
- RETURN_RESULT(Encode(This->d()->container->count()));
+ RETURN_RESULT(Encode(qint32(This->d()->container->size())));
}
static void method_set_length(const BuiltinFunction *, Scope &scope, CallData *callData)
@@ -478,8 +483,8 @@ public:
This->loadReference();
}
/* Determine whether we need to modify the sequence */
- qint32 newCount = static_cast<qint32>(newLength);
- qint32 count = This->d()->container->count();
+ quint32 newCount = static_cast<quint32>(newLength);
+ quint32 count = static_cast<quint32>(This->d()->container->size());
if (newCount == count) {
RETURN_UNDEFINED();
} else if (newCount > count) {
@@ -488,14 +493,13 @@ public:
/* We cannot, so we insert default-values instead. */
This->d()->container->reserve(newCount);
while (newCount > count++) {
- This->d()->container->append(typename Container::value_type());
+ This->d()->container->push_back(typename Container::value_type());
}
} else {
/* according to ECMA262r3 we need to remove */
/* elements until the sequence is the required length. */
- while (newCount < count) {
- count--;
- This->d()->container->removeAt(count);
+ if (newCount < count) {
+ This->d()->container->erase(This->d()->container->begin() + newCount, This->d()->container->end());
}
}
/* write back if required. */
@@ -516,10 +520,13 @@ public:
quint32 length = array->getLength();
QV4::ScopedValue v(scope);
for (quint32 i = 0; i < length; ++i)
- result << convertValueToElement<typename Container::value_type>((v = array->getIndexed(i)));
+ result.push_back(convertValueToElement<typename Container::value_type>((v = array->getIndexed(i))));
return QVariant::fromValue(result);
}
+ void* getRawContainerPtr() const
+ { return d()->container; }
+
void loadReference() const
{
Q_ASSERT(d()->object);
@@ -540,8 +547,8 @@ public:
static QV4::ReturnedValue getIndexed(const QV4::Managed *that, uint index, bool *hasProperty)
{ return static_cast<const QQmlSequence<Container> *>(that)->containerGetIndexed(index, hasProperty); }
- static void putIndexed(Managed *that, uint index, const QV4::Value &value)
- { static_cast<QQmlSequence<Container> *>(that)->containerPutIndexed(index, value); }
+ static bool putIndexed(Managed *that, uint index, const QV4::Value &value)
+ { return static_cast<QQmlSequence<Container> *>(that)->containerPutIndexed(index, value); }
static QV4::PropertyAttributes queryIndexed(const QV4::Managed *that, uint index)
{ return static_cast<const QQmlSequence<Container> *>(that)->containerQueryIndexed(index); }
static bool deleteIndexedProperty(QV4::Managed *that, uint index)
@@ -594,16 +601,34 @@ typedef QQmlSequence<QVector<qreal> > QQmlRealVectorList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlRealVectorList);
typedef QQmlSequence<QVector<bool> > QQmlBoolVectorList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlBoolVectorList);
+typedef QQmlSequence<std::vector<int> > QQmlIntStdVectorList;
+DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlIntStdVectorList);
+typedef QQmlSequence<std::vector<qreal> > QQmlRealStdVectorList;
+DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlRealStdVectorList);
+typedef QQmlSequence<std::vector<bool> > QQmlBoolStdVectorList;
+DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlBoolStdVectorList);
typedef QQmlSequence<QStringList> QQmlQStringList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQStringList);
typedef QQmlSequence<QList<QString> > QQmlStringList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlStringList);
+typedef QQmlSequence<QVector<QString> > QQmlStringVectorList;
+DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlStringVectorList);
+typedef QQmlSequence<std::vector<QString> > QQmlStringStdVectorList;
+DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlStringStdVectorList);
typedef QQmlSequence<QList<int> > QQmlIntList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlIntList);
typedef QQmlSequence<QList<QUrl> > QQmlUrlList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlUrlList);
+typedef QQmlSequence<QVector<QUrl> > QQmlUrlVectorList;
+DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlUrlVectorList);
+typedef QQmlSequence<std::vector<QUrl> > QQmlUrlStdVectorList;
+DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlUrlStdVectorList);
typedef QQmlSequence<QModelIndexList> QQmlQModelIndexList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQModelIndexList);
+typedef QQmlSequence<QVector<QModelIndex> > QQmlQModelIndexVectorList;
+DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQModelIndexVectorList);
+typedef QQmlSequence<std::vector<QModelIndex> > QQmlQModelIndexStdVectorList;
+DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQModelIndexStdVectorList);
typedef QQmlSequence<QItemSelection> QQmlQItemSelectionRangeList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQItemSelectionRangeList);
typedef QQmlSequence<QList<bool> > QQmlBoolList;
@@ -724,6 +749,19 @@ QVariant SequencePrototype::toVariant(const QV4::Value &array, int typeHint, boo
#undef SEQUENCE_TO_VARIANT
+#define SEQUENCE_GET_RAWCONTAINERPTR(ElementType, ElementTypeName, SequenceType, unused) \
+ if (const QQml##ElementTypeName##List *list = [&]() -> const QQml##ElementTypeName##List* \
+ { if (typeHint == qMetaTypeId<SequenceType>()) return object->as<QQml##ElementTypeName##List>(); return nullptr;}()) \
+ return list->getRawContainerPtr(); \
+ else
+
+void* SequencePrototype::getRawContainerPtr(const Object *object, int typeHint)
+{
+ FOREACH_QML_SEQUENCE_TYPE(SEQUENCE_GET_RAWCONTAINERPTR) { /* else */ return nullptr; }
+}
+
+#undef SEQUENCE_GET_RAWCONTAINERPTR
+
#define MAP_META_TYPE(ElementType, ElementTypeName, SequenceType, unused) \
if (object->as<QQml##ElementTypeName##List>()) { \
return qMetaTypeId<SequenceType>(); \
diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h
index 0879f149fa..2b8d1ea716 100644
--- a/src/qml/jsruntime/qv4sequenceobject_p.h
+++ b/src/qml/jsruntime/qv4sequenceobject_p.h
@@ -81,6 +81,7 @@ struct SequencePrototype : public QV4::Object
static int metaTypeForSequence(const Object *object);
static QVariant toVariant(Object *object);
static QVariant toVariant(const Value &array, int typeHint, bool *succeeded);
+ static void* getRawContainerPtr(const Object *object, int typeHint);
};
}
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index 515d61c8e4..c0183a46a7 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -54,12 +54,12 @@ using namespace QV4;
DEFINE_MANAGED_VTABLE(String);
-void String::markObjects(Heap::Base *that, ExecutionEngine *e)
+void String::markObjects(Heap::Base *that, MarkStack *markStack)
{
String::Data *s = static_cast<String::Data *>(that);
if (s->largestSubLength) {
- s->left->mark(e);
- s->right->mark(e);
+ s->left->mark(markStack);
+ s->right->mark(markStack);
}
}
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index f5311ae5d4..2f34dd6139 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -205,7 +205,7 @@ struct Q_QML_PRIVATE_EXPORT String : public Managed {
Identifier *identifier() const { return d()->identifier; }
protected:
- static void markObjects(Heap::Base *that, ExecutionEngine *e);
+ static void markObjects(Heap::Base *that, MarkStack *markStack);
static bool isEqualTo(Managed *that, Managed *o);
static uint getLength(const Managed *m);
#endif
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 1596f4b0fa..81f5c3566c 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -77,15 +77,15 @@ void Heap::StringObject::init()
{
Object::init();
Q_ASSERT(vtable() == QV4::StringObject::staticVTable());
- string = internalClass->engine->id_empty()->d();
- *propertyData(LengthPropertyIndex) = Primitive::fromInt32(0);
+ string.set(internalClass->engine, internalClass->engine->id_empty()->d());
+ setProperty(internalClass->engine, LengthPropertyIndex, Primitive::fromInt32(0));
}
void Heap::StringObject::init(const QV4::String *str)
{
Object::init();
- string = str->d();
- *propertyData(LengthPropertyIndex) = Primitive::fromInt32(length());
+ string.set(internalClass->engine, str->d());
+ setProperty(internalClass->engine, LengthPropertyIndex, Primitive::fromInt32(length()));
}
Heap::String *Heap::StringObject::getIndex(uint index) const
@@ -145,13 +145,6 @@ void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name,
return Object::advanceIterator(m, it, name, index, p, attrs);
}
-void StringObject::markObjects(Heap::Base *that, ExecutionEngine *e)
-{
- StringObject::Data *o = static_cast<StringObject::Data *>(that);
- o->string->mark(e);
- Object::markObjects(that, e);
-}
-
DEFINE_OBJECT_VTABLE(StringCtor);
void Heap::StringCtor::init(QV4::ExecutionContext *scope)
@@ -200,6 +193,7 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor)
defineDefaultProperty(QStringLiteral("lastIndexOf"), method_lastIndexOf, 1);
defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare, 1);
defineDefaultProperty(QStringLiteral("match"), method_match, 1);
+ defineDefaultProperty(QStringLiteral("repeat"), method_repeat, 1);
defineDefaultProperty(QStringLiteral("replace"), method_replace, 2);
defineDefaultProperty(QStringLiteral("search"), method_search, 1);
defineDefaultProperty(QStringLiteral("slice"), method_slice, 2);
@@ -458,6 +452,21 @@ void StringPrototype::method_match(const BuiltinFunction *, Scope &scope, CallDa
scope.result = a;
}
+void StringPrototype::method_repeat(const BuiltinFunction *, Scope &scope, CallData *callData)
+{
+ QString value = getThisString(scope, callData);
+ CHECK_EXCEPTION();
+
+ double repeats = callData->args[0].toInteger();
+
+ if (repeats < 0 || qIsInf(repeats)) {
+ scope.result = scope.engine->throwRangeError(QLatin1String("Invalid count value"));
+ return;
+ }
+
+ scope.result = scope.engine->newString(value.repeated(int(repeats)));
+}
+
static void appendReplacementString(QString *result, const QString &input, const QString& replaceValue, uint* matchOffsets, int captureCount)
{
result->reserve(result->length() + replaceValue.length());
@@ -547,7 +556,7 @@ void StringPrototype::method_replace(const BuiltinFunction *, Scope &scope, Call
offset = qMax(offset + 1, matchOffsets[oldSize + 1]);
}
if (regExp->global())
- *regExp->lastIndexProperty() = Primitive::fromUInt32(0);
+ regExp->setLastIndex(0);
numStringMatches = nMatchOffsets / (regExp->value()->captureCount() * 2);
numCaptures = regExp->value()->captureCount();
} else {
diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h
index 2e64364f9f..ce046f4844 100644
--- a/src/qml/jsruntime/qv4stringobject_p.h
+++ b/src/qml/jsruntime/qv4stringobject_p.h
@@ -60,14 +60,18 @@ namespace QV4 {
namespace Heap {
-struct StringObject : Object {
+#define StringObjectMembers(class, Member) \
+ Member(class, Pointer, String *, string)
+
+DECLARE_HEAP_OBJECT(StringObject, Object) {
+ DECLARE_MARK_TABLE(StringObject);
+
enum {
LengthPropertyIndex = 0
};
void init();
void init(const QV4::String *string);
- String *string;
Heap::String *getIndex(uint index) const;
uint length() const;
@@ -96,7 +100,6 @@ struct StringObject: Object {
protected:
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs);
- static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
struct StringCtor: FunctionObject
@@ -122,6 +125,7 @@ struct StringPrototype: StringObject
static void method_lastIndexOf(const BuiltinFunction *, Scope &scope, CallData *callData);
static void method_localeCompare(const BuiltinFunction *, Scope &scope, CallData *callData);
static void method_match(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_repeat(const BuiltinFunction *, Scope &scope, CallData *callData);
static void method_replace(const BuiltinFunction *, Scope &scope, CallData *callData);
static void method_search(const BuiltinFunction *, Scope &scope, CallData *callData);
static void method_slice(const BuiltinFunction *, Scope &scope, CallData *callData);
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index 80655aded6..fe27d7c2d2 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -229,8 +229,8 @@ void TypedArrayCtor::construct(const Managed *m, Scope &scope, CallData *callDat
return;
}
- Scoped<TypedArray > array(scope, TypedArray::create(scope.engine, that->d()->type));
- array->d()->buffer = buffer->d();
+ Scoped<TypedArray> array(scope, TypedArray::create(scope.engine, that->d()->type));
+ array->d()->buffer.set(scope.engine, buffer->d());
array->d()->byteLength = byteLength;
array->d()->byteOffset = 0;
@@ -252,8 +252,8 @@ void TypedArrayCtor::construct(const Managed *m, Scope &scope, CallData *callDat
return;
}
- Scoped<TypedArray > array(scope, TypedArray::create(scope.engine, that->d()->type));
- array->d()->buffer = newBuffer->d();
+ Scoped<TypedArray> array(scope, TypedArray::create(scope.engine, that->d()->type));
+ array->d()->buffer.set(scope.engine, newBuffer->d());
array->d()->byteLength = destByteLength;
array->d()->byteOffset = 0;
@@ -311,8 +311,8 @@ void TypedArrayCtor::construct(const Managed *m, Scope &scope, CallData *callDat
byteLength = (uint)l;
}
- Scoped<TypedArray > array(scope, TypedArray::create(scope.engine, that->d()->type));
- array->d()->buffer = buffer->d();
+ Scoped<TypedArray> array(scope, TypedArray::create(scope.engine, that->d()->type));
+ array->d()->buffer.set(scope.engine, buffer->d());
array->d()->byteLength = byteLength;
array->d()->byteOffset = byteOffset;
scope.result = array.asReturnedValue();
@@ -335,8 +335,8 @@ void TypedArrayCtor::construct(const Managed *m, Scope &scope, CallData *callDat
return;
}
- Scoped<TypedArray > array(scope, TypedArray::create(scope.engine, that->d()->type));
- array->d()->buffer = newBuffer->d();
+ Scoped<TypedArray> array(scope, TypedArray::create(scope.engine, that->d()->type));
+ array->d()->buffer.set(scope.engine, newBuffer->d());
array->d()->byteLength = l * elementSize;
array->d()->byteOffset = 0;
@@ -377,12 +377,6 @@ Heap::TypedArray *TypedArray::create(ExecutionEngine *e, Heap::TypedArray::Type
return e->memoryManager->allocObject<TypedArray>(ic, e->typedArrayPrototype + t, t);
}
-void TypedArray::markObjects(Heap::Base *that, ExecutionEngine *e)
-{
- static_cast<TypedArray::Data *>(that)->buffer->mark(e);
- Object::markObjects(that, e);
-}
-
ReturnedValue TypedArray::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
Scope scope(static_cast<const Object *>(m)->engine());
@@ -400,11 +394,11 @@ ReturnedValue TypedArray::getIndexed(const Managed *m, uint index, bool *hasProp
return a->d()->type->read(a->d()->buffer->data->data(), byteOffset);
}
-void TypedArray::putIndexed(Managed *m, uint index, const Value &value)
+bool TypedArray::putIndexed(Managed *m, uint index, const Value &value)
{
ExecutionEngine *v4 = static_cast<Object *>(m)->engine();
if (v4->hasException)
- return;
+ return false;
Scope scope(v4);
Scoped<TypedArray> a(scope, static_cast<TypedArray *>(m));
@@ -415,11 +409,12 @@ void TypedArray::putIndexed(Managed *m, uint index, const Value &value)
goto reject;
a->d()->type->write(scope.engine, a->d()->buffer->data->data(), byteOffset, value);
- return;
+ return true;
reject:
if (scope.engine->current->strictMode)
scope.engine->throwTypeError();
+ return false;
}
void TypedArrayPrototype::init(ExecutionEngine *engine, TypedArrayCtor *ctor)
diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h
index a6a74e4b9b..a472dfa607 100644
--- a/src/qml/jsruntime/qv4typedarray_p.h
+++ b/src/qml/jsruntime/qv4typedarray_p.h
@@ -72,7 +72,15 @@ struct TypedArrayOperations {
namespace Heap {
-struct TypedArray : Object {
+#define TypedArrayMembers(class, Member) \
+ Member(class, Pointer, ArrayBuffer *, buffer) \
+ Member(class, NoMark, const TypedArrayOperations *, type) \
+ Member(class, NoMark, uint, byteLength) \
+ Member(class, NoMark, uint, byteOffset) \
+ Member(class, NoMark, uint, arrayType)
+
+DECLARE_HEAP_OBJECT(TypedArray, Object) {
+ DECLARE_MARK_TABLE(TypedArray);
enum Type {
Int8Array,
UInt8Array,
@@ -87,12 +95,6 @@ struct TypedArray : Object {
};
void init(Type t);
-
- const TypedArrayOperations *type;
- Pointer<ArrayBuffer> buffer;
- uint byteLength;
- uint byteOffset;
- Type arrayType;
};
struct TypedArrayCtor : FunctionObject {
@@ -128,12 +130,11 @@ struct Q_QML_PRIVATE_EXPORT TypedArray : Object
}
Heap::TypedArray::Type arrayType() const {
- return d()->arrayType;
+ return static_cast<Heap::TypedArray::Type>(d()->arrayType);
}
- static void markObjects(Heap::Base *that, ExecutionEngine *e);
static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
- static void putIndexed(Managed *m, uint index, const Value &value);
+ static bool putIndexed(Managed *m, uint index, const Value &value);
};
struct TypedArrayCtor: FunctionObject
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 9adad881a1..50cecb6598 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -487,7 +487,7 @@ public:
// Section 9.12
bool sameValue(Value other) const;
- inline void mark(ExecutionEngine *e);
+ inline void mark(MarkStack *markStack);
Value &operator =(const ScopedValue &v);
Value &operator=(ReturnedValue v) { _val = v; return *this; }
@@ -718,7 +718,6 @@ inline unsigned int Value::toUInt32() const
return (unsigned int)toInt32();
}
-
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index 5cab4c5386..f2ff5d307e 100644
--- a/src/qml/jsruntime/qv4variantobject.cpp
+++ b/src/qml/jsruntime/qv4variantobject.cpp
@@ -84,7 +84,7 @@ bool VariantObject::isEqualTo(Managed *m, Managed *other)
return false;
}
-void VariantObject::addVmePropertyReference()
+void VariantObject::addVmePropertyReference() const
{
if (d()->isScarce() && ++d()->vmePropertyReferenceCount == 1) {
// remove from the ep->scarceResources list
@@ -94,7 +94,7 @@ void VariantObject::addVmePropertyReference()
}
}
-void VariantObject::removeVmePropertyReference()
+void VariantObject::removeVmePropertyReference() const
{
if (d()->isScarce() && --d()->vmePropertyReferenceCount == 0) {
// and add to the ep->scarceResources list
diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h
index dba14b13fb..a7c6fa320c 100644
--- a/src/qml/jsruntime/qv4variantobject_p.h
+++ b/src/qml/jsruntime/qv4variantobject_p.h
@@ -96,8 +96,8 @@ struct VariantObject : Object
V4_PROTOTYPE(variantPrototype)
V4_NEEDS_DESTROY
- void addVmePropertyReference();
- void removeVmePropertyReference();
+ void addVmePropertyReference() const;
+ void removeVmePropertyReference() const;
static bool isEqualTo(Managed *m, Managed *other);
};
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 9d65f67f0f..7293630924 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -336,18 +336,24 @@ Param traceParam(const Param &param)
return param;
}
# define VALUE(param) (*VALUEPTR(param))
-# define VALUEPTR(param) (scopes[traceParam(param).scope] + param.index)
+# define VALUEPTR(param) (scopes[traceParam(param).scope].values + param.index)
#else
# define VALUE(param) (*VALUEPTR(param))
-# define VALUEPTR(param) (scopes[param.scope] + param.index)
+# define VALUEPTR(param) (scopes[param.scope].values + param.index)
#endif
+// ### add write barrier here
#define STOREVALUE(param, value) { \
QV4::ReturnedValue tmp = (value); \
if (engine->hasException) \
goto catchException; \
- VALUE(param) = tmp; \
- }
+ if (Q_LIKELY(!engine->writeBarrierActive || !scopes[param.scope].base)) { \
+ VALUE(param) = tmp; \
+ } else { \
+ QV4::WriteBarrier::write(engine, scopes[param.scope].base, VALUEPTR(param), QV4::Value::fromReturnedValue(tmp)); \
+ } \
+}
+
// qv4scopedvalue_p.h also defines a CHECK_EXCEPTION macro
#ifdef CHECK_EXCEPTION
#undef CHECK_EXCEPTION
@@ -394,21 +400,29 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code)
}
}
- Q_ALLOCA_VAR(QV4::Value*, scopes, sizeof(QV4::Value *)*(2 + 2*scopeDepth));
+ struct Scopes {
+ QV4::Value *values;
+ QV4::Heap::Base *base; // non 0 if a write barrier is required
+ };
+ Q_ALLOCA_VAR(Scopes, scopes, sizeof(Scopes)*(2 + 2*scopeDepth));
{
- scopes[0] = const_cast<QV4::Value *>(static_cast<CompiledData::CompilationUnit*>(engine->current->compilationUnit)->constants);
+ scopes[0] = { const_cast<QV4::Value *>(static_cast<CompiledData::CompilationUnit*>(engine->current->compilationUnit)->constants), 0 };
// stack gets setup in push instruction
- scopes[1] = 0;
+ scopes[1] = { 0, 0 };
QV4::Heap::ExecutionContext *scope = engine->current;
int i = 0;
while (scope) {
- if (scope->type >= QV4::Heap::ExecutionContext::Type_SimpleCallContext) {
+ if (scope->type == QV4::Heap::ExecutionContext::Type_SimpleCallContext) {
+ QV4::Heap::SimpleCallContext *cc = static_cast<QV4::Heap::SimpleCallContext *>(scope);
+ scopes[2*i + 2] = { cc->callData->args, 0 };
+ scopes[2*i + 3] = { 0, 0 };
+ } else if (scope->type == QV4::Heap::ExecutionContext::Type_CallContext) {
QV4::Heap::CallContext *cc = static_cast<QV4::Heap::CallContext *>(scope);
- scopes[2*i + 2] = cc->callData->args;
- scopes[2*i + 3] = cc->locals;
+ scopes[2*i + 2] = { cc->callData->args, cc };
+ scopes[2*i + 3] = { cc->locals.values, cc };
} else {
- scopes[2*i + 2] = 0;
- scopes[2*i + 3] = 0;
+ scopes[2*i + 2] = { 0, 0 };
+ scopes[2*i + 3] = { 0, 0 };
}
++i;
scope = scope->outer;
@@ -472,7 +486,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code)
MOTH_BEGIN_INSTR(LoadElementLookup)
QV4::Lookup *l = engine->current->lookups + instr.lookup;
- STOREVALUE(instr.result, l->indexedGetter(l, VALUE(instr.base), VALUE(instr.index)));
+ STOREVALUE(instr.result, l->indexedGetter(l, engine, VALUE(instr.base), VALUE(instr.index)));
MOTH_END_INSTR(LoadElementLookup)
MOTH_BEGIN_INSTR(StoreElement)
@@ -482,7 +496,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code)
MOTH_BEGIN_INSTR(StoreElementLookup)
QV4::Lookup *l = engine->current->lookups + instr.lookup;
- l->indexedSetter(l, VALUE(instr.base), VALUE(instr.index), VALUE(instr.source));
+ l->indexedSetter(l, engine, VALUE(instr.base), VALUE(instr.index), VALUE(instr.source));
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreElementLookup)
@@ -549,7 +563,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code)
TRACE(inline, "stack size: %u", instr.value);
stackSize = instr.value;
stack = scope.alloc(stackSize);
- scopes[1] = stack;
+ scopes[1].values = stack;
MOTH_END_INSTR(Push)
MOTH_BEGIN_INSTR(CallValue)
diff --git a/src/qml/memory/memory.pri b/src/qml/memory/memory.pri
index 38fadbf23f..7956e4a9a1 100644
--- a/src/qml/memory/memory.pri
+++ b/src/qml/memory/memory.pri
@@ -7,7 +7,8 @@ SOURCES += \
HEADERS += \
$$PWD/qv4mm_p.h \
- $$PWD/qv4mmdefs_p.h
+ $$PWD/qv4mmdefs_p.h \
+ $$PWD/qv4writebarrier_p.h
}
HEADERS += \
diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h
index a4e96b4c84..f00ce4283c 100644
--- a/src/qml/memory/qv4heap_p.h
+++ b/src/qml/memory/qv4heap_p.h
@@ -75,6 +75,7 @@ struct InternalClass;
struct VTable
{
const VTable * const parent;
+ const quint64 markTable;
uint inlinePropertyOffset : 16;
uint nInlineProperties : 16;
uint isExecutionContext : 1;
@@ -87,7 +88,7 @@ struct VTable
uint type : 8;
const char *className;
void (*destroy)(Heap::Base *);
- void (*markObjects)(Heap::Base *, ExecutionEngine *e);
+ void (*markObjects)(Heap::Base *, MarkStack *markStack);
bool (*isEqualTo)(Managed *m, Managed *other);
};
@@ -96,10 +97,12 @@ namespace Heap {
struct Q_QML_EXPORT Base {
void *operator new(size_t) = delete;
+ static Q_CONSTEXPR quint64 markTable = 0;
+
InternalClass *internalClass;
inline ReturnedValue asReturnedValue() const;
- inline void mark(QV4::ExecutionEngine *engine);
+ inline void mark(QV4::MarkStack *markStack);
const VTable *vtable() const { return internalClass->vtable; }
inline bool isMarked() const {
@@ -114,6 +117,12 @@ struct Q_QML_EXPORT Base {
Q_ASSERT(!Chunk::testBit(c->extendsBitmap, h - c->realBase()));
return Chunk::setBit(c->blackBitmap, h - c->realBase());
}
+ inline void setGrayBit() {
+ const HeapItem *h = reinterpret_cast<const HeapItem *>(this);
+ Chunk *c = h->chunk();
+ Q_ASSERT(!Chunk::testBit(c->extendsBitmap, h - c->realBase()));
+ return Chunk::setBit(c->grayBitmap, h - c->realBase());
+ }
inline bool inUse() const {
const HeapItem *h = reinterpret_cast<const HeapItem *>(this);
@@ -122,6 +131,8 @@ struct Q_QML_EXPORT Base {
return Chunk::testBit(c->objectBitmap, h - c->realBase());
}
+ inline void markChildren(MarkStack *markStack);
+
void *operator new(size_t, Managed *m) { return m; }
void *operator new(size_t, Heap::Base *m) { return m; }
void operator delete(void *, Heap::Base *) {}
@@ -171,20 +182,6 @@ Q_STATIC_ASSERT(std::is_standard_layout<Base>::value);
Q_STATIC_ASSERT(offsetof(Base, internalClass) == 0);
Q_STATIC_ASSERT(sizeof(Base) == QT_POINTER_SIZE);
-template <typename T>
-struct Pointer {
- T *operator->() const { return ptr; }
- operator T *() const { return ptr; }
-
- Pointer &operator =(T *t) { ptr = t; return *this; }
-
- template <typename Type>
- Type *cast() { return static_cast<Type *>(ptr); }
-
- T *ptr;
-};
-V4_ASSERT_IS_TRIVIAL(Pointer<void>)
-
}
#ifdef QT_NO_QOBJECT
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index 56f1254421..de97918fb0 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -60,7 +60,11 @@
#include "qv4alloca_p.h"
#include "qv4profiling_p.h"
-#define MM_DEBUG 0
+//#define MM_STATS
+
+#if !defined(MM_STATS) && !defined(QT_NO_DEBUG)
+#define MM_STATS
+#endif
#if MM_DEBUG
#define DEBUG qDebug() << "MM:"
@@ -275,14 +279,85 @@ QString binary(quintptr) { return QString(); }
#define SDUMP if (1) ; else qDebug
#endif
-bool Chunk::sweep()
+void Heap::Base::markChildren(MarkStack *markStack)
+{
+ if (vtable()->markObjects)
+ vtable()->markObjects(this, markStack);
+ if (quint64 m = vtable()->markTable) {
+// qDebug() << "using mark table:" << hex << m << "for" << h;
+ void **mem = reinterpret_cast<void **>(this);
+ while (m) {
+ MarkFlags mark = static_cast<MarkFlags>(m & 3);
+ switch (mark) {
+ case Mark_NoMark:
+ break;
+ case Mark_Value:
+// qDebug() << "marking value at " << mem;
+ reinterpret_cast<Value *>(mem)->mark(markStack);
+ break;
+ case Mark_Pointer: {
+// qDebug() << "marking pointer at " << mem;
+ Heap::Base *p = *reinterpret_cast<Heap::Base **>(mem);
+ if (p)
+ p->mark(markStack);
+ break;
+ }
+ case Mark_ValueArray: {
+ Q_ASSERT(m == Mark_ValueArray);
+// qDebug() << "marking Value Array at offset" << hex << (mem - reinterpret_cast<void **>(h));
+ ValueArray<0> *a = reinterpret_cast<ValueArray<0> *>(mem);
+ Value *v = a->values;
+ const Value *end = v + a->alloc;
+ if (a->alloc > 32*1024) {
+ // drain from time to time to avoid overflows in the js stack
+ Heap::Base **currentBase = markStack->top;
+ while (v < end) {
+ v->mark(markStack);
+ ++v;
+ if (markStack->top >= currentBase + 32*1024) {
+ Heap::Base **oldBase = markStack->base;
+ markStack->base = currentBase;
+ markStack->drain();
+ markStack->base = oldBase;
+ }
+ }
+ } else {
+ while (v < end) {
+ v->mark(markStack);
+ ++v;
+ }
+ }
+ break;
+ }
+ }
+
+ m >>= 2;
+ ++mem;
+ }
+ }
+}
+
+// Stores a classname -> freed count mapping.
+typedef QHash<const char*, int> MMStatsHash;
+Q_GLOBAL_STATIC(MMStatsHash, freedObjectStatsGlobal)
+
+// This indirection avoids sticking QHash code in each of the call sites, which
+// shaves off some instructions in the case that it's unused.
+static void increaseFreedCountForClass(const char *className)
+{
+ (*freedObjectStatsGlobal())[className]++;
+}
+
+bool Chunk::sweep(ClassDestroyStatsCallback classCountPtr)
{
bool hasUsedSlots = false;
SDUMP() << "sweeping chunk" << this;
HeapItem *o = realBase();
bool lastSlotFree = false;
for (uint i = 0; i < Chunk::EntriesInBitmap; ++i) {
+#if WRITEBARRIER(none)
Q_ASSERT((grayBitmap[i] | blackBitmap[i]) == blackBitmap[i]); // check that we don't have gray only objects
+#endif
quintptr toFree = objectBitmap[i] ^ blackBitmap[i];
Q_ASSERT((toFree & objectBitmap[i]) == toFree); // check all black objects are marked as being used
quintptr e = extendsBitmap[i];
@@ -311,14 +386,17 @@ bool Chunk::sweep()
HeapItem *itemToFree = o + index;
Heap::Base *b = *itemToFree;
- if (b->vtable()->destroy) {
- b->vtable()->destroy(b);
+ const VTable *v = b->vtable();
+ if (Q_UNLIKELY(classCountPtr))
+ classCountPtr(v->className);
+ if (v->destroy) {
+ v->destroy(b);
b->_checkIsDestroyed();
}
}
objectBitmap[i] = blackBitmap[i];
+ grayBitmap[i] = 0;
hasUsedSlots |= (blackBitmap[i] != 0);
- blackBitmap[i] = 0;
extendsBitmap[i] = e;
lastSlotFree = !((objectBitmap[i]|extendsBitmap[i]) >> (sizeof(quintptr)*8 - 1));
SDUMP() << " new extends =" << binary(e);
@@ -362,13 +440,56 @@ void Chunk::freeAll()
}
}
objectBitmap[i] = 0;
- blackBitmap[i] = 0;
+ grayBitmap[i] = 0;
extendsBitmap[i] = e;
o += Chunk::Bits;
}
// DEBUG << "swept chunk" << this << "freed" << slotsFreed << "slots.";
}
+void Chunk::resetBlackBits()
+{
+ memset(blackBitmap, 0, sizeof(blackBitmap));
+}
+
+#ifdef MM_STATS
+static uint nGrayItems = 0;
+#endif
+
+void Chunk::collectGrayItems(MarkStack *markStack)
+{
+ // DEBUG << "sweeping chunk" << this << (*freeList);
+ HeapItem *o = realBase();
+ for (uint i = 0; i < Chunk::EntriesInBitmap; ++i) {
+#if WRITEBARRIER(none)
+ Q_ASSERT((grayBitmap[i] | blackBitmap[i]) == blackBitmap[i]); // check that we don't have gray only objects
+#endif
+ quintptr toMark = blackBitmap[i] & grayBitmap[i]; // correct for a Steele type barrier
+ Q_ASSERT((toMark & objectBitmap[i]) == toMark); // check all black objects are marked as being used
+ // DEBUG << hex << " index=" << i << toFree;
+ while (toMark) {
+ uint index = qCountTrailingZeroBits(toMark);
+ quintptr bit = (static_cast<quintptr>(1) << index);
+
+ toMark ^= bit; // mask out marked slot
+ // DEBUG << " index" << hex << index << toFree;
+
+ HeapItem *itemToFree = o + index;
+ Heap::Base *b = *itemToFree;
+ Q_ASSERT(b->inUse());
+ markStack->push(b);
+#ifdef MM_STATS
+ ++nGrayItems;
+// qDebug() << "adding gray item" << b << "to mark stack";
+#endif
+ }
+ grayBitmap[i] = 0;
+ o += Chunk::Bits;
+ }
+ // DEBUG << "swept chunk" << this << "freed" << slotsFreed << "slots.";
+
+}
+
void Chunk::sortIntoBins(HeapItem **bins, uint nBins)
{
// qDebug() << "sortIntoBins:";
@@ -378,7 +499,7 @@ void Chunk::sortIntoBins(HeapItem **bins, uint nBins)
#else
const int start = 1;
#endif
-#ifndef QT_NO_DEBUG
+#ifdef MM_STATS
uint freeSlots = 0;
uint allocatedSlots = 0;
#endif
@@ -388,7 +509,7 @@ void Chunk::sortIntoBins(HeapItem **bins, uint nBins)
if (!i)
usedSlots |= (static_cast<quintptr>(1) << (HeaderSize/SlotSize)) - 1;
#endif
-#ifndef QT_NO_DEBUG
+#ifdef MM_STATS
allocatedSlots += qPopulationCount(usedSlots);
// qDebug() << hex << " i=" << i << "used=" << usedSlots;
#endif
@@ -405,7 +526,7 @@ void Chunk::sortIntoBins(HeapItem **bins, uint nBins)
break;
}
usedSlots = (objectBitmap[i]|extendsBitmap[i]);
-#ifndef QT_NO_DEBUG
+#ifdef MM_STATS
allocatedSlots += qPopulationCount(usedSlots);
// qDebug() << hex << " i=" << i << "used=" << usedSlots;
#endif
@@ -416,7 +537,7 @@ void Chunk::sortIntoBins(HeapItem **bins, uint nBins)
usedSlots |= (quintptr(1) << index) - 1;
uint freeEnd = i*Bits + index;
uint nSlots = freeEnd - freeStart;
-#ifndef QT_NO_DEBUG
+#ifdef MM_STATS
// qDebug() << hex << " got free slots from" << freeStart << "to" << freeEnd << "n=" << nSlots << "usedSlots=" << usedSlots;
freeSlots += nSlots;
#endif
@@ -427,7 +548,7 @@ void Chunk::sortIntoBins(HeapItem **bins, uint nBins)
bins[bin] = freeItem;
}
}
-#ifndef QT_NO_DEBUG
+#ifdef MM_STATS
Q_ASSERT(freeSlots + allocatedSlots == (EntriesInBitmap - start) * 8 * sizeof(quintptr));
#endif
}
@@ -574,7 +695,7 @@ done:
return m;
}
-void BlockAllocator::sweep()
+void BlockAllocator::sweep(ClassDestroyStatsCallback classCountPtr)
{
nextFree = 0;
nFree = 0;
@@ -583,8 +704,8 @@ void BlockAllocator::sweep()
// qDebug() << "BlockAlloc: sweep";
usedSlotsAfterLastSweep = 0;
- auto isFree = [this] (Chunk *c) {
- bool isUsed = c->sweep();
+ auto isFree = [this, classCountPtr] (Chunk *c) {
+ bool isUsed = c->sweep(classCountPtr);
if (isUsed) {
c->sortIntoBins(freeBins, NumBins);
@@ -607,6 +728,19 @@ void BlockAllocator::freeAll()
}
}
+void BlockAllocator::resetBlackBits()
+{
+ for (auto c : chunks)
+ c->resetBlackBits();
+}
+
+void BlockAllocator::collectGrayItems(MarkStack *markStack)
+{
+ for (auto c : chunks)
+ c->collectGrayItems(markStack);
+
+}
+
#if MM_DEBUG
void BlockAllocator::stats() {
DEBUG << "MM stats:";
@@ -645,23 +779,27 @@ HeapItem *HugeItemAllocator::allocate(size_t size) {
return c->first();
}
-static void freeHugeChunk(ChunkAllocator *chunkAllocator, const HugeItemAllocator::HugeChunk &c)
+static void freeHugeChunk(ChunkAllocator *chunkAllocator, const HugeItemAllocator::HugeChunk &c, ClassDestroyStatsCallback classCountPtr)
{
HeapItem *itemToFree = c.chunk->first();
Heap::Base *b = *itemToFree;
- if (b->vtable()->destroy) {
- b->vtable()->destroy(b);
+ const VTable *v = b->vtable();
+ if (Q_UNLIKELY(classCountPtr))
+ classCountPtr(v->className);
+
+ if (v->destroy) {
+ v->destroy(b);
b->_checkIsDestroyed();
}
chunkAllocator->free(c.chunk, c.size);
}
-void HugeItemAllocator::sweep() {
- auto isBlack = [this] (const HugeChunk &c) {
+void HugeItemAllocator::sweep(ClassDestroyStatsCallback classCountPtr)
+{
+ auto isBlack = [this, classCountPtr] (const HugeChunk &c) {
bool b = c.chunk->first()->isBlack();
- Chunk::clearBit(c.chunk->blackBitmap, c.chunk->first() - c.chunk->realBase());
if (!b)
- freeHugeChunk(chunkAllocator, c);
+ freeHugeChunk(chunkAllocator, c, classCountPtr);
return !b;
};
@@ -669,10 +807,28 @@ void HugeItemAllocator::sweep() {
chunks.erase(newEnd, chunks.end());
}
+void HugeItemAllocator::resetBlackBits()
+{
+ for (auto c : chunks)
+ Chunk::clearBit(c.chunk->blackBitmap, c.chunk->first() - c.chunk->realBase());
+}
+
+void HugeItemAllocator::collectGrayItems(MarkStack *markStack)
+{
+ for (auto c : chunks)
+ // Correct for a Steele type barrier
+ if (Chunk::testBit(c.chunk->blackBitmap, c.chunk->first() - c.chunk->realBase()) &&
+ Chunk::testBit(c.chunk->grayBitmap, c.chunk->first() - c.chunk->realBase())) {
+ HeapItem *i = c.chunk->first();
+ Heap::Base *b = *i;
+ b->mark(markStack);
+ }
+}
+
void HugeItemAllocator::freeAll()
{
for (auto &c : chunks) {
- freeHugeChunk(chunkAllocator, c);
+ freeHugeChunk(chunkAllocator, c, nullptr);
}
}
@@ -694,15 +850,17 @@ MemoryManager::MemoryManager(ExecutionEngine *engine)
#endif
}
-#ifndef QT_NO_DEBUG
+#ifdef MM_STATS
+static int allocationCount = 0;
static size_t lastAllocRequestedSlots = 0;
#endif
Heap::Base *MemoryManager::allocString(std::size_t unmanagedSize)
{
const size_t stringSize = align(sizeof(Heap::String));
-#ifndef QT_NO_DEBUG
+#ifdef MM_STATS
lastAllocRequestedSlots = stringSize >> Chunk::SlotSizeShift;
+ ++allocationCount;
#endif
bool didGCRun = false;
@@ -713,7 +871,8 @@ Heap::Base *MemoryManager::allocString(std::size_t unmanagedSize)
unmanagedHeapSize += unmanagedSize;
if (unmanagedHeapSize > unmanagedHeapSizeGCLimit) {
- runGC();
+ if (!didGCRun)
+ runGC();
if (3*unmanagedHeapSizeGCLimit <= 4*unmanagedHeapSize)
// more than 75% full, raise limit
@@ -731,14 +890,16 @@ Heap::Base *MemoryManager::allocString(std::size_t unmanagedSize)
m = blockAllocator.allocate(stringSize, true);
}
+// qDebug() << "allocated string" << m;
memset(m, 0, stringSize);
return *m;
}
Heap::Base *MemoryManager::allocData(std::size_t size)
{
-#ifndef QT_NO_DEBUG
+#ifdef MM_STATS
lastAllocRequestedSlots = size >> Chunk::SlotSizeShift;
+ ++allocationCount;
#endif
bool didRunGC = false;
@@ -755,8 +916,11 @@ Heap::Base *MemoryManager::allocData(std::size_t size)
// qDebug() << "unmanagedHeapSize:" << unmanagedHeapSize << "limit:" << unmanagedHeapSizeGCLimit << "unmanagedSize:" << unmanagedSize;
- if (size > Chunk::DataSize)
- return *hugeItemAllocator.allocate(size);
+ if (size > Chunk::DataSize) {
+ HeapItem *h = hugeItemAllocator.allocate(size);
+// qDebug() << "allocating huge item" << h;
+ return *h;
+ }
HeapItem *m = blockAllocator.allocate(size);
if (!m) {
@@ -766,6 +930,7 @@ Heap::Base *MemoryManager::allocData(std::size_t size)
}
memset(m, 0, size);
+// qDebug() << "allocating data" << m;
return *m;
}
@@ -773,48 +938,74 @@ Heap::Object *MemoryManager::allocObjectWithMemberData(const QV4::VTable *vtable
{
uint size = (vtable->nInlineProperties + vtable->inlinePropertyOffset)*sizeof(Value);
Q_ASSERT(!(size % sizeof(HeapItem)));
- Heap::Object *o = static_cast<Heap::Object *>(allocData(size));
- // ### Could optimize this and allocate both in one go through the block allocator
- if (nMembers > vtable->nInlineProperties) {
+ Heap::Object *o;
+ if (nMembers <= vtable->nInlineProperties) {
+ o = static_cast<Heap::Object *>(allocData(size));
+ } else {
+ // Allocate both in one go through the block allocator
nMembers -= vtable->nInlineProperties;
std::size_t memberSize = align(sizeof(Heap::MemberData) + (nMembers - 1)*sizeof(Value));
-// qDebug() << "allocating member data for" << o << nMembers << memberSize;
- Heap::Base *m;
- if (memberSize > Chunk::DataSize)
- m = *hugeItemAllocator.allocate(memberSize);
- else
- m = *blockAllocator.allocate(memberSize, true);
- memset(m, 0, memberSize);
- o->memberData = static_cast<Heap::MemberData *>(m);
- o->memberData->internalClass = engine->internalClasses[EngineBase::Class_MemberData];
+ size_t totalSize = size + memberSize;
+ Heap::MemberData *m;
+ if (totalSize > Chunk::DataSize) {
+ o = static_cast<Heap::Object *>(allocData(size));
+ m = hugeItemAllocator.allocate(memberSize)->as<Heap::MemberData>();
+ } else {
+ HeapItem *mh = reinterpret_cast<HeapItem *>(allocData(totalSize));
+ Heap::Base *b = *mh;
+ o = static_cast<Heap::Object *>(b);
+ mh += (size >> Chunk::SlotSizeShift);
+ m = mh->as<Heap::MemberData>();
+ Chunk *c = mh->chunk();
+ size_t index = mh - c->realBase();
+ Chunk::setBit(c->objectBitmap, index);
+ Chunk::clearBit(c->extendsBitmap, index);
+ }
+ o->memberData.set(engine, m);
+ m->internalClass = engine->internalClasses[EngineBase::Class_MemberData];
Q_ASSERT(o->memberData->internalClass);
- o->memberData->size = static_cast<uint>((memberSize - sizeof(Heap::MemberData) + sizeof(Value))/sizeof(Value));
- o->memberData->init();
+ m->values.alloc = static_cast<uint>((memberSize - sizeof(Heap::MemberData) + sizeof(Value))/sizeof(Value));
+ m->values.size = o->memberData->values.alloc;
+ m->init();
// qDebug() << " got" << o->memberData << o->memberData->size;
}
+// qDebug() << "allocating object with memberData" << o << o->memberData.operator->();
return o;
}
-static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase)
+static uint markStackSize = 0;
+
+MarkStack::MarkStack(ExecutionEngine *engine)
+ : engine(engine)
+{
+ base = (Heap::Base **)engine->gcStack->base();
+ top = base;
+ limit = base + ExecutionEngine::GCStackLimit/sizeof(Heap::Base)*3/4;
+}
+
+void MarkStack::drain()
{
- while (engine->jsStackTop > markBase) {
- Heap::Base *h = engine->popForGC();
+ while (top > base) {
+ Heap::Base *h = pop();
+ ++markStackSize;
Q_ASSERT(h); // at this point we should only have Heap::Base objects in this area on the stack. If not, weird things might happen.
- Q_ASSERT (h->vtable()->markObjects);
- h->vtable()->markObjects(h, engine);
+ h->markChildren(this);
}
}
-void MemoryManager::mark()
+void MemoryManager::collectRoots(MarkStack *markStack)
{
- Value *markBase = engine->jsStackTop;
+ engine->markObjects(markStack);
+
+// qDebug() << " mark stack after engine->mark" << (engine->jsStackTop - markBase);
- engine->markObjects();
+ collectFromJSStack(markStack);
- collectFromJSStack();
+// qDebug() << " mark stack after js stack collect" << (engine->jsStackTop - markBase);
+ m_persistentValues->mark(markStack);
- m_persistentValues->mark(engine);
+// qDebug() << " mark stack after persistants" << (engine->jsStackTop - markBase);
// Preserve QObject ownership rules within JavaScript: A parent with c++ ownership
// keeps all of its children alive in JavaScript.
@@ -841,16 +1032,24 @@ void MemoryManager::mark()
}
if (keepAlive)
- qobjectWrapper->mark(engine);
+ qobjectWrapper->mark(markStack);
- if (engine->jsStackTop >= engine->jsStackLimit)
- drainMarkStack(engine, markBase);
+ if (markStack->top >= markStack->limit)
+ markStack->drain();
}
+}
+
+void MemoryManager::mark()
+{
+ markStackSize = 0;
+
+ MarkStack markStack(engine);
+ collectRoots(&markStack);
- drainMarkStack(engine, markBase);
+ markStack.drain();
}
-void MemoryManager::sweep(bool lastSweep)
+void MemoryManager::sweep(bool lastSweep, ClassDestroyStatsCallback classCountPtr)
{
for (PersistentValueStorage::Iterator it = m_weakValues->begin(); it != m_weakValues->end(); ++it) {
Managed *m = (*it).managed();
@@ -897,30 +1096,29 @@ void MemoryManager::sweep(bool lastSweep)
}
}
- blockAllocator.sweep();
- hugeItemAllocator.sweep();
+ blockAllocator.sweep(classCountPtr);
+ hugeItemAllocator.sweep(classCountPtr);
}
bool MemoryManager::shouldRunGC() const
{
size_t total = blockAllocator.totalSlots();
- size_t usedSlots = blockAllocator.usedSlotsAfterLastSweep;
- if (total > MinSlotsGCLimit && usedSlots * GCOverallocation < total * 100)
+ if (total > MinSlotsGCLimit && usedSlotsAfterLastFullSweep * GCOverallocation < total * 100)
return true;
return false;
}
size_t dumpBins(BlockAllocator *b, bool printOutput = true)
{
- size_t totalFragmentedSlots = 0;
+ size_t totalSlotMem = 0;
if (printOutput)
- qDebug() << "Fragmentation map:";
+ qDebug() << "Slot map:";
for (uint i = 0; i < BlockAllocator::NumBins; ++i) {
uint nEntries = 0;
HeapItem *h = b->freeBins[i];
while (h) {
++nEntries;
- totalFragmentedSlots += h->freeData.availableSlots;
+ totalSlotMem += h->freeData.availableSlots;
h = h->freeData.next;
}
if (printOutput)
@@ -934,8 +1132,8 @@ size_t dumpBins(BlockAllocator *b, bool printOutput = true)
}
if (printOutput)
- qDebug() << " total mem in bins" << totalFragmentedSlots*Chunk::SlotSize;
- return totalFragmentedSlots*Chunk::SlotSize;
+ qDebug() << " total mem in bins" << totalSlotMem*Chunk::SlotSize;
+ return totalSlotMem*Chunk::SlotSize;
}
void MemoryManager::runGC()
@@ -946,6 +1144,7 @@ void MemoryManager::runGC()
}
QScopedValueRollback<bool> gcBlocker(gcBlocked, true);
+// qDebug() << "runGC";
if (!gcStats) {
// uint oldUsed = allocator.usedMem();
@@ -960,22 +1159,29 @@ void MemoryManager::runGC()
const size_t largeItemsBefore = getLargeItemsMem();
qDebug() << "========== GC ==========";
-#ifndef QT_NO_DEBUG
+#ifdef MM_STATS
qDebug() << " Triggered by alloc request of" << lastAllocRequestedSlots << "slots.";
+ qDebug() << " Allocations since last GC" << allocationCount;
+ allocationCount = 0;
#endif
size_t oldChunks = blockAllocator.chunks.size();
qDebug() << "Allocated" << totalMem << "bytes in" << oldChunks << "chunks";
qDebug() << "Fragmented memory before GC" << (totalMem - usedBefore);
dumpBins(&blockAllocator);
+#ifdef MM_STATS
+ nGrayItems = 0;
+#endif
+
QElapsedTimer t;
t.start();
mark();
- qint64 markTime = t.restart();
- sweep();
+ qint64 markTime = t.nsecsElapsed()/1000;
+ t.restart();
+ sweep(false, increaseFreedCountForClass);
const size_t usedAfter = getUsedMem();
const size_t largeItemsAfter = getLargeItemsMem();
- qint64 sweepTime = t.elapsed();
+ qint64 sweepTime = t.nsecsElapsed()/1000;
if (triggeredByUnmanagedHeap) {
qDebug() << "triggered by unmanaged heap:";
@@ -984,12 +1190,27 @@ void MemoryManager::runGC()
qDebug() << " unmanaged heap limit:" << unmanagedHeapSizeGCLimit;
}
size_t memInBins = dumpBins(&blockAllocator);
- qDebug() << "Marked object in" << markTime << "ms.";
- qDebug() << "Sweeped object in" << sweepTime << "ms.";
+ qDebug() << "Marked object in" << markTime << "us.";
+ qDebug() << " " << markStackSize << "objects marked";
+ qDebug() << "Sweeped object in" << sweepTime << "us.";
+
+ // sort our object types by number of freed instances
+ MMStatsHash freedObjectStats;
+ std::swap(freedObjectStats, *freedObjectStatsGlobal());
+ typedef std::pair<const char*, int> ObjectStatInfo;
+ std::vector<ObjectStatInfo> freedObjectsSorted;
+ freedObjectsSorted.reserve(freedObjectStats.count());
+ for (auto it = freedObjectStats.constBegin(); it != freedObjectStats.constEnd(); ++it) {
+ freedObjectsSorted.push_back(std::make_pair(it.key(), it.value()));
+ }
+ std::sort(freedObjectsSorted.begin(), freedObjectsSorted.end(), [](const ObjectStatInfo &a, const ObjectStatInfo &b) {
+ return a.second > b.second && strcmp(a.first, b.first) < 0;
+ });
+
qDebug() << "Used memory before GC:" << usedBefore;
qDebug() << "Used memory after GC:" << usedAfter;
- qDebug() << "Freed up bytes:" << (usedBefore - usedAfter);
- qDebug() << "Freed up chunks:" << (oldChunks - blockAllocator.chunks.size());
+ qDebug() << "Freed up bytes :" << (usedBefore - usedAfter);
+ qDebug() << "Freed up chunks :" << (oldChunks - blockAllocator.chunks.size());
size_t lost = blockAllocator.allocatedMem() - memInBins - usedAfter;
if (lost)
qDebug() << "!!!!!!!!!!!!!!!!!!!!! LOST MEM:" << lost << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
@@ -998,6 +1219,11 @@ void MemoryManager::runGC()
qDebug() << "Large item memory after GC:" << largeItemsAfter;
qDebug() << "Large item memory freed up:" << (largeItemsBefore - largeItemsAfter);
}
+
+ for (auto it = freedObjectsSorted.cbegin(); it != freedObjectsSorted.cend(); ++it) {
+ qDebug().noquote() << QString::fromLatin1("Freed JS type: %1 (%2 instances)").arg(QString::fromLatin1(it->first), QString::number(it->second));
+ }
+
qDebug() << "======== End GC ========";
}
@@ -1005,6 +1231,12 @@ void MemoryManager::runGC()
// ensure we don't 'loose' any memory
Q_ASSERT(blockAllocator.allocatedMem() == getUsedMem() + dumpBins(&blockAllocator, false));
}
+
+ usedSlotsAfterLastFullSweep = blockAllocator.usedSlotsAfterLastSweep;
+
+ // reset all black bits
+ blockAllocator.resetBlackBits();
+ hugeItemAllocator.resetBlackBits();
}
size_t MemoryManager::getUsedMem() const
@@ -1065,7 +1297,7 @@ void MemoryManager::willAllocate(std::size_t size)
#endif // DETAILED_MM_STATS
-void MemoryManager::collectFromJSStack() const
+void MemoryManager::collectFromJSStack(MarkStack *markStack) const
{
Value *v = engine->jsStackBase;
Value *top = engine->jsStackTop;
@@ -1073,7 +1305,7 @@ void MemoryManager::collectFromJSStack() const
Managed *m = v->managed();
if (m && m->inUse())
// Skip pointers to already freed objects, they are bogus as well
- m->mark(engine);
+ m->mark(markStack);
++v;
}
}
diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h
index 77c5885dfe..17957d0cd6 100644
--- a/src/qml/memory/qv4mm_p.h
+++ b/src/qml/memory/qv4mm_p.h
@@ -80,27 +80,28 @@ struct StackAllocator {
StackAllocator(ChunkAllocator *chunkAlloc);
T *allocate() {
- T *m = nextFree->as<T>();
+ HeapItem *m = nextFree;
if (Q_UNLIKELY(nextFree == lastInChunk)) {
nextChunk();
} else {
nextFree += requiredSlots;
}
-#if MM_DEBUG
+#if MM_DEBUG || !defined(QT_NO_DEBUG) || defined(QT_FORCE_ASSERTS)
Chunk *c = m->chunk();
Chunk::setBit(c->objectBitmap, m - c->realBase());
#endif
- return m;
+ return m->as<T>();
}
void free() {
-#if MM_DEBUG
- Chunk::clearBit(item->chunk()->objectBitmap, item - item->chunk()->realBase());
-#endif
if (Q_UNLIKELY(nextFree == firstInChunk)) {
prevChunk();
} else {
nextFree -= requiredSlots;
}
+#if MM_DEBUG || !defined(QT_NO_DEBUG) || defined(QT_FORCE_ASSERTS)
+ Chunk *c = nextFree->chunk();
+ Chunk::clearBit(c->objectBitmap, nextFree - c->realBase());
+#endif
}
void nextChunk();
@@ -152,8 +153,10 @@ struct BlockAllocator {
return used;
}
- void sweep();
+ void sweep(ClassDestroyStatsCallback classCountPtr);
void freeAll();
+ void resetBlackBits();
+ void collectGrayItems(MarkStack *markStack);
// bump allocations
HeapItem *nextFree = 0;
@@ -173,8 +176,10 @@ struct HugeItemAllocator {
{}
HeapItem *allocate(size_t size);
- void sweep();
+ void sweep(ClassDestroyStatsCallback classCountPtr);
void freeAll();
+ void resetBlackBits();
+ void collectGrayItems(MarkStack *markStack);
size_t usedMem() const {
size_t used = 0;
@@ -209,8 +214,8 @@ public:
QV4::Heap::CallContext *allocSimpleCallContext()
{
Heap::CallContext *ctxt = stackAllocator.allocate();
- memset(ctxt, 0, sizeof(Heap::CallContext));
- ctxt->internalClass = CallContext::defaultInternalClass(engine);
+ memset(ctxt, 0, sizeof(Heap::SimpleCallContext));
+ ctxt->internalClass = SimpleCallContext::defaultInternalClass(engine);
Q_ASSERT(ctxt->internalClass && ctxt->internalClass->vtable);
ctxt->init();
return ctxt;
@@ -440,7 +445,6 @@ public:
// called when a JS object grows itself. Specifically: Heap::String::append
void changeUnmanagedHeapSizeUsage(qptrdiff delta) { unmanagedHeapSize += delta; }
-
protected:
/// expects size to be aligned
Heap::Base *allocString(std::size_t unmanagedSize);
@@ -452,10 +456,11 @@ protected:
#endif // DETAILED_MM_STATS
private:
- void collectFromJSStack() const;
+ void collectFromJSStack(MarkStack *markStack) const;
void mark();
- void sweep(bool lastSweep = false);
+ void sweep(bool lastSweep = false, ClassDestroyStatsCallback classCountPtr = nullptr);
bool shouldRunGC() const;
+ void collectRoots(MarkStack *markStack);
public:
QV4::ExecutionEngine *engine;
@@ -469,6 +474,7 @@ public:
std::size_t unmanagedHeapSize = 0; // the amount of bytes of heap that is not managed by the memory manager, but which is held onto by managed items.
std::size_t unmanagedHeapSizeGCLimit;
+ std::size_t usedSlotsAfterLastFullSweep = 0;
bool gcBlocked = false;
bool aggressiveGC = false;
diff --git a/src/qml/memory/qv4mmdefs_p.h b/src/qml/memory/qv4mmdefs_p.h
index ef93971ab8..328797fb5e 100644
--- a/src/qml/memory/qv4mmdefs_p.h
+++ b/src/qml/memory/qv4mmdefs_p.h
@@ -116,22 +116,29 @@ struct Chunk {
HeapItem *realBase();
HeapItem *first();
+ static Q_ALWAYS_INLINE size_t bitmapIndex(size_t index) {
+ return index >> BitShift;
+ }
+ static Q_ALWAYS_INLINE quintptr bitForIndex(size_t index) {
+ return static_cast<quintptr>(1) << (index & (Bits - 1));
+ }
+
static void setBit(quintptr *bitmap, size_t index) {
// Q_ASSERT(index >= HeaderSize/SlotSize && index < ChunkSize/SlotSize);
- bitmap += index >> BitShift;
- quintptr bit = static_cast<quintptr>(1) << (index & (Bits - 1));
+ bitmap += bitmapIndex(index);
+ quintptr bit = bitForIndex(index);
*bitmap |= bit;
}
static void clearBit(quintptr *bitmap, size_t index) {
// Q_ASSERT(index >= HeaderSize/SlotSize && index < ChunkSize/SlotSize);
- bitmap += index >> BitShift;
- quintptr bit = static_cast<quintptr>(1) << (index & (Bits - 1));
+ bitmap += bitmapIndex(index);
+ quintptr bit = bitForIndex(index);
*bitmap &= ~bit;
}
static bool testBit(quintptr *bitmap, size_t index) {
// Q_ASSERT(index >= HeaderSize/SlotSize && index < ChunkSize/SlotSize);
- bitmap += index >> BitShift;
- quintptr bit = static_cast<quintptr>(1) << (index & (Bits - 1));
+ bitmap += bitmapIndex(index);
+ quintptr bit = bitForIndex(index);
return (*bitmap & bit);
}
static void setBits(quintptr *bitmap, size_t index, size_t nBits) {
@@ -179,8 +186,10 @@ struct Chunk {
return usedSlots;
}
- bool sweep();
+ bool sweep(ClassDestroyStatsCallback classCountPtr);
void freeAll();
+ void resetBlackBits();
+ void collectGrayItems(QV4::MarkStack *markStack);
void sortIntoBins(HeapItem **bins, uint nBins);
};
@@ -260,6 +269,91 @@ Q_STATIC_ASSERT(sizeof(HeapItem) == Chunk::SlotSize);
Q_STATIC_ASSERT(QT_POINTER_SIZE*8 == Chunk::Bits);
Q_STATIC_ASSERT((1 << Chunk::BitShift) == Chunk::Bits);
+struct MarkStack {
+ MarkStack(ExecutionEngine *engine);
+ Heap::Base **top = 0;
+ Heap::Base **base = 0;
+ Heap::Base **limit = 0;
+ ExecutionEngine *engine;
+ void push(Heap::Base *m) {
+ *top = m;
+ ++top;
+ }
+ Heap::Base *pop() {
+ --top;
+ return *top;
+ }
+ void drain();
+
+};
+
+// Some helper classes and macros to automate the generation of our
+// tables used for marking objects
+
+enum MarkFlags {
+ Mark_NoMark = 0,
+ Mark_Value = 1,
+ Mark_Pointer = 2,
+ Mark_ValueArray = 3
+};
+
+template <typename T>
+struct MarkFlagEvaluator {
+ static Q_CONSTEXPR quint64 value = 0;
+};
+template <typename T, size_t o>
+struct MarkFlagEvaluator<Heap::Pointer<T, o>> {
+ static Q_CONSTEXPR quint64 value = static_cast<quint64>(Mark_Pointer) << (2*o / sizeof(quintptr));
+};
+template <size_t o>
+struct MarkFlagEvaluator<ValueArray<o>> {
+ static Q_CONSTEXPR quint64 value = static_cast<quint64>(Mark_ValueArray) << (2*o / sizeof(quintptr));
+};
+template <size_t o>
+struct MarkFlagEvaluator<HeapValue<o>> {
+ static Q_CONSTEXPR quint64 value = static_cast<quint64>(Mark_Value) << (2 *o / sizeof(quintptr));
+};
+
+#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION(c, gcType, type, name) \
+ HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_##gcType(c, type, name)
+
+#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_Pointer(c, type, name) Pointer<type, 0> name;
+#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_NoMark(c, type, name) type name;
+#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_HeapValue(c, type, name) HeapValue<0> name;
+#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_ValueArray(c, type, name) type<0> name;
+
+#define HEAP_OBJECT_MEMBER_EXPANSION(c, gcType, type, name) \
+ HEAP_OBJECT_MEMBER_EXPANSION_##gcType(c, type, name)
+
+#define HEAP_OBJECT_MEMBER_EXPANSION_Pointer(c, type, name) \
+ Pointer<type, offsetof(c##OffsetStruct, name) + baseOffset> name;
+#define HEAP_OBJECT_MEMBER_EXPANSION_NoMark(c, type, name) \
+ type name;
+#define HEAP_OBJECT_MEMBER_EXPANSION_HeapValue(c, type, name) \
+ HeapValue<offsetof(c##OffsetStruct, name) + baseOffset> name;
+#define HEAP_OBJECT_MEMBER_EXPANSION_ValueArray(c, type, name) \
+ type<offsetof(c##OffsetStruct, name) + baseOffset> name;
+
+#define HEAP_OBJECT_MARK_EXPANSION(class, gcType, type, name) \
+ MarkFlagEvaluator<decltype(class::name)>::value |
+
+#define DECLARE_HEAP_OBJECT(name, base) \
+struct name##OffsetStruct { \
+ name##Members(name, HEAP_OBJECT_OFFSET_MEMBER_EXPANSION) \
+}; \
+struct name##SizeStruct : base, name##OffsetStruct {}; \
+struct name##Data { \
+ static Q_CONSTEXPR size_t baseOffset = sizeof(name##SizeStruct) - sizeof(name##OffsetStruct); \
+ name##Members(name, HEAP_OBJECT_MEMBER_EXPANSION) \
+}; \
+Q_STATIC_ASSERT(sizeof(name##SizeStruct) == sizeof(name##Data) + name##Data::baseOffset); \
+static Q_CONSTEXPR quint64 name##_markTable = \
+ (name##Members(name##Data, HEAP_OBJECT_MARK_EXPANSION) 0) | QV4::Heap::base::markTable; \
+ \
+struct name : base, name##Data
+
+#define DECLARE_MARK_TABLE(class) static Q_CONSTEXPR quint64 markTable = class##_markTable
+
}
QT_END_NAMESPACE
diff --git a/src/qml/memory/qv4writebarrier_p.h b/src/qml/memory/qv4writebarrier_p.h
new file mode 100644
index 0000000000..86fd28000d
--- /dev/null
+++ b/src/qml/memory/qv4writebarrier_p.h
@@ -0,0 +1,206 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4WRITEBARRIER_P_H
+#define QV4WRITEBARRIER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qv4global_p.h>
+#include <private/qv4value_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#define WRITEBARRIER_none 1
+
+#define WRITEBARRIER(x) (1/WRITEBARRIER_##x == 1)
+
+namespace QV4 {
+
+namespace WriteBarrier {
+
+enum Type {
+ NoBarrier,
+ Barrier
+};
+
+enum NewValueType {
+ Primitive,
+ Object,
+ Unknown
+};
+
+// ### this needs to be filled with a real memory fence once marking is concurrent
+Q_ALWAYS_INLINE void fence() {}
+
+#if WRITEBARRIER(none)
+
+template <NewValueType type>
+static Q_CONSTEXPR inline bool isRequired() {
+ return false;
+}
+
+inline void write(EngineBase *engine, Heap::Base *base, Value *slot, Value value)
+{
+ Q_UNUSED(engine);
+ Q_UNUSED(base);
+ *slot = value;
+}
+
+inline void write(EngineBase *engine, Heap::Base *base, Value *slot, Heap::Base *value)
+{
+ Q_UNUSED(engine);
+ Q_UNUSED(base);
+ *slot = value;
+}
+
+inline void write(EngineBase *engine, Heap::Base *base, Heap::Base **slot, Heap::Base *value)
+{
+ Q_UNUSED(engine);
+ Q_UNUSED(base);
+ *slot = value;
+}
+
+#endif
+
+}
+
+namespace Heap {
+
+template <typename T, size_t o>
+struct Pointer {
+ static Q_CONSTEXPR size_t offset = o;
+ T operator->() const { return ptr; }
+ operator T () const { return ptr; }
+
+ Heap::Base *base() {
+ Heap::Base *base = reinterpret_cast<Heap::Base *>(this) - (offset/sizeof(Heap::Base));
+ Q_ASSERT(base->inUse());
+ return base;
+ }
+
+ void set(EngineBase *e, T newVal) {
+ WriteBarrier::write(e, base(), reinterpret_cast<Heap::Base **>(&ptr), reinterpret_cast<Heap::Base *>(newVal));
+ }
+
+ template <typename Type>
+ Type *cast() { return static_cast<Type *>(ptr); }
+
+private:
+ T ptr;
+};
+typedef Pointer<char *, 0> V4PointerCheck;
+V4_ASSERT_IS_TRIVIAL(V4PointerCheck)
+
+}
+
+template <size_t offset>
+struct HeapValue : Value {
+ Heap::Base *base() {
+ Heap::Base *base = reinterpret_cast<Heap::Base *>(this) - (offset/sizeof(Heap::Base));
+ Q_ASSERT(base->inUse());
+ return base;
+ }
+
+ void set(EngineBase *e, const Value &newVal) {
+ WriteBarrier::write(e, base(), this, newVal);
+ }
+ void set(EngineBase *e, Heap::Base *b) {
+ WriteBarrier::write(e, base(), this, b);
+ }
+};
+
+template <size_t offset>
+struct ValueArray {
+ uint size;
+ uint alloc;
+ Value values[1];
+
+ Heap::Base *base() {
+ Heap::Base *base = reinterpret_cast<Heap::Base *>(this) - (offset/sizeof(Heap::Base));
+ Q_ASSERT(base->inUse());
+ return base;
+ }
+
+ void set(EngineBase *e, uint index, Value v) {
+ WriteBarrier::write(e, base(), values + index, v);
+ }
+ void set(EngineBase *e, uint index, Heap::Base *b) {
+ WriteBarrier::write(e, base(), values + index, b);
+ }
+ inline const Value &operator[] (uint index) const {
+ Q_ASSERT(index < alloc);
+ return values[index];
+ }
+ inline const Value *data() const {
+ return values;
+ }
+
+ void insertData(EngineBase *e, uint index, Value v) {
+ for (uint i = size - 1; i > index; --i) {
+ values[i] = values[i - 1];
+ }
+ set(e, index, v);
+ }
+ void removeData(EngineBase *e, uint index, int n = 1) {
+ Q_UNUSED(e);
+ for (uint i = index; i < size - n; ++i) {
+ values[i] = values[i + n];
+ }
+ }
+};
+
+// It's really important that the offset of values in this structure is
+// constant across all architecture, otherwise JIT cross-compiled code will
+// have wrong offsets between host and target.
+Q_STATIC_ASSERT(offsetof(ValueArray<0>, values) == 8);
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g
index 9cd212015e..395e62e657 100644
--- a/src/qml/parser/qqmljs.g
+++ b/src/qml/parser/qqmljs.g
@@ -71,12 +71,13 @@
%token T_VAR "var" T_VOID "void" T_WHILE "while"
%token T_WITH "with" T_XOR "^" T_XOR_EQ "^="
%token T_NULL "null" T_TRUE "true" T_FALSE "false"
-%token T_CONST "const"
+%token T_CONST "const" T_LET "let"
%token T_DEBUGGER "debugger"
%token T_RESERVED_WORD "reserved word"
%token T_MULTILINE_STRING_LITERAL "multiline string literal"
%token T_COMMENT "comment"
%token T_COMPATIBILITY_SEMICOLON
+%token T_ENUM "enum"
--- context keywords.
%token T_PUBLIC "public"
@@ -281,6 +282,7 @@ public:
AST::UiArrayMemberList *UiArrayMemberList;
AST::UiQualifiedId *UiQualifiedId;
AST::UiQualifiedPragmaId *UiQualifiedPragmaId;
+ AST::UiEnumMemberList *UiEnumMemberList;
};
public:
@@ -1207,6 +1209,37 @@ case $rule_number: {
} break;
./
+UiObjectMember: T_ENUM T_IDENTIFIER T_LBRACE EnumMemberList T_RBRACE;
+/.
+case $rule_number: {
+ AST::UiEnumDeclaration *enumDeclaration = new (pool) AST::UiEnumDeclaration(stringRef(2), sym(4).UiEnumMemberList->finish());
+ enumDeclaration->enumToken = loc(1);
+ enumDeclaration->rbraceToken = loc(5);
+ sym(1).Node = enumDeclaration;
+ break;
+}
+./
+
+EnumMemberList: T_IDENTIFIER;
+/.
+case $rule_number: {
+ AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(stringRef(1));
+ node->memberToken = loc(1);
+ sym(1).Node = node;
+ break;
+}
+./
+
+EnumMemberList: EnumMemberList T_COMMA T_IDENTIFIER;
+/.
+case $rule_number: {
+ AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(sym(1).UiEnumMemberList, stringRef(3));
+ node->memberToken = loc(3);
+ sym(1).Node = node;
+ break;
+}
+./
+
JsIdentifier: T_IDENTIFIER;
JsIdentifier: T_PROPERTY ;
@@ -1602,6 +1635,7 @@ ReservedIdentifier: T_DEFAULT ;
ReservedIdentifier: T_DELETE ;
ReservedIdentifier: T_DO ;
ReservedIdentifier: T_ELSE ;
+ReservedIdentifier: T_ENUM ;
ReservedIdentifier: T_FALSE ;
ReservedIdentifier: T_FINALLY ;
ReservedIdentifier: T_FOR ;
@@ -1622,6 +1656,7 @@ ReservedIdentifier: T_VAR ;
ReservedIdentifier: T_VOID ;
ReservedIdentifier: T_WHILE ;
ReservedIdentifier: T_CONST ;
+ReservedIdentifier: T_LET ;
ReservedIdentifier: T_DEBUGGER ;
ReservedIdentifier: T_RESERVED_WORD ;
ReservedIdentifier: T_WITH ;
@@ -2486,14 +2521,26 @@ VariableStatement: VariableDeclarationKind VariableDeclarationList T_AUTOMATIC_S
VariableStatement: VariableDeclarationKind VariableDeclarationList T_SEMICOLON ;
/.
case $rule_number: {
- AST::VariableStatement *node = new (pool) AST::VariableStatement(
- sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST));
+ AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope;
+ if (sym(1).ival == T_LET)
+ s = AST::VariableDeclaration::BlockScope;
+ else if (sym(1).ival == T_CONST)
+ s = AST::VariableDeclaration::ReadOnlyBlockScope;
+
+ AST::VariableStatement *node = new (pool) AST::VariableStatement(sym(2).VariableDeclarationList->finish(s));
node->declarationKindToken = loc(1);
node->semicolonToken = loc(3);
sym(1).Node = node;
} break;
./
+VariableDeclarationKind: T_LET ;
+/.
+case $rule_number: {
+ sym(1).ival = T_LET;
+} break;
+./
+
VariableDeclarationKind: T_CONST ;
/.
case $rule_number: {
@@ -2542,7 +2589,8 @@ case $rule_number: {
VariableDeclaration: JsIdentifier InitialiserOpt ;
/.
case $rule_number: {
- AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression);
+ AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope;
+ AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression, s);
node->identifierToken = loc(1);
sym(1).Node = node;
} break;
@@ -2551,7 +2599,8 @@ case $rule_number: {
VariableDeclarationNotIn: JsIdentifier InitialiserNotInOpt ;
/.
case $rule_number: {
- AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression);
+ AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope;
+ AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression, s);
node->identifierToken = loc(1);
sym(1).Node = node;
} break;
@@ -2677,8 +2726,9 @@ case $rule_number: {
IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationListNotIn T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ;
/.
case $rule_number: {
+ AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope;
AST::LocalForStatement *node = new (pool) AST::LocalForStatement(
- sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression,
+ sym(4).VariableDeclarationList->finish(s), sym(6).Expression,
sym(8).Expression, sym(10).Statement);
node->forToken = loc(1);
node->lparenToken = loc(2);
diff --git a/src/qml/parser/qqmljsast.cpp b/src/qml/parser/qqmljsast.cpp
index 7f8cecca8f..2433522f42 100644
--- a/src/qml/parser/qqmljsast.cpp
+++ b/src/qml/parser/qqmljsast.cpp
@@ -967,6 +967,23 @@ void UiSourceElement::accept0(Visitor *visitor)
visitor->endVisit(this);
}
+void UiEnumDeclaration::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(members, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiEnumMemberList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
} } // namespace QQmlJS::AST
QT_QML_END_NAMESPACE
diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h
index 9b06bf3d31..d458b2cd35 100644
--- a/src/qml/parser/qqmljsast_p.h
+++ b/src/qml/parser/qqmljsast_p.h
@@ -218,7 +218,9 @@ public:
Kind_UiQualifiedPragmaId,
Kind_UiScriptBinding,
Kind_UiSourceElement,
- Kind_UiHeaderItemList
+ Kind_UiHeaderItemList,
+ Kind_UiEnumDeclaration,
+ Kind_UiEnumMemberList
};
inline Node()
@@ -1315,10 +1317,18 @@ class QML_PARSER_EXPORT VariableDeclaration: public Node
public:
QQMLJS_DECLARE_AST_NODE(VariableDeclaration)
- VariableDeclaration(const QStringRef &n, ExpressionNode *e):
- name (n), expression (e), readOnly(false)
+ enum VariableScope {
+ FunctionScope,
+ BlockScope, // let
+ ReadOnlyBlockScope // const
+ };
+
+ VariableDeclaration(const QStringRef &n, ExpressionNode *e, VariableScope s):
+ name (n), expression (e), scope(s)
{ kind = K; }
+ bool isLexicallyScoped() const { return scope != FunctionScope; }
+
void accept0(Visitor *visitor) override;
SourceLocation firstSourceLocation() const override
@@ -1330,8 +1340,8 @@ public:
// attributes
QStringRef name;
ExpressionNode *expression;
- bool readOnly;
SourceLocation identifierToken;
+ VariableScope scope;
};
class QML_PARSER_EXPORT VariableDeclarationList: public Node
@@ -1363,14 +1373,13 @@ public:
return declaration->lastSourceLocation();
}
- inline VariableDeclarationList *finish (bool readOnly)
+ inline VariableDeclarationList *finish(VariableDeclaration::VariableScope s)
{
VariableDeclarationList *front = next;
next = 0;
- if (readOnly) {
- VariableDeclarationList *vdl;
- for (vdl = front; vdl != 0; vdl = vdl->next)
- vdl->declaration->readOnly = true;
+ VariableDeclarationList *vdl;
+ for (vdl = front; vdl != 0; vdl = vdl->next) {
+ vdl->declaration->scope = s;
}
return front;
}
@@ -2778,6 +2787,69 @@ public:
SourceLocation rbracketToken;
};
+class QML_PARSER_EXPORT UiEnumMemberList: public Node
+{
+ QQMLJS_DECLARE_AST_NODE(UiEnumMemberList)
+public:
+ UiEnumMemberList(const QStringRef &member)
+ : next(this), member(member)
+ { kind = K; }
+
+ UiEnumMemberList(UiEnumMemberList *previous, const QStringRef &member)
+ : member(member)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ SourceLocation firstSourceLocation() const override
+ { return memberToken; }
+
+ SourceLocation lastSourceLocation() const override
+ { return next ? next->lastSourceLocation() : memberToken; }
+
+ void accept0(Visitor *visitor) override;
+
+ UiEnumMemberList *finish()
+ {
+ UiEnumMemberList *head = next;
+ next = 0;
+ return head;
+ }
+
+// attributes
+ UiEnumMemberList *next;
+ QStringRef member;
+ SourceLocation memberToken;
+};
+
+class QML_PARSER_EXPORT UiEnumDeclaration: public UiObjectMember
+{
+public:
+ QQMLJS_DECLARE_AST_NODE(UiEnumDeclaration)
+
+ UiEnumDeclaration(const QStringRef &name,
+ UiEnumMemberList *members)
+ : name(name)
+ , members(members)
+ { kind = K; }
+
+ SourceLocation firstSourceLocation() const override
+ { return enumToken; }
+
+ SourceLocation lastSourceLocation() const override
+ { return rbraceToken; }
+
+ void accept0(Visitor *visitor) override;
+
+// attributes
+ SourceLocation enumToken;
+ SourceLocation rbraceToken;
+ QStringRef name;
+ UiEnumMemberList *members;
+};
+
} } // namespace AST
diff --git a/src/qml/parser/qqmljsastfwd_p.h b/src/qml/parser/qqmljsastfwd_p.h
index 189eb72a57..140a757e51 100644
--- a/src/qml/parser/qqmljsastfwd_p.h
+++ b/src/qml/parser/qqmljsastfwd_p.h
@@ -181,6 +181,8 @@ class UiArrayMemberList;
class UiQualifiedId;
class UiQualifiedPragmaId;
class UiHeaderItemList;
+class UiEnumDeclaration;
+class UiEnumMemberList;
} } // namespace AST
diff --git a/src/qml/parser/qqmljsastvisitor_p.h b/src/qml/parser/qqmljsastvisitor_p.h
index e582a8f6a7..13218f0e98 100644
--- a/src/qml/parser/qqmljsastvisitor_p.h
+++ b/src/qml/parser/qqmljsastvisitor_p.h
@@ -84,6 +84,8 @@ public:
virtual bool visit(UiArrayMemberList *) { return true; }
virtual bool visit(UiQualifiedId *) { return true; }
virtual bool visit(UiQualifiedPragmaId *) { return true; }
+ virtual bool visit(UiEnumDeclaration *) { return true; }
+ virtual bool visit(UiEnumMemberList *) { return true; }
virtual void endVisit(UiProgram *) {}
virtual void endVisit(UiImport *) {}
@@ -101,6 +103,8 @@ public:
virtual void endVisit(UiArrayMemberList *) {}
virtual void endVisit(UiQualifiedId *) {}
virtual void endVisit(UiQualifiedPragmaId *) {}
+ virtual void endVisit(UiEnumDeclaration *) {}
+ virtual void endVisit(UiEnumMemberList *) { }
// QQmlJS
virtual bool visit(ThisExpression *) { return true; }
diff --git a/src/qml/parser/qqmljsgrammar.cpp b/src/qml/parser/qqmljsgrammar.cpp
index b27f4af080..8e47898e2f 100644
--- a/src/qml/parser/qqmljsgrammar.cpp
+++ b/src/qml/parser/qqmljsgrammar.cpp
@@ -43,1049 +43,1086 @@
QT_BEGIN_NAMESPACE
const char *const QQmlJSGrammar::spell [] = {
- "end of file", "&", "&&", "&=", "break", "case", "catch", ":", ",", "continue",
- "default", "delete", "/", "/=", "do", ".", "else", "=", "==", "===",
- "finally", "for", "function", ">=", ">", ">>", ">>=", ">>>", ">>>=", "identifier",
- "if", "in", "instanceof", "{", "[", "<=", "(", "<", "<<", "<<=",
- "-", "-=", "--", "new", "!", "!=", "!==", "numeric literal", "|", "|=",
- "||", "+", "+=", "++", "?", "}", "]", "%", "%=", "return",
- ")", ";", 0, "*", "*=", "string literal", "property", "signal", "readonly", "switch",
- "this", "throw", "~", "try", "typeof", "var", "void", "while", "with", "^",
- "^=", "null", "true", "false", "const", "debugger", "reserved word", "multiline string literal", "comment", 0,
- "public", "import", "pragma", "as", "on", "get", "set", 0, 0, 0,
- 0, 0, 0, 0, 0, 0};
+ "end of file", "&", "&&", "&=", "break", "case", "catch", ":", ",", "continue",
+ "default", "delete", "/", "/=", "do", ".", "else", "=", "==", "===",
+ "finally", "for", "function", ">=", ">", ">>", ">>=", ">>>", ">>>=", "identifier",
+ "if", "in", "instanceof", "{", "[", "<=", "(", "<", "<<", "<<=",
+ "-", "-=", "--", "new", "!", "!=", "!==", "numeric literal", "|", "|=",
+ "||", "+", "+=", "++", "?", "}", "]", "%", "%=", "return",
+ ")", ";", 0, "*", "*=", "string literal", "property", "signal", "readonly", "switch",
+ "this", "throw", "~", "try", "typeof", "var", "void", "while", "with", "^",
+ "^=", "null", "true", "false", "const", "let", "debugger", "reserved word", "multiline string literal", "comment",
+ 0, "enum", "public", "import", "pragma", "as", "on", "get", "set", 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
const short QQmlJSGrammar::lhs [] = {
- 106, 106, 106, 106, 106, 106, 107, 113, 113, 116,
- 116, 116, 116, 119, 121, 117, 117, 118, 118, 118,
- 118, 118, 118, 118, 118, 122, 123, 115, 114, 126,
- 126, 127, 127, 128, 128, 125, 111, 111, 111, 111,
- 130, 130, 130, 130, 130, 130, 130, 111, 138, 138,
- 138, 138, 139, 139, 140, 140, 111, 111, 111, 111,
- 111, 111, 111, 111, 111, 111, 111, 111, 111, 111,
- 111, 111, 111, 111, 111, 111, 124, 124, 124, 124,
- 124, 124, 124, 143, 143, 143, 143, 143, 143, 143,
- 143, 143, 143, 143, 143, 143, 143, 143, 143, 143,
- 143, 129, 145, 145, 145, 145, 144, 144, 149, 149,
- 149, 147, 147, 150, 150, 150, 150, 153, 153, 153,
- 153, 153, 153, 153, 153, 153, 153, 153, 153, 153,
- 153, 153, 153, 153, 153, 153, 153, 153, 153, 153,
- 153, 153, 153, 153, 153, 153, 153, 153, 154, 154,
- 120, 120, 120, 120, 120, 157, 157, 158, 158, 158,
- 158, 156, 156, 159, 159, 160, 160, 161, 161, 161,
- 162, 162, 162, 162, 162, 162, 162, 162, 162, 162,
- 163, 163, 163, 163, 164, 164, 164, 165, 165, 165,
- 165, 166, 166, 166, 166, 166, 166, 166, 167, 167,
- 167, 167, 167, 167, 168, 168, 168, 168, 168, 169,
- 169, 169, 169, 169, 170, 170, 171, 171, 172, 172,
- 173, 173, 174, 174, 175, 175, 176, 176, 177, 177,
- 178, 178, 179, 179, 180, 180, 181, 181, 148, 148,
- 182, 182, 183, 183, 183, 183, 183, 183, 183, 183,
- 183, 183, 183, 183, 109, 109, 184, 184, 185, 185,
- 186, 186, 108, 108, 108, 108, 108, 108, 108, 108,
- 108, 108, 108, 108, 108, 108, 108, 131, 195, 195,
- 194, 194, 142, 142, 196, 196, 197, 197, 199, 199,
- 198, 200, 203, 201, 201, 204, 202, 202, 132, 133,
- 133, 134, 134, 187, 187, 187, 187, 187, 187, 187,
- 187, 188, 188, 188, 188, 189, 189, 189, 189, 190,
- 190, 135, 136, 205, 205, 208, 208, 206, 206, 209,
- 207, 191, 192, 192, 137, 137, 137, 210, 211, 193,
- 193, 212, 141, 155, 155, 213, 213, 152, 152, 151,
- 151, 214, 112, 112, 215, 215, 110, 110, 146, 146,
- 216};
+ 108, 108, 108, 108, 108, 108, 109, 115, 115, 118,
+ 118, 118, 118, 121, 123, 119, 119, 120, 120, 120,
+ 120, 120, 120, 120, 120, 124, 125, 117, 116, 128,
+ 128, 129, 129, 130, 130, 127, 113, 113, 113, 113,
+ 132, 132, 132, 132, 132, 132, 132, 113, 140, 140,
+ 140, 140, 141, 141, 142, 142, 113, 113, 113, 113,
+ 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
+ 113, 113, 113, 113, 113, 113, 113, 145, 145, 126,
+ 126, 126, 126, 126, 126, 126, 146, 146, 146, 146,
+ 146, 146, 146, 146, 146, 146, 146, 146, 146, 146,
+ 146, 146, 146, 146, 131, 148, 148, 148, 148, 147,
+ 147, 152, 152, 152, 150, 150, 153, 153, 153, 153,
+ 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
+ 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
+ 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
+ 156, 156, 156, 157, 157, 122, 122, 122, 122, 122,
+ 160, 160, 161, 161, 161, 161, 159, 159, 162, 162,
+ 163, 163, 164, 164, 164, 165, 165, 165, 165, 165,
+ 165, 165, 165, 165, 165, 166, 166, 166, 166, 167,
+ 167, 167, 168, 168, 168, 168, 169, 169, 169, 169,
+ 169, 169, 169, 170, 170, 170, 170, 170, 170, 171,
+ 171, 171, 171, 171, 172, 172, 172, 172, 172, 173,
+ 173, 174, 174, 175, 175, 176, 176, 177, 177, 178,
+ 178, 179, 179, 180, 180, 181, 181, 182, 182, 183,
+ 183, 184, 184, 151, 151, 185, 185, 186, 186, 186,
+ 186, 186, 186, 186, 186, 186, 186, 186, 186, 111,
+ 111, 187, 187, 188, 188, 189, 189, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 133, 198, 198, 197, 197, 144, 144, 199,
+ 199, 199, 200, 200, 202, 202, 201, 203, 206, 204,
+ 204, 207, 205, 205, 134, 135, 135, 136, 136, 190,
+ 190, 190, 190, 190, 190, 190, 190, 191, 191, 191,
+ 191, 192, 192, 192, 192, 193, 193, 137, 138, 208,
+ 208, 211, 211, 209, 209, 212, 210, 194, 195, 195,
+ 139, 139, 139, 213, 214, 196, 196, 215, 143, 158,
+ 158, 216, 216, 155, 155, 154, 154, 217, 114, 114,
+ 218, 218, 112, 112, 149, 149, 219
+};
const short QQmlJSGrammar::rhs [] = {
- 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
- 1, 2, 2, 1, 1, 2, 2, 2, 2, 3,
- 3, 5, 5, 4, 4, 2, 2, 0, 1, 1,
- 2, 1, 3, 2, 3, 2, 1, 5, 4, 4,
- 1, 1, 1, 1, 1, 1, 1, 3, 1, 1,
- 1, 3, 0, 1, 2, 4, 6, 6, 3, 3,
- 7, 7, 4, 4, 5, 5, 8, 8, 5, 6,
- 6, 10, 6, 7, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 2, 3, 3, 4, 5, 3, 4,
- 3, 1, 1, 2, 3, 4, 1, 2, 3, 7,
- 8, 1, 3, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 4, 3, 5, 1, 2, 4, 4, 4,
- 3, 0, 1, 1, 3, 1, 1, 1, 2, 2,
- 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 3, 3, 3, 1, 3, 3, 1, 3, 3,
- 3, 1, 3, 3, 3, 3, 3, 3, 1, 3,
- 3, 3, 3, 3, 1, 3, 3, 3, 3, 1,
- 3, 3, 3, 3, 1, 3, 1, 3, 1, 3,
- 1, 3, 1, 3, 1, 3, 1, 3, 1, 3,
- 1, 3, 1, 3, 1, 5, 1, 5, 1, 3,
- 1, 3, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 3, 0, 1, 1, 3,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 3, 1, 2,
- 0, 1, 3, 3, 1, 1, 1, 3, 1, 3,
- 2, 2, 2, 0, 1, 2, 0, 1, 1, 2,
- 2, 7, 5, 7, 7, 7, 5, 9, 10, 7,
- 8, 2, 2, 3, 3, 2, 2, 3, 3, 3,
- 3, 5, 5, 3, 5, 1, 2, 0, 1, 4,
- 3, 3, 3, 3, 3, 3, 4, 5, 2, 2,
- 2, 1, 8, 8, 7, 1, 3, 0, 1, 0,
- 1, 1, 1, 1, 1, 2, 1, 1, 0, 1,
- 2};
+ 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
+ 1, 2, 2, 1, 1, 2, 2, 2, 2, 3,
+ 3, 5, 5, 4, 4, 2, 2, 0, 1, 1,
+ 2, 1, 3, 2, 3, 2, 1, 5, 4, 4,
+ 1, 1, 1, 1, 1, 1, 1, 3, 1, 1,
+ 1, 3, 0, 1, 2, 4, 6, 6, 3, 3,
+ 7, 7, 4, 4, 5, 5, 8, 8, 5, 6,
+ 6, 10, 6, 7, 1, 1, 5, 1, 3, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 2, 3, 3, 4,
+ 5, 3, 4, 3, 1, 1, 2, 3, 4, 1,
+ 2, 3, 7, 8, 1, 3, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 4, 3, 5,
+ 1, 2, 4, 4, 4, 3, 0, 1, 1, 3,
+ 1, 1, 1, 2, 2, 1, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 1, 3, 3, 3, 1,
+ 3, 3, 1, 3, 3, 3, 1, 3, 3, 3,
+ 3, 3, 3, 1, 3, 3, 3, 3, 3, 1,
+ 3, 3, 3, 3, 1, 3, 3, 3, 3, 1,
+ 3, 1, 3, 1, 3, 1, 3, 1, 3, 1,
+ 3, 1, 3, 1, 3, 1, 3, 1, 3, 1,
+ 5, 1, 5, 1, 3, 1, 3, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 3, 0, 1, 1, 3, 0, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 3, 1, 2, 0, 1, 3, 3, 1,
+ 1, 1, 1, 3, 1, 3, 2, 2, 2, 0,
+ 1, 2, 0, 1, 1, 2, 2, 7, 5, 7,
+ 7, 7, 5, 9, 10, 7, 8, 2, 2, 3,
+ 3, 2, 2, 3, 3, 3, 3, 5, 5, 3,
+ 5, 1, 2, 0, 1, 4, 3, 3, 3, 3,
+ 3, 3, 4, 5, 2, 2, 2, 1, 8, 8,
+ 7, 1, 3, 0, 1, 0, 1, 1, 1, 1,
+ 1, 2, 1, 1, 0, 1, 2
+};
const short QQmlJSGrammar::action_default [] = {
- 0, 0, 28, 0, 0, 0, 28, 0, 188, 255,
- 219, 227, 223, 167, 239, 215, 3, 152, 85, 168,
- 231, 235, 156, 185, 166, 171, 151, 205, 192, 0,
- 92, 93, 88, 0, 82, 77, 359, 0, 0, 0,
- 0, 90, 0, 0, 86, 89, 81, 0, 0, 78,
- 80, 83, 79, 91, 84, 0, 87, 0, 0, 181,
- 0, 0, 168, 187, 170, 169, 0, 0, 0, 183,
- 184, 182, 186, 0, 216, 0, 0, 0, 0, 206,
- 0, 0, 0, 0, 0, 0, 196, 0, 0, 0,
- 190, 191, 189, 194, 198, 197, 195, 193, 208, 207,
- 209, 0, 224, 0, 220, 0, 0, 162, 149, 161,
- 150, 118, 119, 120, 145, 121, 146, 122, 123, 124,
- 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
- 147, 135, 136, 137, 138, 139, 140, 141, 142, 143,
- 144, 148, 0, 0, 160, 256, 163, 0, 164, 0,
- 165, 159, 0, 252, 245, 243, 250, 251, 249, 248,
- 254, 247, 246, 244, 253, 240, 0, 228, 0, 0,
- 232, 0, 0, 236, 0, 0, 162, 154, 0, 153,
- 0, 158, 172, 0, 348, 348, 349, 0, 346, 0,
- 347, 0, 350, 263, 270, 269, 277, 265, 0, 266,
- 0, 351, 0, 358, 267, 268, 85, 273, 271, 355,
- 352, 357, 274, 0, 285, 0, 0, 0, 0, 342,
- 0, 359, 257, 299, 0, 0, 0, 286, 0, 0,
- 275, 276, 0, 264, 272, 300, 301, 0, 348, 0,
- 0, 350, 0, 343, 344, 0, 332, 356, 0, 316,
- 317, 318, 319, 0, 312, 313, 314, 315, 340, 341,
- 0, 0, 0, 0, 0, 304, 305, 306, 261, 259,
- 221, 229, 225, 241, 217, 262, 0, 168, 233, 237,
- 210, 199, 0, 0, 218, 0, 0, 0, 0, 211,
- 0, 0, 0, 0, 0, 203, 201, 204, 202, 200,
- 213, 212, 214, 0, 226, 0, 222, 0, 260, 168,
- 0, 242, 257, 258, 0, 257, 0, 0, 308, 0,
- 0, 0, 310, 0, 230, 0, 0, 234, 0, 0,
- 238, 297, 0, 289, 298, 292, 0, 296, 0, 257,
- 290, 0, 257, 0, 0, 309, 0, 0, 0, 311,
- 0, 0, 0, 303, 0, 302, 85, 112, 360, 0,
- 0, 117, 279, 282, 0, 118, 285, 121, 146, 123,
- 124, 88, 128, 129, 82, 130, 133, 86, 89, 257,
- 83, 91, 136, 84, 138, 87, 140, 141, 286, 143,
- 144, 148, 0, 114, 113, 116, 100, 115, 99, 0,
- 109, 280, 278, 0, 0, 0, 350, 0, 110, 156,
- 157, 162, 0, 155, 0, 320, 321, 0, 348, 0,
- 0, 350, 0, 111, 0, 0, 0, 323, 328, 326,
- 329, 0, 0, 327, 328, 0, 324, 0, 325, 281,
- 331, 0, 281, 330, 0, 333, 334, 0, 281, 335,
- 336, 0, 0, 337, 0, 0, 0, 338, 339, 174,
- 173, 0, 0, 0, 307, 0, 0, 0, 322, 294,
- 287, 0, 295, 291, 0, 293, 283, 0, 284, 288,
- 0, 0, 350, 0, 345, 103, 0, 0, 107, 94,
- 0, 96, 105, 0, 97, 106, 108, 98, 104, 95,
- 0, 101, 178, 176, 180, 177, 175, 179, 353, 6,
- 354, 4, 2, 75, 102, 0, 0, 78, 80, 79,
- 37, 5, 0, 76, 0, 51, 50, 49, 0, 0,
- 51, 0, 0, 0, 52, 0, 67, 68, 0, 65,
- 0, 66, 41, 42, 43, 44, 46, 47, 71, 45,
- 0, 51, 0, 0, 0, 0, 0, 61, 0, 62,
- 0, 0, 32, 0, 0, 72, 33, 0, 36, 34,
- 30, 0, 35, 31, 0, 63, 0, 64, 156, 0,
- 69, 73, 0, 0, 0, 0, 156, 281, 0, 70,
- 85, 118, 285, 121, 146, 123, 124, 88, 128, 129,
- 130, 133, 86, 89, 257, 91, 136, 84, 138, 87,
- 140, 141, 286, 143, 144, 148, 74, 0, 59, 53,
- 60, 54, 0, 0, 0, 0, 56, 0, 57, 58,
- 55, 0, 0, 0, 0, 48, 0, 38, 39, 0,
- 40, 8, 0, 0, 9, 0, 11, 0, 10, 0,
- 1, 27, 15, 14, 26, 13, 12, 29, 7, 0,
- 18, 0, 19, 0, 24, 25, 0, 20, 21, 0,
- 22, 23, 16, 17, 361};
+ 0, 0, 28, 0, 0, 0, 28, 0, 193, 260,
+ 224, 232, 228, 172, 244, 220, 3, 157, 88, 173,
+ 236, 240, 161, 190, 171, 176, 156, 210, 197, 0,
+ 95, 96, 91, 0, 85, 80, 365, 0, 0, 0,
+ 0, 93, 0, 0, 89, 92, 84, 0, 0, 81,
+ 83, 86, 82, 94, 87, 0, 90, 0, 0, 186,
+ 0, 0, 173, 192, 175, 174, 0, 0, 0, 188,
+ 189, 187, 191, 0, 221, 0, 0, 0, 0, 211,
+ 0, 0, 0, 0, 0, 0, 201, 0, 0, 0,
+ 195, 196, 194, 199, 203, 202, 200, 198, 213, 212,
+ 214, 0, 229, 0, 225, 0, 0, 167, 154, 166,
+ 155, 121, 122, 123, 149, 124, 151, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 150,
+ 137, 138, 152, 139, 140, 141, 142, 143, 144, 145,
+ 146, 147, 148, 153, 0, 0, 165, 261, 168, 0,
+ 169, 0, 170, 164, 0, 257, 250, 248, 255, 256,
+ 254, 253, 259, 252, 251, 249, 258, 245, 0, 233,
+ 0, 0, 237, 0, 0, 241, 0, 0, 167, 159,
+ 0, 158, 0, 163, 177, 0, 354, 354, 355, 0,
+ 352, 0, 353, 0, 356, 268, 275, 274, 282, 270,
+ 0, 271, 0, 357, 0, 364, 272, 273, 88, 278,
+ 276, 361, 358, 363, 279, 0, 291, 0, 0, 0,
+ 0, 348, 0, 365, 290, 262, 305, 0, 0, 0,
+ 292, 0, 0, 280, 281, 0, 269, 277, 306, 307,
+ 0, 354, 0, 0, 356, 0, 349, 350, 0, 338,
+ 362, 0, 322, 323, 324, 325, 0, 318, 319, 320,
+ 321, 346, 347, 0, 0, 0, 0, 0, 310, 311,
+ 312, 266, 264, 226, 234, 230, 246, 222, 267, 0,
+ 173, 238, 242, 215, 204, 0, 0, 223, 0, 0,
+ 0, 0, 216, 0, 0, 0, 0, 0, 208, 206,
+ 209, 207, 205, 218, 217, 219, 0, 231, 0, 227,
+ 0, 265, 173, 0, 247, 262, 263, 0, 262, 0,
+ 0, 314, 0, 0, 0, 316, 0, 235, 0, 0,
+ 239, 0, 0, 243, 303, 0, 295, 304, 298, 0,
+ 302, 0, 262, 296, 0, 262, 0, 0, 315, 0,
+ 0, 0, 317, 0, 0, 0, 309, 0, 308, 88,
+ 115, 366, 0, 0, 120, 284, 287, 0, 121, 291,
+ 124, 151, 126, 127, 91, 132, 133, 85, 134, 290,
+ 137, 89, 92, 262, 86, 94, 140, 87, 142, 90,
+ 144, 145, 292, 147, 148, 153, 0, 117, 116, 119,
+ 103, 118, 102, 0, 112, 285, 283, 0, 0, 0,
+ 356, 0, 113, 161, 162, 167, 0, 160, 0, 326,
+ 327, 0, 354, 0, 0, 356, 0, 114, 0, 0,
+ 0, 329, 334, 332, 335, 0, 0, 333, 334, 0,
+ 330, 0, 331, 286, 337, 0, 286, 336, 0, 339,
+ 340, 0, 286, 341, 342, 0, 0, 343, 0, 0,
+ 0, 344, 345, 179, 178, 0, 0, 0, 313, 0,
+ 0, 0, 328, 300, 293, 0, 301, 297, 0, 299,
+ 288, 0, 289, 294, 0, 0, 356, 0, 351, 106,
+ 0, 0, 110, 97, 0, 99, 108, 0, 100, 109,
+ 111, 101, 107, 98, 0, 104, 183, 181, 185, 182,
+ 180, 184, 359, 6, 360, 4, 2, 75, 105, 0,
+ 0, 0, 81, 83, 82, 37, 5, 0, 76, 0,
+ 51, 50, 49, 0, 0, 51, 0, 0, 0, 52,
+ 0, 67, 68, 0, 65, 0, 66, 41, 42, 43,
+ 44, 46, 47, 71, 45, 0, 0, 0, 78, 0,
+ 77, 79, 0, 51, 0, 0, 0, 0, 0, 61,
+ 0, 62, 0, 0, 32, 0, 0, 72, 33, 0,
+ 36, 34, 30, 0, 35, 31, 0, 63, 0, 64,
+ 161, 0, 69, 73, 0, 0, 0, 0, 161, 286,
+ 0, 70, 88, 121, 291, 124, 151, 126, 127, 91,
+ 132, 133, 134, 290, 137, 89, 92, 262, 94, 140,
+ 87, 142, 90, 144, 145, 292, 147, 148, 153, 74,
+ 0, 59, 53, 60, 54, 0, 0, 0, 0, 56,
+ 0, 57, 58, 55, 0, 0, 0, 0, 48, 0,
+ 38, 39, 0, 40, 8, 0, 0, 9, 0, 11,
+ 0, 10, 0, 1, 27, 15, 14, 26, 13, 12,
+ 29, 7, 0, 18, 0, 19, 0, 24, 25, 0,
+ 20, 21, 0, 22, 23, 16, 17, 367
+};
const short QQmlJSGrammar::goto_default [] = {
- 7, 650, 211, 198, 209, 521, 509, 645, 658, 508,
- 644, 648, 646, 654, 22, 651, 649, 647, 18, 520,
- 571, 561, 568, 563, 548, 193, 197, 199, 204, 234,
- 212, 231, 552, 622, 621, 203, 233, 26, 487, 486,
- 359, 358, 9, 357, 360, 202, 480, 361, 109, 17,
- 147, 24, 13, 146, 19, 25, 59, 23, 8, 28,
- 27, 280, 15, 274, 10, 270, 12, 272, 11, 271,
- 20, 278, 21, 279, 14, 273, 269, 310, 414, 275,
- 276, 205, 195, 194, 208, 207, 230, 196, 364, 363,
- 232, 471, 470, 332, 333, 473, 335, 472, 334, 427,
- 431, 434, 430, 429, 449, 450, 200, 186, 201, 210,
- 0};
+ 7, 663, 213, 200, 211, 526, 513, 658, 671, 512,
+ 657, 661, 659, 667, 22, 664, 662, 660, 18, 525,
+ 583, 573, 580, 575, 553, 195, 199, 201, 206, 237,
+ 214, 234, 564, 635, 634, 205, 236, 557, 26, 491,
+ 490, 362, 361, 9, 360, 363, 204, 484, 364, 109,
+ 17, 149, 24, 13, 148, 19, 25, 59, 23, 8,
+ 28, 27, 283, 15, 277, 10, 273, 12, 275, 11,
+ 274, 20, 281, 21, 282, 14, 276, 272, 313, 418,
+ 278, 279, 207, 197, 196, 210, 209, 233, 198, 367,
+ 366, 235, 475, 474, 335, 336, 477, 338, 476, 337,
+ 431, 435, 438, 434, 433, 453, 454, 202, 188, 203,
+ 212, 0
+};
const short QQmlJSGrammar::action_index [] = {
- 246, 1285, 2768, 2768, 2666, 998, 98, 198, 86, -106,
- 26, -15, -39, 234, -106, 314, 54, -106, -106, 714,
- 89, 151, 212, 219, -106, -106, -106, 412, 279, 1285,
- -106, -106, -106, 525, -106, -106, 2360, 1675, 1285, 1285,
- 1285, -106, 902, 1285, -106, -106, -106, 1285, 1285, -106,
- -106, -106, -106, -106, -106, 1285, -106, 1285, 1285, -106,
- 1285, 1285, 103, 197, -106, -106, 1285, 1285, 1285, -106,
- -106, -106, 214, 1285, 297, 1285, 1285, 1285, 1285, 392,
- 1285, 1285, 1285, 1285, 1285, 1285, 213, 1285, 1285, 1285,
- 96, 100, 101, 279, 279, 195, 190, 181, 402, 372,
- 382, 1285, -10, 1285, 106, 2258, 1285, 1285, -106, -106,
- -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
- -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
- -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
- -106, -106, 136, 1285, -106, -106, 65, 29, -106, 1285,
- -106, -106, 1285, -106, -106, -106, -106, -106, -106, -106,
- -106, -106, -106, -106, -106, -106, 1285, -46, 1285, 1285,
- 30, 27, 1285, -106, 2258, 1285, 1285, -106, 130, -106,
- -31, -106, -106, -16, 520, 520, 71, 21, -106, 421,
- -106, 38, 2768, -106, -106, -106, -106, -106, 237, -106,
- 520, -106, -52, -106, -106, -106, 23, -106, -106, -106,
- 2768, -106, -106, 596, -106, 588, 141, 2666, 2, 1,
- -1, 2972, 1285, -106, 13, 1285, 28, -106, -28, -30,
- -106, -106, 435, -106, -106, -106, -106, 60, 520, 52,
- 67, 2768, 64, -106, -106, 2666, -106, -106, 126, -106,
- -106, -106, -106, 73, -106, -106, -106, -106, -106, -106,
- -18, 34, 1285, 156, 168, -106, -106, -106, 1479, -106,
- 79, 40, 48, -106, 312, 75, 42, 672, 80, 143,
- 331, 279, 442, 1285, 316, 1285, 1285, 1285, 1285, 341,
- 1285, 1285, 1285, 1285, 1285, 279, 360, 360, 196, 225,
- 443, 357, 351, 1285, -4, 1285, 63, 1285, -106, 714,
- 1285, -106, 1285, 102, 68, 1285, 62, 2666, -106, 1285,
- 147, 2666, -106, 1285, 56, 1285, 1285, 91, 87, 1285,
- -106, 81, 149, 74, -106, -106, 1285, -106, 439, 1285,
- -106, -44, 1285, -42, 2666, -106, 1285, 153, 2666, -106,
- 1285, 154, 2666, 10, 2666, -106, 0, -106, 15, -54,
- 92, -106, -106, 2666, -50, 539, -7, 536, 121, 1285,
- 2666, 5, -8, 445, 2462, 24, 902, 51, 50, 1384,
- 2462, 47, 20, 46, 1285, 44, 19, 1285, 41, 1285,
- 3, -5, 2564, -106, -106, -106, -106, -106, -106, 1285,
- -106, -106, -106, 6, -17, 11, 2768, -9, -106, 249,
- -106, 1285, -13, -106, 105, -106, -106, -12, 520, -41,
- -20, 2768, -45, -106, 1285, 115, 12, -106, 36, -106,
- 31, 122, 1285, -106, 58, 4, -106, -51, -106, 2666,
- -106, 146, 2666, -106, 235, -106, -106, 140, 2666, 93,
- -106, 84, 76, -106, 520, 17, 33, -106, -106, -106,
- -106, 1285, 134, 2666, -106, 1285, 125, 2666, -106, 55,
- -106, 163, -106, -106, 1285, -106, -106, 520, -106, -106,
- 7, 45, 2768, 32, -106, -106, 120, 1773, -106, -106,
- 1577, -106, -106, 1871, -106, -106, -106, -106, -106, -106,
- 113, -106, -106, -106, -106, -106, -106, -106, -106, -106,
- 2768, -106, -106, -106, 109, 35, 808, 206, 49, 61,
- -106, -106, 229, -106, 203, 37, -106, -106, 611, 183,
- -106, 124, 39, 389, -106, 97, -106, -106, 252, -106,
- 2061, -106, -106, -106, -106, -106, -106, -106, -106, -106,
- 269, -23, 611, 243, 180, 424, 232, -106, 16, -106,
- 808, 162, -106, 22, 808, -106, -106, 1190, -106, -106,
- -106, 1094, -106, -106, 248, -106, 2061, -106, 305, -24,
- -106, -106, 215, 457, 18, 2156, 292, 2870, -11, -106,
- 14, 599, 9, 528, 119, 1285, 2666, 8, 70, 514,
- 72, 902, 95, 90, 1384, 85, 59, 77, 1285, 110,
- 83, 1285, 104, 1285, 82, 78, -106, 205, -106, 236,
- -106, 57, 25, 611, 167, 517, -106, 107, -106, -106,
- -106, 1966, 808, 1675, 43, -106, 155, -106, -106, 53,
- -106, -106, 808, 808, 108, 808, -106, 289, -106, 117,
- -106, -106, 150, 157, -106, -106, -106, -106, -106, 364,
- -106, 226, -106, 69, -106, -106, 432, -106, -106, 88,
- -106, -106, -106, -106, -106,
+ 301, 1388, 2901, 2901, 2797, 1095, 106, 97, 99, -108,
+ 92, 88, 85, 364, -108, 338, 96, -108, -108, 805,
+ 100, 161, 281, 247, -108, -108, -108, 394, 274, 1388,
+ -108, -108, -108, 516, -108, -108, 2589, 1786, 1388, 1388,
+ 1388, -108, 997, 1388, -108, -108, -108, 1388, 1388, -108,
+ -108, -108, -108, -108, -108, 1388, -108, 1388, 1388, -108,
+ 1388, 1388, 116, 235, -108, -108, 1388, 1388, 1388, -108,
+ -108, -108, 220, 1388, 326, 1388, 1388, 1388, 1388, 384,
+ 1388, 1388, 1388, 1388, 1388, 1388, 193, 1388, 1388, 1388,
+ 115, 103, 102, 211, 227, 231, 257, 230, 424, 414,
+ 404, 1388, 85, 1388, 78, 2381, 1388, 1388, -108, -108,
+ -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+ -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+ -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+ -108, -108, -108, -108, 157, 1388, -108, -108, 68, 61,
+ -108, 1388, -108, -108, 1388, -108, -108, -108, -108, -108,
+ -108, -108, -108, -108, -108, -108, -108, -108, 1388, 59,
+ 1388, 1388, 71, 60, 1388, -108, 2381, 1388, 1388, -108,
+ 271, -108, 54, -108, -108, 53, 428, 434, 58, 51,
+ -108, 437, -108, 50, 2901, -108, -108, -108, -108, -108,
+ 232, -108, 528, -108, 48, -108, -108, -108, 55, -108,
+ -108, -108, 2901, -108, -108, 634, -108, 637, 101, 2797,
+ 56, 90, 89, 3109, -108, 1388, -108, 86, 1388, 77,
+ -108, 84, 82, -108, -108, 425, -108, -108, -108, -108,
+ 81, 346, 75, 66, 2901, 74, -108, -108, 2797, -108,
+ -108, 121, -108, -108, -108, -108, 117, -108, -108, -108,
+ -108, -108, -108, 63, 69, 1388, 108, 160, -108, -108,
+ -108, 1586, -108, 80, 67, 72, -108, 324, 76, 73,
+ 711, 83, 122, 449, 308, 411, 1388, 331, 1388, 1388,
+ 1388, 1388, 449, 1388, 1388, 1388, 1388, 1388, 303, 299,
+ 298, 284, 280, 449, 357, 449, 1388, -20, 1388, 57,
+ 1388, -108, 805, 1388, -108, 1388, 70, 62, 1388, 64,
+ 2797, -108, 1388, 204, 2797, -108, 1388, 65, 1388, 1388,
+ 104, 105, 1388, -108, 91, 136, 171, -108, -108, 1388,
+ -108, 528, 1388, -108, -6, 1388, 87, 2797, -108, 1388,
+ 129, 2797, -108, 1388, 125, 2797, 93, 2797, -108, 79,
+ -108, 22, -36, 20, -108, -108, 2797, -34, 581, 15,
+ 594, 113, 1388, 2797, 16, -12, 508, 2485, -11, 11,
+ 997, 21, 24, 1489, 2485, 25, -2, 3, 1388, 94,
+ -32, 1388, -4, 1388, -30, -29, 2693, -108, -108, -108,
+ -108, -108, -108, 1388, -108, -108, -108, -19, -9, 37,
+ 2901, -1, -108, 285, -108, 1388, 5, -108, 134, -108,
+ -108, 39, 421, 40, 44, 2901, 41, -108, 1388, 141,
+ 47, -108, 52, -108, 36, 206, 1388, -108, 30, 29,
+ -108, -16, -108, 2797, -108, 123, 2797, -108, 270, -108,
+ -108, 132, 2797, 18, -108, 27, 28, -108, 528, -10,
+ 31, -108, -108, -108, -108, 1388, 133, 2797, -108, 1388,
+ 124, 2797, -108, 9, -108, 209, -108, -108, 1388, -108,
+ -108, 445, -108, -108, 0, -17, 2901, -51, -108, -108,
+ 111, 1986, -108, -108, 1686, -108, -108, 1886, -108, -108,
+ -108, -108, -108, -108, 120, -108, -108, -108, -108, -108,
+ -108, -108, -108, -108, 2901, -108, -108, -108, 112, -22,
+ 23, 901, 216, -26, 13, -108, -108, 218, -108, 210,
+ 45, -108, -108, 621, 201, -108, 162, 43, 401, -108,
+ 144, -108, -108, 219, -108, 2277, -108, -108, -108, -108,
+ -108, -108, -108, -108, -108, -31, 17, 186, -108, 19,
+ -108, -108, 208, 34, 621, 200, 166, 528, 228, -108,
+ -5, -108, 901, 190, -108, -13, 794, -108, -108, 1291,
+ -108, -108, -108, 1193, -108, -108, 212, -108, 2277, -108,
+ 352, -13, -108, -108, 185, 521, 26, 2083, 319, 3005,
+ 4, -108, 1, 571, 2, 700, 146, 1388, 2797, -7,
+ -25, 511, -24, 6, 997, 7, 8, 1489, 46, 38,
+ 49, 1388, 94, 12, 1388, 42, 1388, 32, 33, -108,
+ 277, -108, 273, -108, -3, 35, 524, 233, 621, -108,
+ 98, -108, -108, -108, 2180, 901, 1786, 14, -108, 153,
+ -108, -108, 10, -108, -108, 901, 901, 110, 901, -108,
+ 300, -108, 95, -108, -108, 176, 158, -108, -108, -108,
+ -108, -108, 528, -108, 172, -108, 109, -108, -108, 528,
+ -108, -108, 126, -108, -108, -108, -108, -108,
- -111, 8, 65, 83, 84, 317, 1, -111, -111, -111,
- -111, -111, -111, -111, -111, -111, -111, -111, -111, -77,
- -111, -111, -111, -111, -111, -111, -111, -111, -111, 96,
- -111, -111, -111, 2, -111, -111, -5, -28, 12, 106,
- 95, -111, 61, 55, -111, -111, -111, 63, 70, -111,
- -111, -111, -111, -111, -111, 54, -111, 172, 177, -111,
- 180, 191, -111, -111, -111, -111, 197, 202, 203, -111,
- -111, -111, -111, 210, -111, 209, 195, 109, 116, -111,
- 146, 125, 126, 127, 135, 138, -111, 141, 144, 110,
- -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
- -111, 150, -111, 155, -111, 192, 4, -33, -111, -111,
- -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
- -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
- -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
- -111, -111, -111, -9, -111, -111, -111, -111, -111, 7,
- -111, -111, 40, -111, -111, -111, -111, -111, -111, -111,
- -111, -111, -111, -111, -111, -111, 99, -111, 52, 31,
- -111, -111, 30, -111, 253, 44, 87, -111, -111, -111,
- -111, -111, -111, -111, 45, 86, -111, -111, -111, 41,
- -111, -111, 5, -111, -111, -111, -111, -111, -111, -111,
- 50, -111, -111, -111, -111, -111, -111, -111, -111, -111,
- 154, -111, -111, 26, -111, 49, -111, 330, -111, 28,
- -111, 248, 27, -111, -111, 124, 51, -111, -111, -111,
- -111, -111, 46, -111, -111, -111, -111, -111, 196, -111,
- -111, 185, -111, -111, -111, 194, -111, -111, -111, -111,
- -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
- -111, -111, 15, -111, -111, -111, -111, -111, 74, -111,
- -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
- -111, -111, -16, 230, -111, 233, 269, 251, 265, -111,
- 80, 81, 82, 88, 89, -111, -111, -111, -111, -111,
- -111, -111, -111, 216, -111, 255, -111, 259, -111, -111,
- 223, -111, 68, -111, -111, 217, -111, 236, -111, 24,
- -111, 244, -111, 227, -111, 226, 257, -111, -111, 263,
- -111, -111, -111, -111, -111, -111, 249, -111, 113, 163,
- -111, -111, 212, -111, 173, -111, 48, -111, 211, -111,
- 53, -111, 206, -111, 204, -111, -111, -111, -111, -111,
- -111, -111, -111, 199, -111, 23, -111, 25, -111, 134,
- 175, -111, -111, 37, 200, -111, 222, -111, -111, 57,
- 56, -111, -111, -111, 124, -111, 32, 43, -111, 105,
- -111, -111, 139, -111, -111, -111, -111, -111, -111, 38,
- -111, -111, -111, -111, -111, -111, 75, -111, -111, -111,
- -111, 71, -111, -111, -111, -111, -111, -111, 72, -111,
- -111, 85, -111, -111, 59, -111, -111, -111, -111, -111,
- -37, -111, 62, -111, -58, -111, -111, -111, -111, 286,
- -111, -111, 250, -111, -111, -111, -111, -111, 153, -57,
- -111, -111, 33, -111, 34, -111, 36, -111, -111, -111,
- -111, 47, -111, 77, -111, 29, -111, 67, -111, -111,
- -111, -111, -111, -111, 42, -111, -111, 214, -111, -111,
- -111, -111, 229, -111, -111, -111, -111, 35, -111, -111,
- 145, -111, -111, 3, -111, -111, -111, -111, -111, -111,
- -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
- 207, -111, -111, -111, -111, -111, 39, -111, -111, -111,
- -111, -111, -111, -111, -24, -111, -111, -111, -12, -27,
- -111, -111, -111, -14, -111, -111, -111, -111, -111, -111,
- 333, -111, -111, -111, -111, -111, -111, -111, -111, -111,
- -111, -111, 6, 22, -111, 20, -111, -111, -111, -111,
- 159, -111, -111, -111, 246, -111, -111, 332, -111, -111,
- -111, 436, -111, -111, -111, -111, 388, -111, -111, 18,
- -111, -111, -6, 19, -111, 352, -111, 225, 14, -111,
- -111, 13, -111, 11, -111, 167, 136, -111, -111, 10,
- -111, 64, -111, -111, 9, -111, -111, -111, 124, -111,
- 0, 69, -111, 60, -111, -111, -111, -111, -111, -10,
- -111, -111, -111, -1, -11, -2, -111, -111, -111, -111,
- -111, 370, 142, 315, -3, -111, -111, -111, -111, 17,
- -111, -111, -13, 21, 133, 221, -111, -111, -111, -111,
- -111, -111, -111, -111, -111, -111, -111, -111, -111, 16,
- -111, -111, -111, -111, -111, -111, -15, -111, -111, -111,
- -111, -111, -111, -111, -111};
+ -112, -3, 65, 88, 78, 292, -4, -112, -112, -112,
+ -112, -112, -112, -112, -112, -112, -112, -112, -112, -70,
+ -112, -112, -112, -112, -112, -112, -112, -112, -112, 70,
+ -112, -112, -112, 10, -112, -112, 2, -24, 15, 96,
+ 99, -112, 130, 103, -112, -112, -112, 48, 62, -112,
+ -112, -112, -112, -112, -112, 57, -112, 82, 203, -112,
+ 187, 181, -112, -112, -112, -112, 169, 177, 178, -112,
+ -112, -112, -112, 189, -112, 196, 198, 206, 161, -112,
+ 107, 113, 135, 116, 117, 119, -112, 125, 128, 133,
+ -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+ -112, 139, -112, 145, -112, 180, 8, -42, -112, -112,
+ -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+ -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+ -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+ -112, -112, -112, -112, -112, 5, -112, -112, -112, -112,
+ -112, 31, -112, -112, 32, -112, -112, -112, -112, -112,
+ -112, -112, -112, -112, -112, -112, -112, -112, 86, -112,
+ 77, 17, -112, -112, 28, -112, 273, 37, 79, -112,
+ -112, -112, -112, -112, -112, -112, 61, 95, -112, -112,
+ -112, 46, -112, -112, 58, -112, -112, -112, -112, -112,
+ -112, -112, 45, -112, -112, -112, -112, -112, -112, -112,
+ -112, -112, 131, -112, -112, 29, -112, 33, -112, 84,
+ -112, 39, -112, 223, -112, 42, -112, -112, 35, 16,
+ -112, -112, -112, -112, -112, 49, -112, -112, -112, -112,
+ -112, 184, -112, -112, 194, -112, -112, -112, 199, -112,
+ -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+ -112, -112, -112, -112, -112, 19, -112, -112, -112, -112,
+ -112, 76, -112, -112, -112, -112, -112, -112, -112, -112,
+ -112, -112, -112, -112, -112, -11, 214, -112, 215, 221,
+ 224, 225, -112, 92, 90, 83, 74, 73, -112, -112,
+ -112, -112, -112, -112, -112, -112, 237, -112, 234, -112,
+ 243, -112, -112, 254, -112, 67, -112, -112, 85, -112,
+ 167, -112, 26, -112, 219, -112, 247, -112, 244, 241,
+ -112, -112, 233, -112, -112, -112, -112, -112, -112, 213,
+ -112, 108, 183, -112, -112, 193, -112, 202, -112, 106,
+ -112, 209, -112, 55, -112, 317, -112, 205, -112, -112,
+ -112, -112, -112, -112, -112, -112, 191, -112, 59, -112,
+ 60, -112, 134, 179, -112, -112, 44, 160, -112, -112,
+ 156, -112, -112, 41, 211, -112, -112, -112, 50, -112,
+ 36, 192, -112, 63, -112, -112, 72, -112, -112, -112,
+ -112, -112, -112, 23, -112, -112, -112, -112, -112, -112,
+ 75, -112, -112, -112, -112, 114, -112, -112, -112, -112,
+ -112, -112, 64, -112, -112, 69, -112, -112, 52, -112,
+ -112, -112, -112, -112, -50, -112, 56, -112, -45, -112,
+ -112, -112, -112, 293, -112, -112, 264, -112, -112, -112,
+ -112, -112, 89, -64, -112, -112, 24, -112, 25, -112,
+ 27, -112, -112, -112, -112, 34, -112, 122, -112, 47,
+ -112, 66, -112, -112, -112, -112, -112, -112, 38, -112,
+ -112, 220, -112, -112, -112, -112, 197, -112, -112, -112,
+ -112, 30, -112, -112, 120, -112, -112, 3, -112, -112,
+ -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+ -112, -112, -112, -112, 195, -112, -112, -112, -112, -112,
+ -112, 51, -112, -112, -112, -112, -112, -112, -112, 40,
+ -112, -112, -112, -15, -28, -112, -112, -112, -12, -112,
+ -112, -112, -112, -112, -112, 314, -112, -112, -112, -112,
+ -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+ -112, -112, -112, -112, 7, 0, -112, 21, -112, -112,
+ -112, -112, 147, -112, -112, -112, 236, -112, -112, 324,
+ -112, -112, -112, 424, -112, -112, -112, -112, 360, -112,
+ -112, 13, -112, -112, -1, 12, -112, 338, -112, 212,
+ 4, -112, -112, 9, -112, -6, -112, 208, 246, -112,
+ -112, 6, -112, -112, 71, -112, -112, 18, -112, -112,
+ -112, 14, -112, -10, 53, -112, 43, -112, -112, -112,
+ -112, -112, -30, -112, -112, -112, -5, -18, -2, -112,
+ -112, -112, -112, -112, 378, 81, 311, 1, -112, -112,
+ -112, -112, 11, -112, -112, 20, 22, 207, 80, -112,
+ -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+ -112, -112, -8, -112, -112, -112, -112, -112, -112, -9,
+ -112, -112, -112, -112, -112, -112, -112, -112
+};
const short QQmlJSGrammar::action_info [] = {
- -145, 398, 101, 244, 438, 402, 465, 245, 461, 567,
- 423, 439, -126, 421, 553, -126, -145, 342, 344, 420,
- 185, 245, 567, 392, 418, 585, 354, 73, 268, 181,
- 245, 465, 166, 101, 172, 350, 432, 184, 268, 461,
- 103, 432, 404, 405, 406, 428, 408, 413, -142, 424,
- 560, -139, 448, -137, -115, 567, 424, -116, -134, 261,
- 350, 448, 143, 432, 283, 624, 448, 481, 534, 103,
- 262, 192, 474, 149, 529, 305, 567, 456, 482, 189,
- 283, 191, 323, 307, -137, 627, 567, 484, 303, 151,
- 617, 166, -115, 323, 329, 424, 238, -116, 336, 399,
- 241, 524, -134, 312, 303, 346, 268, 73, 350, 448,
- 143, -142, 240, 452, 465, 582, 448, -139, 461, 243,
- 454, 143, 317, 143, 174, 0, 60, 305, 490, 315,
- 665, 664, 435, 143, 257, 256, 60, 61, 143, 532,
- 60, 60, 143, 175, 143, 64, 451, 61, 533, 671,
- 670, 61, 61, 442, 143, 143, 65, 338, 537, 536,
- 452, 143, 143, 564, 143, 174, 416, 415, 629, 628,
- 564, 477, 174, 501, 0, 426, 491, 436, 673, 672,
- 259, 258, 259, 258, 175, 467, 179, 252, 251, 642,
- 643, 175, 144, 325, 463, 532, 530, 326, 674, 642,
- 643, 168, 259, 258, 555, 169, 87, 321, 88, 66,
- 339, 637, 530, 348, 352, 87, 264, 88, 565, 89,
- 87, 87, 88, 88, 478, 476, 66, 174, 89, 267,
- 265, 66, 525, 89, 89, 551, 631, 0, 87, 558,
- 88, 619, 527, 143, 530, 143, 175, 0, 176, 105,
- 87, 89, 88, 526, 67, 576, 0, 266, 527, 540,
- 68, 0, 567, 89, 174, 530, 620, 618, 106, 526,
- 107, 67, 530, 0, 0, 0, 67, 68, 527, 0,
- 0, 527, 68, 175, 174, 411, 0, 668, 667, 526,
- 527, 0, 526, 559, 557, 0, 446, 445, 236, 235,
- 0, 526, 0, 175, 87, 411, 88, 174, 0, 577,
- 575, 527, 0, 541, 539, 75, 76, 89, 527, 666,
- 174, 0, 526, 632, 0, -102, 175, 0, 176, 526,
- 285, 286, 75, 76, 285, 286, 661, 0, -102, 175,
- 0, 176, 77, 78, 6, 5, 4, 1, 3, 2,
- 662, 660, 0, 0, 290, 291, 0, 287, 288, 77,
- 78, 287, 288, 292, 290, 291, 293, 0, 294, 0,
- 0, 0, 0, 292, 290, 291, 293, 0, 294, 0,
- 290, 291, 659, 292, 0, 87, 293, 88, 294, 292,
- 0, 0, 293, 35, 294, 80, 81, 0, 89, 0,
- 0, 0, 0, 82, 83, 80, 81, 84, 0, 85,
- 0, 0, 0, 82, 83, 80, 81, 84, 35, 85,
- 0, 0, 0, 82, 83, 80, 81, 84, 0, 85,
- 49, 52, 50, 82, 83, 80, 81, 84, 0, 85,
- 0, 0, 0, 82, 83, 0, 0, 84, 0, 85,
- 35, 0, 0, 35, 0, 49, 52, 50, 46, 34,
- 51, 35, 0, 0, 35, 0, 290, 291, 35, 0,
- 0, 35, 532, 0, 35, 292, 0, 0, 293, 0,
- 294, 184, 0, 46, 34, 51, 35, 49, 52, 50,
- 49, 52, 50, 0, 0, 0, 0, 0, 49, 52,
- 50, 49, 52, 50, 0, 49, 52, 50, 49, 52,
- 50, 49, 52, 50, 0, 46, 34, 51, 46, 34,
- 51, 0, 0, 49, 52, 50, 46, 34, 51, 46,
- 34, 51, 532, 46, 34, 51, 46, 34, 51, 46,
- 34, 51, 0, 35, 0, 0, 35, 0, 0, 35,
- 184, 46, 34, 51, 35, 0, 0, 35, 0, 0,
- 0, 184, 0, 0, 0, 35, 0, 0, 35, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 49, 52, 50, 49, 52, 50, 49, 52, 50, 255,
- 254, 49, 52, 50, 49, 52, 50, 255, 254, 0,
- 250, 249, 49, 52, 50, 49, 52, 50, 46, 34,
- 51, 46, 34, 51, 46, 34, 51, 35, 0, 46,
- 34, 51, 46, 34, 51, 35, 532, 0, 35, 0,
- 46, 34, 51, 46, 34, 51, 0, 0, 0, 0,
- 35, 0, 0, 0, 0, 0, 0, 0, 0, 255,
- 254, 0, 0, 0, 49, 52, 50, 250, 249, 0,
- 250, 249, 49, 52, 50, 49, 52, 50, 0, 0,
- 0, 0, 0, 0, 0, 153, 0, 49, 52, 50,
- 0, 0, 46, 34, 51, 154, 0, 0, 0, 155,
- 46, 34, 51, 46, 34, 51, 0, 0, 156, 0,
- 157, 0, 0, 319, 0, 46, 34, 51, 0, 0,
- 0, 158, 0, 159, 64, 0, 0, 153, 0, 0,
- 0, 160, 0, 0, 161, 65, 0, 154, 0, 0,
- 162, 155, 0, 0, 0, 0, 163, 0, 0, 0,
- 156, 0, 157, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 164, 158, 0, 159, 64, 0, 0, 0,
- 0, 0, 0, 160, 0, 0, 161, 65, 0, 0,
- 0, 0, 162, 0, 0, 0, 0, 0, 163, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 164, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 30, 31, 0, 0, 0, 0, 0, 0, 0, 0,
- 33, 0, 0, 0, 0, 0, 0, 35, 0, 0,
- 0, 36, 37, 0, 38, 0, 0, 0, 0, 0,
- 0, 516, 0, 0, 0, 45, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 53, 49, 52, 50, 0, 54, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 44,
- 56, 32, 0, 0, 0, 41, 0, 0, 0, 0,
- 0, 0, 46, 34, 51, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 30, 31, 0, 0, 0, 0,
- 0, 0, 0, 0, 33, 0, 0, 0, 0, 0,
- 0, 35, 0, 0, 0, 36, 37, 0, 38, 0,
- 0, 0, 0, 0, 0, 42, 0, 0, 0, 45,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 53, 49, 52,
- 50, 0, 54, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 44, 56, 32, 0, 0, 0, 41,
- 0, 0, 0, 0, 0, 0, 46, 34, 51, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 515, 0,
- 30, 31, 0, 0, 0, 0, 0, 0, 0, 0,
- 219, 0, 0, 0, 0, 0, 0, 35, 0, 0,
- 0, 36, 37, 0, 38, 0, 0, 0, 0, 0,
- 0, 516, 0, 0, 0, 45, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 53, 517, 519, 518, 0, 54, 0,
- 0, 0, 0, 227, 0, 0, 0, 0, 0, 44,
- 56, 32, 214, 0, 0, 41, 0, 0, 0, 0,
- 0, 0, 46, 34, 51, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 515, 0, 30, 31, 0, 0,
- 0, 0, 0, 0, 0, 0, 219, 0, 0, 0,
- 0, 0, 0, 35, 0, 0, 0, 36, 37, 0,
- 38, 0, 0, 0, 0, 0, 0, 516, 0, 0,
- 0, 45, 0, 0, 0, 0, 0, 0, 0, 572,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 53,
- 517, 519, 518, 0, 54, 0, 0, 0, 0, 227,
- 0, 0, 0, 0, 0, 44, 56, 32, 214, 0,
- 0, 41, 0, 0, 0, 0, 0, 0, 46, 34,
- 51, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 515, 0, 30, 31, 0, 0, 0, 0, 0, 0,
- 0, 0, 219, 0, 0, 0, 0, 0, 0, 35,
- 0, 0, 0, 36, 37, 0, 38, 0, 0, 0,
- 0, 0, 0, 516, 0, 0, 0, 45, 0, 0,
- 0, 0, 0, 0, 0, 569, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 53, 517, 519, 518, 0,
- 54, 0, 0, 0, 0, 227, 0, 0, 0, 0,
- 0, 44, 56, 32, 214, 0, 0, 41, 0, 0,
- 0, 0, 0, 0, 46, 34, 51, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 29, 30, 31, 0,
- 0, 0, 0, 0, 0, 0, 0, 33, 0, 0,
- 0, 0, 0, 0, 35, 0, 0, 0, 36, 37,
- 0, 38, 0, 0, 0, 39, 0, 40, 42, 43,
- 0, 0, 45, 0, 0, 0, 47, 0, 48, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 53, 49, 52, 50, 0, 54, 0, 55, 0, 57,
- 0, 58, 0, 0, 0, 0, 44, 56, 32, 0,
- 0, 0, 41, 0, 0, 0, 0, 0, 0, 46,
- 34, 51, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, -135, 0, 0, 0, 29, 30, 31, 0, 0,
- 0, 0, 0, 0, 0, 0, 33, 0, 0, 0,
- 0, 0, 0, 35, 0, 0, 0, 36, 37, 0,
- 38, 0, 0, 0, 39, 0, 40, 42, 43, 0,
- 0, 45, 0, 0, 0, 47, 0, 48, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 53,
- 49, 52, 50, 0, 54, 0, 55, 0, 57, 0,
- 58, 0, 0, 0, 0, 44, 56, 32, 0, 0,
- 0, 41, 0, 0, 0, 0, 0, 0, 46, 34,
- 51, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 29, 30, 31, 0, 0, 0, 0, 0, 0, 0,
- 0, 33, 0, 0, 0, 0, 0, 0, 35, 0,
- 0, 0, 36, 37, 0, 38, 0, 0, 0, 39,
- 0, 40, 42, 43, 0, 0, 45, 0, 0, 0,
- 47, 0, 48, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 53, 49, 52, 50, 0, 54,
- 0, 55, 0, 57, 282, 58, 0, 0, 0, 0,
- 44, 56, 32, 0, 0, 0, 41, 0, 0, 0,
- 0, 0, 0, 46, 34, 51, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 488, 0, 0, 29, 30,
- 31, 0, 0, 0, 0, 0, 0, 0, 0, 33,
- 0, 0, 0, 0, 0, 0, 35, 0, 0, 0,
- 36, 37, 0, 38, 0, 0, 0, 39, 0, 40,
- 42, 43, 0, 0, 45, 0, 0, 0, 47, 0,
- 48, 0, 0, 494, 0, 0, 0, 0, 0, 0,
- 0, 0, 53, 49, 52, 50, 0, 54, 0, 55,
- 0, 57, 0, 58, 0, 0, 0, 0, 44, 56,
- 32, 0, 0, 0, 41, 0, 0, 0, 0, 0,
- 0, 46, 34, 51, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 488, 0, 0, 29, 30, 31, 0,
- 0, 0, 0, 0, 0, 0, 0, 33, 0, 0,
- 0, 0, 0, 0, 35, 0, 0, 0, 36, 37,
- 0, 38, 0, 0, 0, 39, 0, 40, 42, 43,
- 0, 0, 45, 0, 0, 0, 47, 0, 48, 0,
- 0, 489, 0, 0, 0, 0, 0, 0, 0, 0,
- 53, 49, 52, 50, 0, 54, 0, 55, 0, 57,
- 0, 58, 0, 0, 0, 0, 44, 56, 32, 0,
- 0, 0, 41, 0, 0, 0, 0, 0, 0, 46,
- 34, 51, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 496, 0, 0, 29, 30, 31, 0, 0, 0,
- 0, 0, 0, 0, 0, 33, 0, 0, 0, 0,
- 0, 0, 35, 0, 0, 0, 36, 37, 0, 38,
- 0, 0, 0, 39, 0, 40, 42, 43, 0, 0,
- 45, 0, 0, 0, 47, 0, 48, 0, 0, 499,
- 0, 0, 0, 0, 0, 0, 0, 0, 53, 49,
- 52, 50, 0, 54, 0, 55, 0, 57, 0, 58,
- 0, 0, 0, 0, 44, 56, 32, 0, 0, 0,
- 41, 0, 0, 0, 0, 0, 0, 46, 34, 51,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 496,
- 0, 0, 29, 30, 31, 0, 0, 0, 0, 0,
- 0, 0, 0, 33, 0, 0, 0, 0, 0, 0,
- 35, 0, 0, 0, 36, 37, 0, 38, 0, 0,
- 0, 39, 0, 40, 42, 43, 0, 0, 45, 0,
- 0, 0, 47, 0, 48, 0, 0, 497, 0, 0,
- 0, 0, 0, 0, 0, 0, 53, 49, 52, 50,
- 0, 54, 0, 55, 0, 57, 0, 58, 0, 0,
- 0, 0, 44, 56, 32, 0, 0, 0, 41, 0,
- 0, 0, 0, 0, 0, 46, 34, 51, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 29, 30, 31,
- 0, 0, 0, 0, 0, 0, 0, 0, 33, 0,
- 0, 0, 0, 0, 0, 35, 220, 0, 0, 587,
- 633, 0, 38, 0, 0, 0, 39, 0, 40, 42,
- 43, 0, 0, 45, 0, 0, 0, 47, 0, 48,
- 0, 0, 0, 0, 0, 0, 0, 223, 0, 0,
- 0, 53, 49, 52, 50, 224, 54, 0, 55, 226,
- 57, 0, 58, 0, 229, 0, 0, 44, 56, 32,
- 0, 0, 0, 41, 0, 0, 0, 0, 0, 0,
- 46, 34, 51, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 29, 30, 31, 0, 0, 0, 0, 0,
- 0, 0, 0, 33, 0, 0, 0, 0, 0, 0,
- 35, 220, 0, 0, 221, 37, 0, 38, 0, 0,
- 0, 39, 0, 40, 42, 43, 0, 0, 45, 0,
- 0, 0, 47, 0, 48, 0, 0, 0, 0, 0,
- 0, 0, 223, 0, 0, 0, 53, 49, 52, 50,
- 224, 54, 0, 55, 226, 57, 0, 58, 0, 229,
- 0, 0, 44, 56, 32, 0, 0, 0, 41, 0,
- 0, 0, 0, 0, 0, 46, 34, 51, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 29, 30, 31,
- 0, 0, 0, 0, 0, 0, 0, 0, 33, 0,
- 0, 0, 0, 0, 0, 35, 220, 0, 0, 587,
- 37, 0, 38, 0, 0, 0, 39, 0, 40, 42,
- 43, 0, 0, 45, 0, 0, 0, 47, 0, 48,
- 0, 0, 0, 0, 0, 0, 0, 223, 0, 0,
- 0, 53, 49, 52, 50, 224, 54, 0, 55, 226,
- 57, 0, 58, 0, 229, 0, 0, 44, 56, 32,
- 0, 0, 0, 41, 0, 0, 0, 0, 0, 0,
- 46, 34, 51, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 111, 112, 113, 0, 0, 115, 117, 118,
- 0, 0, 119, 0, 120, 0, 0, 0, 122, 123,
- 124, 0, 0, 0, 0, 0, 0, 35, 125, 126,
- 127, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 128, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 131, 0, 0,
- 0, 0, 0, 0, 49, 52, 50, 132, 133, 134,
- 0, 136, 137, 138, 139, 140, 141, 0, 0, 129,
- 135, 121, 114, 116, 130, 0, 0, 0, 0, 0,
- 0, 0, 46, 34, 51, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 111, 112, 113, 0, 0, 115,
- 117, 118, 0, 0, 119, 0, 120, 0, 0, 0,
- 122, 123, 124, 0, 0, 0, 0, 0, 0, 35,
- 125, 126, 127, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 128, 0, 0, 0, 395, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 131,
- 0, 0, 0, 0, 0, 397, 49, 52, 50, 132,
- 133, 134, 0, 136, 137, 138, 139, 140, 141, 0,
- 0, 129, 135, 121, 114, 116, 130, 0, 0, 0,
- 0, 0, 0, 0, 46, 374, 380, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 111, 112, 113, 0,
- 0, 115, 117, 118, 0, 0, 119, 0, 120, 0,
- 0, 0, 122, 123, 124, 0, 0, 0, 0, 0,
- 0, 35, 125, 126, 127, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 128, 0, 0, 0, 395,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 131, 0, 0, 0, 0, 0, 397, 49, 52,
- 50, 132, 133, 134, 0, 136, 137, 138, 139, 140,
- 141, 0, 0, 129, 135, 121, 114, 116, 130, 0,
- 0, 0, 0, 0, 0, 0, 46, 34, 51, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 111, 112,
- 113, 0, 0, 115, 117, 118, 0, 0, 119, 0,
- 120, 0, 0, 0, 122, 123, 124, 0, 0, 0,
- 0, 0, 0, 35, 125, 126, 127, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 128, 0, 0,
- 0, 395, 0, 0, 0, 0, 0, 0, 0, 396,
- 0, 0, 0, 131, 0, 0, 0, 0, 0, 397,
- 49, 52, 50, 132, 133, 134, 0, 136, 137, 138,
- 139, 140, 141, 0, 0, 129, 135, 121, 114, 116,
- 130, 0, 0, 0, 0, 0, 0, 0, 46, 374,
- 380, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 213, 0, 0, 0, 0, 215, 0, 29, 30, 31,
- 217, 0, 0, 0, 0, 0, 0, 218, 33, 0,
- 0, 0, 0, 0, 0, 35, 220, 0, 0, 221,
- 37, 0, 38, 0, 0, 0, 39, 0, 40, 42,
- 43, 0, 0, 45, 0, 0, 0, 47, 0, 48,
- 0, 0, 0, 0, 0, 222, 0, 223, 0, 0,
- 0, 53, 49, 52, 50, 224, 54, 225, 55, 226,
- 57, 227, 58, 228, 229, 0, 0, 44, 56, 32,
- 214, 216, 0, 41, 0, 0, 0, 0, 0, 0,
- 46, 34, 51, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 213, 0, 0, 0, 0, 215, 0, 29,
- 30, 31, 217, 0, 0, 0, 0, 0, 0, 218,
- 219, 0, 0, 0, 0, 0, 0, 35, 220, 0,
- 0, 221, 37, 0, 38, 0, 0, 0, 39, 0,
- 40, 42, 43, 0, 0, 45, 0, 0, 0, 47,
- 0, 48, 0, 0, 0, 0, 0, 222, 0, 223,
- 0, 0, 0, 53, 49, 52, 50, 224, 54, 225,
- 55, 226, 57, 227, 58, 228, 229, 0, 0, 44,
- 56, 32, 214, 216, 0, 41, 0, 0, 0, 0,
- 0, 0, 46, 34, 51, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 591, 112, 113, 0, 0, 593,
- 117, 595, 30, 31, 596, 0, 120, 0, 0, 0,
- 122, 598, 599, 0, 0, 0, 0, 0, 0, 35,
- 600, 126, 127, 221, 37, 0, 38, 0, 0, 0,
- 39, 0, 40, 601, 43, 0, 0, 603, 0, 0,
- 0, 47, 0, 48, 0, 0, 0, 0, 0, 604,
- 0, 223, 0, 0, 0, 605, 49, 52, 50, 606,
- 607, 608, 55, 610, 611, 612, 613, 614, 615, 0,
- 0, 602, 609, 597, 592, 594, 130, 41, 0, 0,
- 0, 0, 0, 0, 46, 374, 380, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 365, 112, 113, 0,
- 0, 367, 117, 369, 30, 31, 370, 0, 120, 0,
- 0, 0, 122, 372, 373, 0, 0, 0, 0, 0,
- 0, 35, 375, 126, 127, 221, 37, 0, 38, 0,
- 0, 0, 39, 0, 40, 376, 43, 0, 0, 378,
- 0, 0, 0, 47, 0, 48, 0, -281, 0, 0,
- 0, 379, 0, 223, 0, 0, 0, 381, 49, 52,
- 50, 382, 383, 384, 55, 386, 387, 388, 389, 390,
- 391, 0, 0, 377, 385, 371, 366, 368, 130, 41,
- 0, 0, 0, 0, 0, 0, 46, 374, 380, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
+ -130, 452, 556, -146, 488, 637, 465, 469, 248, -149,
+ -141, 271, 353, -150, -138, -119, 486, 408, -150, 402,
+ 579, 406, -149, -130, 271, 353, 478, 403, -138, 572,
+ 396, -119, -118, 597, 428, 436, 443, 579, 456, 442,
+ 594, 436, 630, 579, 529, 452, 558, 579, 561, -146,
+ 460, 409, 555, -118, 412, 345, -141, 436, 286, 308,
+ 485, 452, 248, 458, 452, 417, 191, 174, 465, 469,
+ 410, 565, 539, 168, 428, 422, 151, 425, 145, 73,
+ 432, 286, 534, 194, 310, 326, 248, 0, 0, 187,
+ 0, 0, 271, 73, 0, 640, 427, 687, 0, 244,
+ 424, -143, 168, 247, 145, 265, 326, 101, 339, 357,
+ 452, 193, 332, 306, 183, 306, 145, 241, 469, 494,
+ 465, 153, 428, 318, 320, 353, 186, 176, 145, 246,
+ 446, 145, 145, 145, 315, 243, 101, 145, 455, 60,
+ 264, 145, 60, 60, 341, 0, 177, 347, 0, 145,
+ 61, 308, 456, 61, 61, 60, 686, 685, 64, 642,
+ 641, 576, 262, 261, 103, 145, 61, 495, 267, 65,
+ 678, 677, 328, 176, 262, 261, 329, 537, 260, 259,
+ 505, 537, 255, 254, 471, 355, 538, 684, 683, 351,
+ 567, 176, 177, 467, 559, 420, 419, 342, 576, 655,
+ 656, 430, 349, 655, 656, 542, 541, 262, 261, 650,
+ 177, 170, 145, 146, 535, 171, 439, 481, 87, 588,
+ 88, 270, 268, 176, 0, 644, 545, 0, 0, 535,
+ 535, 89, 66, 681, 680, 570, 87, 0, 88, 530,
+ 145, 560, 177, 0, 415, 563, 577, 66, 0, 89,
+ 269, 579, 87, 0, 88, 87, 87, 88, 88, 66,
+ 532, 440, 535, 0, 324, 89, 0, 679, 89, 89,
+ 482, 480, 531, 589, 587, 532, 532, 67, 145, 145,
+ 546, 544, 87, 68, 88, 532, 0, 531, 531, 571,
+ 569, 532, 67, 239, 238, 89, 176, 531, 68, 87,
+ 176, 88, 535, 531, 67, 87, 0, 88, 532, 87,
+ 68, 88, 89, 632, 645, 177, 0, 178, 89, 177,
+ 531, 415, 89, 87, 87, 88, 88, 181, 87, 0,
+ 88, 450, 449, 87, 176, 88, 89, 89, 633, 631,
+ 0, 89, 288, 289, 75, 76, 89, 674, 532, 288,
+ 289, 0, -105, 177, 0, 178, 75, 76, 0, 0,
+ 531, 675, 673, 0, 0, 0, 0, 176, 0, 290,
+ 291, 77, 78, 0, 0, 35, 290, 291, 0, 105,
+ 293, 294, 0, 77, 78, -105, 177, 0, 178, 295,
+ 0, 0, 296, 0, 297, 672, 0, 0, 106, 0,
+ 107, 6, 5, 4, 1, 3, 2, 80, 81, 0,
+ 0, 0, 49, 52, 50, 82, 83, 80, 81, 84,
+ 0, 85, 0, 0, 0, 82, 83, 80, 81, 84,
+ 35, 85, 0, 0, 0, 82, 83, 80, 81, 84,
+ 35, 85, 46, 34, 51, 82, 83, 80, 81, 84,
+ 35, 85, 0, 0, 35, 82, 83, 35, 0, 84,
+ 0, 85, 0, 35, 0, 0, 35, 49, 52, 50,
+ 0, 0, 293, 294, 35, 0, 0, 49, 52, 50,
+ 0, 295, 0, 0, 296, 0, 297, 49, 52, 50,
+ 0, 49, 52, 50, 49, 52, 50, 46, 34, 51,
+ 49, 52, 50, 49, 52, 50, 0, 46, 34, 51,
+ 0, 49, 52, 50, 0, 0, 0, 46, 34, 51,
+ 0, 46, 34, 51, 46, 34, 51, 0, 0, 0,
+ 46, 34, 51, 46, 34, 51, 537, 35, 0, 537,
+ 35, 46, 34, 51, 186, 35, 0, 186, 0, 0,
+ 35, 0, 186, 35, 0, 0, 0, 35, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 49, 52, 50, 49, 52, 50,
+ 0, 0, 49, 52, 50, 0, 0, 49, 52, 50,
+ 49, 52, 50, 0, 49, 52, 50, 0, 0, 0,
+ 35, 0, 0, 0, 46, 34, 51, 46, 34, 51,
+ 35, 0, 46, 34, 51, 0, 0, 46, 34, 51,
+ 46, 34, 51, 35, 46, 34, 51, 0, 0, 0,
+ 0, 0, 253, 252, 0, 0, 537, 49, 52, 50,
+ 0, 0, 253, 252, 0, 0, 0, 49, 52, 50,
+ 35, 0, 0, 0, 0, 258, 257, 0, 0, 0,
+ 49, 52, 50, 35, 0, 0, 35, 46, 34, 51,
+ 0, 0, 0, 0, 0, 0, 0, 46, 34, 51,
+ 0, 0, 0, 0, 0, 0, 0, 49, 52, 50,
+ 46, 34, 51, 0, 0, 253, 252, 0, 258, 257,
+ 49, 52, 50, 49, 52, 50, 0, 0, 0, 0,
+ 0, 0, 0, 0, 155, 0, 0, 46, 34, 51,
+ 0, 0, 0, 0, 156, 0, 0, 0, 157, 35,
+ 46, 34, 51, 46, 34, 51, 0, 158, 0, 159,
+ 0, 0, 322, 0, 0, 0, 0, 0, 0, 0,
+ 160, 0, 161, 64, 0, 0, 0, 0, 0, 0,
+ 162, 258, 257, 163, 65, 0, 49, 52, 50, 164,
+ 0, 0, 0, 0, 0, 165, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 166, 0, 0, 0, 0, 46, 34, 51, 0,
+ 0, 0, 0, 0, 0, 0, 30, 31, 155, 0,
+ 0, 0, 0, 0, 0, 0, 33, 0, 156, 0,
+ 0, 0, 157, 35, 0, 0, 0, 36, 37, 0,
+ 38, 158, 0, 159, 0, 0, 0, 521, 0, 0,
+ 0, 45, 0, 0, 160, 0, 161, 64, 0, 0,
+ 0, 0, 0, 0, 162, 0, 0, 163, 65, 53,
+ 49, 52, 50, 164, 54, 0, 0, 0, 0, 165,
+ 0, 0, 0, 0, 0, 44, 56, 32, 0, 0,
+ 0, 0, 41, 0, 0, 166, 0, 0, 0, 0,
+ 46, 34, 51, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 30, 31, 0, 0, 0, 0, 0,
+ 0, 0, 0, 33, 0, 0, 0, 0, 0, 0,
+ 35, 0, 0, 0, 36, 37, 0, 38, 0, 0,
+ 0, 0, 0, 0, 521, 0, 0, 0, 45, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 53, 49, 52, 50,
+ 0, 54, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 44, 56, 32, 0, 0, 0, 0, 41,
+ 0, 0, 0, 0, 0, 0, 0, 46, 34, 51,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 30,
+ 31, 0, 0, 0, 0, 0, 0, 0, 0, 33,
+ 0, 0, 0, 0, 0, 0, 35, 0, 0, 0,
+ 36, 37, 0, 38, 0, 0, 0, 0, 0, 0,
+ 42, 0, 0, 0, 45, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 53, 49, 52, 50, 0, 54, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 44, 56,
+ 32, 0, 0, 0, 0, 41, 0, 0, 0, 0,
+ 0, 0, 0, 46, 34, 51, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 519, 0, 30, 31, 0,
+ 0, 0, 0, 0, 0, 0, 0, 221, 0, 0,
+ 0, 0, 0, 0, 35, 0, 0, 0, 36, 37,
+ 0, 38, 0, 0, 0, 0, 0, 0, 521, 0,
+ 0, 0, 45, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 53, 522, 524, 523, 0, 54, 0, 0, 0, 0,
+ 230, 0, 0, 0, 0, 0, 44, 56, 32, 216,
+ 224, 0, 0, 41, 0, 0, 520, 0, 0, 0,
+ 0, 46, 34, 51, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 519, 0, 30, 31, 0, 0, 0,
+ 0, 0, 0, 0, 0, 221, 0, 0, 0, 0,
+ 0, 0, 35, 0, 0, 0, 36, 37, 0, 38,
+ 0, 0, 0, 0, 0, 0, 521, 0, 0, 0,
+ 45, 0, 0, 0, 0, 0, 0, 0, 584, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 53, 522,
+ 524, 523, 0, 54, 0, 0, 0, 0, 230, 0,
+ 0, 0, 0, 0, 44, 56, 32, 216, 224, 0,
+ 0, 41, 0, 0, 520, 0, 0, 0, 0, 46,
+ 34, 51, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 519, 0, 30, 31, 0, 0, 0, 0, 0,
+ 0, 0, 0, 221, 0, 0, 0, 0, 0, 0,
+ 35, 0, 0, 0, 36, 37, 0, 38, 0, 0,
+ 0, 0, 0, 0, 521, 0, 0, 0, 45, 0,
+ 0, 0, 0, 0, 0, 0, 581, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 53, 522, 524, 523,
+ 0, 54, 0, 0, 0, 0, 230, 0, 0, 0,
+ 0, 0, 44, 56, 32, 216, 224, 0, 0, 41,
+ 0, 0, 520, 0, 0, 0, 0, 46, 34, 51,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 29,
+ 30, 31, 0, 0, 0, 0, 0, 0, 0, 0,
+ 33, 0, 0, 0, 0, 0, 0, 35, 0, 0,
+ 0, 36, 37, 0, 38, 0, 0, 0, 39, 0,
+ 40, 42, 43, 0, 0, 45, 0, 0, 0, 47,
+ 0, 48, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 53, 49, 52, 50, 0, 54, 0,
+ 55, 0, 57, 0, 58, 0, 0, 0, 0, 44,
+ 56, 32, 0, 0, 0, 0, 41, 0, 0, 0,
+ 0, 0, 0, 0, 46, 34, 51, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -139, 0, 0, 0,
+ 29, 30, 31, 0, 0, 0, 0, 0, 0, 0,
+ 0, 33, 0, 0, 0, 0, 0, 0, 35, 0,
+ 0, 0, 36, 37, 0, 38, 0, 0, 0, 39,
+ 0, 40, 42, 43, 0, 0, 45, 0, 0, 0,
+ 47, 0, 48, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 53, 49, 52, 50, 0, 54,
+ 0, 55, 0, 57, 0, 58, 0, 0, 0, 0,
+ 44, 56, 32, 0, 0, 0, 0, 41, 0, 0,
+ 0, 0, 0, 0, 0, 46, 34, 51, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 29, 30, 31,
+ 0, 0, 0, 0, 0, 0, 0, 0, 33, 0,
+ 0, 0, 0, 0, 0, 35, 0, 0, 0, 36,
+ 37, 0, 38, 0, 0, 0, 39, 0, 40, 42,
+ 43, 0, 0, 45, 0, 0, 0, 47, 0, 48,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 53, 49, 52, 50, 0, 54, 0, 55, 0,
+ 57, 285, 58, 0, 0, 0, 0, 44, 56, 32,
+ 0, 0, 0, 0, 41, 0, 0, 0, 0, 0,
+ 0, 0, 46, 34, 51, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 492, 0, 0, 29, 30, 31,
+ 0, 0, 0, 0, 0, 0, 0, 0, 33, 0,
+ 0, 0, 0, 0, 0, 35, 0, 0, 0, 36,
+ 37, 0, 38, 0, 0, 0, 39, 0, 40, 42,
+ 43, 0, 0, 45, 0, 0, 0, 47, 0, 48,
+ 0, 0, 498, 0, 0, 0, 0, 0, 0, 0,
+ 0, 53, 49, 52, 50, 0, 54, 0, 55, 0,
+ 57, 0, 58, 0, 0, 0, 0, 44, 56, 32,
+ 0, 0, 0, 0, 41, 0, 0, 0, 0, 0,
+ 0, 0, 46, 34, 51, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 492, 0, 0, 29, 30, 31,
+ 0, 0, 0, 0, 0, 0, 0, 0, 33, 0,
+ 0, 0, 0, 0, 0, 35, 0, 0, 0, 36,
+ 37, 0, 38, 0, 0, 0, 39, 0, 40, 42,
+ 43, 0, 0, 45, 0, 0, 0, 47, 0, 48,
+ 0, 0, 493, 0, 0, 0, 0, 0, 0, 0,
+ 0, 53, 49, 52, 50, 0, 54, 0, 55, 0,
+ 57, 0, 58, 0, 0, 0, 0, 44, 56, 32,
+ 0, 0, 0, 0, 41, 0, 0, 0, 0, 0,
+ 0, 0, 46, 34, 51, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 500, 0, 0, 29, 30, 31,
+ 0, 0, 0, 0, 0, 0, 0, 0, 33, 0,
+ 0, 0, 0, 0, 0, 35, 0, 0, 0, 36,
+ 37, 0, 38, 0, 0, 0, 39, 0, 40, 42,
+ 43, 0, 0, 45, 0, 0, 0, 47, 0, 48,
+ 0, 0, 501, 0, 0, 0, 0, 0, 0, 0,
+ 0, 53, 49, 52, 50, 0, 54, 0, 55, 0,
+ 57, 0, 58, 0, 0, 0, 0, 44, 56, 32,
+ 0, 0, 0, 0, 41, 0, 0, 0, 0, 0,
+ 0, 0, 46, 34, 51, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 500, 0, 0, 29, 30, 31,
+ 0, 0, 0, 0, 0, 0, 0, 0, 33, 0,
+ 0, 0, 0, 0, 0, 35, 0, 0, 0, 36,
+ 37, 0, 38, 0, 0, 0, 39, 0, 40, 42,
+ 43, 0, 0, 45, 0, 0, 0, 47, 0, 48,
+ 0, 0, 503, 0, 0, 0, 0, 0, 0, 0,
+ 0, 53, 49, 52, 50, 0, 54, 0, 55, 0,
+ 57, 0, 58, 0, 0, 0, 0, 44, 56, 32,
+ 0, 0, 0, 0, 41, 0, 0, 0, 0, 0,
+ 0, 0, 46, 34, 51, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 29, 30, 31, 0, 0, 0,
+ 0, 0, 0, 0, 0, 33, 0, 0, 0, 0,
+ 0, 0, 35, 222, 0, 0, 599, 37, 0, 38,
+ 0, 0, 0, 39, 0, 40, 42, 43, 0, 0,
+ 45, 0, 0, 0, 47, 0, 48, 0, 0, 0,
+ 0, 0, 0, 0, 226, 0, 0, 0, 53, 49,
+ 52, 50, 227, 54, 0, 55, 229, 57, 0, 58,
+ 0, 232, 0, 0, 44, 56, 32, 0, 0, 0,
+ 0, 41, 0, 0, 0, 0, 0, 0, 0, 46,
+ 34, 51, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 29, 30, 31, 0, 0, 0, 0, 0, 0,
+ 0, 0, 33, 0, 0, 0, 0, 0, 0, 35,
+ 222, 0, 0, 599, 646, 0, 38, 0, 0, 0,
+ 39, 0, 40, 42, 43, 0, 0, 45, 0, 0,
+ 0, 47, 0, 48, 0, 0, 0, 0, 0, 0,
+ 0, 226, 0, 0, 0, 53, 49, 52, 50, 227,
+ 54, 0, 55, 229, 57, 0, 58, 0, 232, 0,
+ 0, 44, 56, 32, 0, 0, 0, 0, 41, 0,
+ 0, 0, 0, 0, 0, 0, 46, 34, 51, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 29, 30,
+ 31, 0, 0, 0, 0, 0, 0, 0, 0, 33,
+ 0, 0, 0, 0, 0, 0, 35, 222, 0, 0,
+ 223, 37, 0, 38, 0, 0, 0, 39, 0, 40,
+ 42, 43, 0, 0, 45, 0, 0, 0, 47, 0,
+ 48, 0, 0, 0, 0, 0, 0, 0, 226, 0,
+ 0, 0, 53, 49, 52, 50, 227, 54, 0, 55,
+ 229, 57, 0, 58, 0, 232, 0, 0, 44, 56,
+ 32, 0, 0, 0, 0, 41, 0, 0, 0, 0,
+ 0, 0, 0, 46, 34, 51, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 111, 112, 113, 0, 0,
+ 115, 117, 118, 0, 0, 119, 0, 120, 0, 0,
+ 0, 123, 124, 125, 0, 0, 0, 0, 0, 0,
+ 35, 126, 127, 128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 130, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 133, 0, 0, 0, 0, 0, 0, 49, 52, 50,
+ 134, 135, 136, 0, 138, 139, 140, 141, 142, 143,
+ 0, 0, 131, 137, 122, 114, 129, 116, 132, 0,
+ 0, 0, 121, 0, 0, 0, 0, 46, 34, 51,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 111,
+ 112, 113, 0, 0, 115, 117, 118, 0, 0, 119,
+ 0, 120, 0, 0, 0, 123, 124, 125, 0, 0,
+ 0, 0, 0, 0, 35, 126, 127, 128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 130, 0,
+ 0, 0, 399, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 133, 0, 0, 0, 0, 0,
+ 401, 49, 52, 50, 134, 135, 136, 0, 138, 139,
+ 140, 141, 142, 143, 0, 0, 131, 137, 122, 114,
+ 129, 116, 132, 0, 0, 0, 121, 0, 0, 0,
+ 0, 46, 34, 51, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 111, 112, 113, 0, 0, 115, 117,
+ 118, 0, 0, 119, 0, 120, 0, 0, 0, 123,
+ 124, 125, 0, 0, 0, 0, 0, 0, 35, 126,
+ 127, 128, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 130, 0, 0, 0, 399, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 133, 0,
+ 0, 0, 0, 0, 401, 49, 52, 50, 134, 135,
+ 136, 0, 138, 139, 140, 141, 142, 143, 0, 0,
+ 131, 137, 122, 114, 129, 116, 132, 0, 0, 0,
+ 121, 0, 0, 0, 0, 46, 377, 384, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 111, 112, 113,
+ 0, 0, 115, 117, 118, 0, 0, 119, 0, 120,
+ 0, 0, 0, 123, 124, 125, 0, 0, 0, 0,
+ 0, 0, 35, 126, 127, 128, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 130, 0, 0, 0,
+ 399, 0, 0, 0, 0, 0, 0, 0, 400, 0,
+ 0, 0, 133, 0, 0, 0, 0, 0, 401, 49,
+ 52, 50, 134, 135, 136, 0, 138, 139, 140, 141,
+ 142, 143, 0, 0, 131, 137, 122, 114, 129, 116,
+ 132, 0, 0, 0, 121, 0, 0, 0, 0, 46,
+ 377, 384, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 215, 0, 0, 0, 0, 217, 0, 29, 30,
+ 31, 219, 0, 0, 0, 0, 0, 0, 220, 33,
+ 0, 0, 0, 0, 0, 0, 35, 222, 0, 0,
+ 223, 37, 0, 38, 0, 0, 0, 39, 0, 40,
+ 42, 43, 0, 0, 45, 0, 0, 0, 47, 0,
+ 48, 0, 0, 0, 0, 0, 225, 0, 226, 0,
+ 0, 0, 53, 49, 52, 50, 227, 54, 228, 55,
+ 229, 57, 230, 58, 231, 232, 0, 0, 44, 56,
+ 32, 216, 224, 218, 0, 41, 0, 0, 0, 0,
+ 0, 0, 0, 46, 34, 51, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 215, 0, 0, 0, 0,
+ 217, 0, 29, 30, 31, 219, 0, 0, 0, 0,
+ 0, 0, 220, 221, 0, 0, 0, 0, 0, 0,
+ 35, 222, 0, 0, 223, 37, 0, 38, 0, 0,
+ 0, 39, 0, 40, 42, 43, 0, 0, 45, 0,
+ 0, 0, 47, 0, 48, 0, 0, 0, 0, 0,
+ 225, 0, 226, 0, 0, 0, 53, 49, 52, 50,
+ 227, 54, 228, 55, 229, 57, 230, 58, 231, 232,
+ 0, 0, 44, 56, 32, 216, 224, 218, 0, 41,
+ 0, 0, 0, 0, 0, 0, 0, 46, 34, 51,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 603,
+ 112, 113, 0, 0, 605, 117, 607, 30, 31, 608,
+ 0, 120, 0, 0, 0, 123, 610, 611, 0, 0,
+ 0, 0, 0, 0, 35, 612, 127, 128, 223, 37,
+ 0, 38, 0, 0, 0, 39, 0, 40, 614, 43,
+ 0, 0, 616, 0, 0, 0, 47, 0, 48, 0,
+ 0, 0, 0, 0, 617, 0, 226, 0, 0, 0,
+ 618, 49, 52, 50, 619, 620, 621, 55, 623, 624,
+ 625, 626, 627, 628, 0, 0, 615, 622, 609, 604,
+ 613, 606, 132, 41, 0, 0, 121, 0, 0, 0,
+ 0, 46, 377, 384, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 368, 112, 113, 0, 0, 370, 117,
+ 372, 30, 31, 373, 0, 120, 0, 0, 0, 123,
+ 375, 376, 0, 0, 0, 0, 0, 0, 35, 378,
+ 127, 128, 223, 37, 0, 38, 0, 0, 0, 39,
+ 0, 40, 380, 43, 0, 0, 382, 0, 0, 0,
+ 47, 0, 48, 0, -286, 0, 0, 0, 383, 0,
+ 226, 0, 0, 0, 385, 49, 52, 50, 386, 387,
+ 388, 55, 390, 391, 392, 393, 394, 395, 0, 0,
+ 381, 389, 374, 369, 379, 371, 132, 41, 0, 0,
+ 121, 0, 0, 0, 0, 46, 377, 384, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
- 152, 652, 331, 669, 535, 531, 538, 142, 528, 148,
- 641, 16, 313, 393, 485, 500, 626, 630, 263, 638,
- 183, 625, 623, 206, 574, 447, 583, 320, 183, 253,
- 313, 248, 466, 145, 663, 653, 616, 584, 556, 640,
- 581, 248, 437, 253, 248, 495, 183, 178, 453, 150,
- 462, 347, 455, 550, 554, 183, 351, 447, 458, 190,
- 313, 457, 425, 188, 469, 441, 433, 253, 237, 468,
- 0, 313, 173, 171, 393, 409, 447, 498, 409, 464,
- 400, 0, 165, 206, 475, 206, 512, 511, 0, 0,
- 188, 0, 0, 206, 0, 206, 0, 62, 0, 459,
- 417, 206, 206, 206, 188, 0, 62, 0, 62, 62,
- 507, 504, 410, 148, 62, 410, 460, 62, 419, 505,
- 407, 412, 170, 62, 62, 459, 506, 444, 277, 148,
- 422, 331, 187, 281, 62, 62, 62, 180, 260, 295,
- 296, 297, 62, 62, 656, 655, 314, 298, 299, 62,
- 62, 503, 182, 62, 206, 362, 514, 393, 247, 62,
- 62, 460, 502, 62, 62, 639, 313, 167, 92, 99,
- 62, 206, 206, 514, 510, 345, 100, 260, 562, 62,
- 62, 62, 394, 493, 93, 94, 95, 492, 62, 62,
- 182, 206, 62, 206, 96, 62, 246, 97, 62, 90,
- 62, 401, 91, 206, 62, 86, 355, 340, 353, 62,
- 108, 247, 206, 349, 188, 313, 102, 206, 393, 104,
- 313, 62, 206, 182, 206, 206, 62, 362, 459, 206,
- 242, 62, 469, 460, 62, 514, 409, 63, 318, 110,
- 657, 341, 239, 590, 403, 62, 322, 206, 72, 62,
- 362, 62, 362, 69, 206, 98, 62, 62, 70, 71,
- 514, 0, 206, 62, 62, 566, 356, 0, 206, 79,
- 62, 108, 74, 410, 483, 281, 0, 309, 0, 0,
- 62, 62, 281, 304, 62, 281, 281, 62, 362, 281,
- 343, 0, 281, 284, 289, 316, 324, 327, 0, 311,
- 110, 177, 0, 309, 206, 62, 479, 0, 281, 62,
- 281, 309, 301, 309, 281, 0, 281, 309, 281, 62,
- 306, 0, 281, 62, 281, 337, 302, 0, 281, 578,
- 300, 514, 260, 328, 562, 308, 636, 570, 443, 330,
- 522, 0, 0, 0, 0, 0, 514, 0, 206, 0,
- 0, 0, 513, 523, 0, 522, 0, 485, 542, 543,
- 544, 545, 549, 546, 547, 0, 586, 513, 523, 0,
- 0, 0, 0, 0, 440, 588, 589, 542, 543, 544,
- 545, 549, 546, 547, 586, 0, 0, 0, 0, 0,
- 0, 0, 0, 634, 635, 542, 543, 544, 545, 549,
- 546, 547, 578, 0, 0, 0, 0, 0, 0, 0,
- 0, 579, 580, 542, 543, 544, 545, 549, 546, 547,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 573, 0, 0, 0, 0, 0, 0, 0, 0,
- 514, 0, 0, 0, 0, 0, 0, 0, 0, 522,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 513, 523, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0};
+ 16, 150, 636, 543, 536, 654, 540, 334, 154, 682,
+ 676, 144, 256, 643, 638, 451, 639, 448, 504, 489,
+ 397, 316, 266, 651, 185, 586, 629, 251, 185, 323,
+ 596, 595, 566, 653, 665, 593, 666, 466, 448, 568,
+ 180, 451, 457, 459, 316, 316, 499, 251, 147, 462,
+ 470, 256, 461, 448, 437, 429, 441, 185, 354, 445,
+ 173, 451, 185, 240, 192, 562, 404, 473, 472, 0,
+ 316, 175, 533, 502, 152, 167, 208, 251, 256, 190,
+ 516, 479, 190, 208, 208, 413, 263, 208, 316, 0,
+ 397, 365, 515, 208, 518, 518, 208, 0, 62, 670,
+ 464, 0, 208, 62, 652, 509, 208, 208, 62, 350,
+ 463, 423, 62, 190, 511, 426, 398, 62, 62, 510,
+ 464, 411, 150, 414, 468, 62, 334, 184, 62, 62,
+ 182, 280, 62, 302, 301, 250, 284, 62, 62, 463,
+ 208, 62, 189, 300, 413, 62, 317, 62, 172, 208,
+ 299, 62, 298, 506, 62, 169, 507, 150, 62, 497,
+ 508, 518, 62, 496, 319, 416, 574, 86, 62, 321,
+ 413, 62, 62, 93, 62, 514, 95, 96, 397, 97,
+ 62, 263, 414, 62, 90, 208, 316, 91, 62, 62,
+ 62, 184, 92, 405, 62, 94, 316, 208, 108, 250,
+ 62, 249, 190, 343, 348, 407, 102, 358, 414, 208,
+ 104, 352, 208, 208, 365, 208, 62, 208, 669, 668,
+ 208, 325, 100, 208, 62, 365, 69, 208, 110, 397,
+ 602, 242, 62, 62, 70, 71, 62, 208, 473, 72,
+ 245, 359, 62, 487, 62, 63, 0, 62, 263, 463,
+ 518, 62, 74, 62, 0, 578, 421, 79, 62, 98,
+ 464, 62, 344, 62, 208, 184, 365, 99, 312, 62,
+ 62, 0, 346, 284, 284, 284, 62, 292, 287, 62,
+ 62, 284, 208, 303, 284, 284, 304, 305, 312, 62,
+ 340, 108, 62, 284, 284, 365, 312, 284, 312, 62,
+ 309, 284, 62, 284, 284, 307, 518, 284, 0, 312,
+ 333, 208, 0, 483, 284, 527, 330, 327, 331, 356,
+ 311, 110, 179, 0, 0, 590, 0, 517, 528, 582,
+ 574, 314, 649, 0, 0, 208, 0, 0, 518, 547,
+ 548, 549, 550, 554, 551, 552, 0, 527, 0, 0,
+ 0, 0, 598, 447, 489, 0, 0, 0, 0, 517,
+ 528, 600, 601, 547, 548, 549, 550, 554, 551, 552,
+ 0, 0, 0, 0, 590, 0, 0, 0, 0, 0,
+ 0, 0, 444, 591, 592, 547, 548, 549, 550, 554,
+ 551, 552, 598, 0, 0, 0, 0, 0, 0, 0,
+ 0, 647, 648, 547, 548, 549, 550, 554, 551, 552,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 585,
+ 0, 0, 0, 0, 0, 0, 0, 0, 518, 0,
+ 0, 0, 0, 0, 0, 0, 0, 527, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 517,
+ 528, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
const short QQmlJSGrammar::action_check [] = {
- 7, 55, 48, 55, 55, 55, 36, 7, 36, 33,
- 55, 7, 7, 33, 37, 7, 7, 61, 60, 60,
- 36, 7, 33, 8, 36, 7, 16, 1, 36, 60,
- 7, 36, 2, 48, 7, 36, 5, 36, 36, 36,
- 79, 5, 36, 60, 33, 33, 55, 60, 7, 36,
- 34, 7, 33, 7, 7, 33, 36, 7, 7, 77,
- 36, 33, 8, 5, 1, 8, 33, 60, 29, 79,
- 36, 33, 17, 8, 37, 79, 33, 60, 33, 8,
- 1, 60, 2, 8, 7, 60, 33, 55, 48, 60,
- 29, 2, 7, 2, 7, 36, 36, 7, 17, 7,
- 33, 66, 7, 61, 48, 31, 36, 1, 36, 33,
- 8, 7, 60, 20, 36, 66, 33, 7, 36, 55,
- 36, 8, 60, 8, 15, -1, 40, 79, 8, 61,
- 61, 62, 10, 8, 61, 62, 40, 51, 8, 15,
- 40, 40, 8, 34, 8, 42, 6, 51, 24, 61,
- 62, 51, 51, 7, 8, 8, 53, 8, 61, 62,
- 20, 8, 8, 8, 8, 15, 61, 62, 61, 62,
- 8, 8, 15, 60, -1, 60, 56, 55, 61, 62,
- 61, 62, 61, 62, 34, 60, 56, 61, 62, 91,
- 92, 34, 56, 50, 60, 15, 29, 54, 0, 91,
- 92, 50, 61, 62, 24, 54, 25, 60, 27, 12,
- 61, 56, 29, 60, 60, 25, 60, 27, 56, 38,
- 25, 25, 27, 27, 61, 62, 12, 15, 38, 61,
- 62, 12, 29, 38, 38, 29, 7, -1, 25, 7,
- 27, 36, 75, 8, 29, 8, 34, -1, 36, 15,
- 25, 38, 27, 86, 57, 7, -1, 89, 75, 7,
- 63, -1, 33, 38, 15, 29, 61, 62, 34, 86,
- 36, 57, 29, -1, -1, -1, 57, 63, 75, -1,
- -1, 75, 63, 34, 15, 36, -1, 61, 62, 86,
- 75, -1, 86, 61, 62, -1, 61, 62, 61, 62,
- -1, 86, -1, 34, 25, 36, 27, 15, -1, 61,
- 62, 75, -1, 61, 62, 18, 19, 38, 75, 93,
- 15, -1, 86, 94, -1, 33, 34, -1, 36, 86,
- 18, 19, 18, 19, 18, 19, 47, -1, 33, 34,
- -1, 36, 45, 46, 98, 99, 100, 101, 102, 103,
- 61, 62, -1, -1, 23, 24, -1, 45, 46, 45,
- 46, 45, 46, 32, 23, 24, 35, -1, 37, -1,
- -1, -1, -1, 32, 23, 24, 35, -1, 37, -1,
- 23, 24, 93, 32, -1, 25, 35, 27, 37, 32,
- -1, -1, 35, 29, 37, 23, 24, -1, 38, -1,
- -1, -1, -1, 31, 32, 23, 24, 35, -1, 37,
- -1, -1, -1, 31, 32, 23, 24, 35, 29, 37,
- -1, -1, -1, 31, 32, 23, 24, 35, -1, 37,
- 66, 67, 68, 31, 32, 23, 24, 35, -1, 37,
- -1, -1, -1, 31, 32, -1, -1, 35, -1, 37,
- 29, -1, -1, 29, -1, 66, 67, 68, 94, 95,
- 96, 29, -1, -1, 29, -1, 23, 24, 29, -1,
- -1, 29, 15, -1, 29, 32, -1, -1, 35, -1,
- 37, 36, -1, 94, 95, 96, 29, 66, 67, 68,
- 66, 67, 68, -1, -1, -1, -1, -1, 66, 67,
- 68, 66, 67, 68, -1, 66, 67, 68, 66, 67,
- 68, 66, 67, 68, -1, 94, 95, 96, 94, 95,
- 96, -1, -1, 66, 67, 68, 94, 95, 96, 94,
- 95, 96, 15, 94, 95, 96, 94, 95, 96, 94,
- 95, 96, -1, 29, -1, -1, 29, -1, -1, 29,
- 36, 94, 95, 96, 29, -1, -1, 29, -1, -1,
- -1, 36, -1, -1, -1, 29, -1, -1, 29, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 66, 67, 68, 66, 67, 68, 66, 67, 68, 61,
- 62, 66, 67, 68, 66, 67, 68, 61, 62, -1,
- 61, 62, 66, 67, 68, 66, 67, 68, 94, 95,
- 96, 94, 95, 96, 94, 95, 96, 29, -1, 94,
- 95, 96, 94, 95, 96, 29, 15, -1, 29, -1,
- 94, 95, 96, 94, 95, 96, -1, -1, -1, -1,
- 29, -1, -1, -1, -1, -1, -1, -1, -1, 61,
- 62, -1, -1, -1, 66, 67, 68, 61, 62, -1,
- 61, 62, 66, 67, 68, 66, 67, 68, -1, -1,
- -1, -1, -1, -1, -1, 3, -1, 66, 67, 68,
- -1, -1, 94, 95, 96, 13, -1, -1, -1, 17,
- 94, 95, 96, 94, 95, 96, -1, -1, 26, -1,
- 28, -1, -1, 31, -1, 94, 95, 96, -1, -1,
- -1, 39, -1, 41, 42, -1, -1, 3, -1, -1,
- -1, 49, -1, -1, 52, 53, -1, 13, -1, -1,
- 58, 17, -1, -1, -1, -1, 64, -1, -1, -1,
- 26, -1, 28, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 80, 39, -1, 41, 42, -1, -1, -1,
- -1, -1, -1, 49, -1, -1, 52, 53, -1, -1,
- -1, -1, 58, -1, -1, -1, -1, -1, 64, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 80, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 12, 13, -1, -1, -1, -1, -1, -1, -1, -1,
- 22, -1, -1, -1, -1, -1, -1, 29, -1, -1,
- -1, 33, 34, -1, 36, -1, -1, -1, -1, -1,
- -1, 43, -1, -1, -1, 47, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 65, 66, 67, 68, -1, 70, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 81,
- 82, 83, -1, -1, -1, 87, -1, -1, -1, -1,
- -1, -1, 94, 95, 96, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 12, 13, -1, -1, -1, -1,
- -1, -1, -1, -1, 22, -1, -1, -1, -1, -1,
- -1, 29, -1, -1, -1, 33, 34, -1, 36, -1,
- -1, -1, -1, -1, -1, 43, -1, -1, -1, 47,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 65, 66, 67,
- 68, -1, 70, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 81, 82, 83, -1, -1, -1, 87,
- -1, -1, -1, -1, -1, -1, 94, 95, 96, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 10, -1,
- 12, 13, -1, -1, -1, -1, -1, -1, -1, -1,
- 22, -1, -1, -1, -1, -1, -1, 29, -1, -1,
- -1, 33, 34, -1, 36, -1, -1, -1, -1, -1,
- -1, 43, -1, -1, -1, 47, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 65, 66, 67, 68, -1, 70, -1,
- -1, -1, -1, 75, -1, -1, -1, -1, -1, 81,
- 82, 83, 84, -1, -1, 87, -1, -1, -1, -1,
- -1, -1, 94, 95, 96, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 10, -1, 12, 13, -1, -1,
- -1, -1, -1, -1, -1, -1, 22, -1, -1, -1,
- -1, -1, -1, 29, -1, -1, -1, 33, 34, -1,
- 36, -1, -1, -1, -1, -1, -1, 43, -1, -1,
- -1, 47, -1, -1, -1, -1, -1, -1, -1, 55,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 65,
- 66, 67, 68, -1, 70, -1, -1, -1, -1, 75,
- -1, -1, -1, -1, -1, 81, 82, 83, 84, -1,
- -1, 87, -1, -1, -1, -1, -1, -1, 94, 95,
- 96, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 10, -1, 12, 13, -1, -1, -1, -1, -1, -1,
- -1, -1, 22, -1, -1, -1, -1, -1, -1, 29,
- -1, -1, -1, 33, 34, -1, 36, -1, -1, -1,
- -1, -1, -1, 43, -1, -1, -1, 47, -1, -1,
- -1, -1, -1, -1, -1, 55, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 65, 66, 67, 68, -1,
- 70, -1, -1, -1, -1, 75, -1, -1, -1, -1,
- -1, 81, 82, 83, 84, -1, -1, 87, -1, -1,
- -1, -1, -1, -1, 94, 95, 96, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 11, 12, 13, -1,
- -1, -1, -1, -1, -1, -1, -1, 22, -1, -1,
- -1, -1, -1, -1, 29, -1, -1, -1, 33, 34,
- -1, 36, -1, -1, -1, 40, -1, 42, 43, 44,
- -1, -1, 47, -1, -1, -1, 51, -1, 53, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 65, 66, 67, 68, -1, 70, -1, 72, -1, 74,
- -1, 76, -1, -1, -1, -1, 81, 82, 83, -1,
- -1, -1, 87, -1, -1, -1, -1, -1, -1, 94,
- 95, 96, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 7, -1, -1, -1, 11, 12, 13, -1, -1,
- -1, -1, -1, -1, -1, -1, 22, -1, -1, -1,
- -1, -1, -1, 29, -1, -1, -1, 33, 34, -1,
- 36, -1, -1, -1, 40, -1, 42, 43, 44, -1,
- -1, 47, -1, -1, -1, 51, -1, 53, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 65,
- 66, 67, 68, -1, 70, -1, 72, -1, 74, -1,
- 76, -1, -1, -1, -1, 81, 82, 83, -1, -1,
- -1, 87, -1, -1, -1, -1, -1, -1, 94, 95,
- 96, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 11, 12, 13, -1, -1, -1, -1, -1, -1, -1,
- -1, 22, -1, -1, -1, -1, -1, -1, 29, -1,
- -1, -1, 33, 34, -1, 36, -1, -1, -1, 40,
- -1, 42, 43, 44, -1, -1, 47, -1, -1, -1,
- 51, -1, 53, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 65, 66, 67, 68, -1, 70,
- -1, 72, -1, 74, 75, 76, -1, -1, -1, -1,
- 81, 82, 83, -1, -1, -1, 87, -1, -1, -1,
- -1, -1, -1, 94, 95, 96, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 8, -1, -1, 11, 12,
- 13, -1, -1, -1, -1, -1, -1, -1, -1, 22,
- -1, -1, -1, -1, -1, -1, 29, -1, -1, -1,
- 33, 34, -1, 36, -1, -1, -1, 40, -1, 42,
- 43, 44, -1, -1, 47, -1, -1, -1, 51, -1,
- 53, -1, -1, 56, -1, -1, -1, -1, -1, -1,
- -1, -1, 65, 66, 67, 68, -1, 70, -1, 72,
- -1, 74, -1, 76, -1, -1, -1, -1, 81, 82,
- 83, -1, -1, -1, 87, -1, -1, -1, -1, -1,
- -1, 94, 95, 96, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 8, -1, -1, 11, 12, 13, -1,
- -1, -1, -1, -1, -1, -1, -1, 22, -1, -1,
- -1, -1, -1, -1, 29, -1, -1, -1, 33, 34,
- -1, 36, -1, -1, -1, 40, -1, 42, 43, 44,
- -1, -1, 47, -1, -1, -1, 51, -1, 53, -1,
- -1, 56, -1, -1, -1, -1, -1, -1, -1, -1,
- 65, 66, 67, 68, -1, 70, -1, 72, -1, 74,
- -1, 76, -1, -1, -1, -1, 81, 82, 83, -1,
- -1, -1, 87, -1, -1, -1, -1, -1, -1, 94,
- 95, 96, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 8, -1, -1, 11, 12, 13, -1, -1, -1,
- -1, -1, -1, -1, -1, 22, -1, -1, -1, -1,
- -1, -1, 29, -1, -1, -1, 33, 34, -1, 36,
- -1, -1, -1, 40, -1, 42, 43, 44, -1, -1,
- 47, -1, -1, -1, 51, -1, 53, -1, -1, 56,
- -1, -1, -1, -1, -1, -1, -1, -1, 65, 66,
- 67, 68, -1, 70, -1, 72, -1, 74, -1, 76,
- -1, -1, -1, -1, 81, 82, 83, -1, -1, -1,
- 87, -1, -1, -1, -1, -1, -1, 94, 95, 96,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 8,
- -1, -1, 11, 12, 13, -1, -1, -1, -1, -1,
- -1, -1, -1, 22, -1, -1, -1, -1, -1, -1,
- 29, -1, -1, -1, 33, 34, -1, 36, -1, -1,
- -1, 40, -1, 42, 43, 44, -1, -1, 47, -1,
- -1, -1, 51, -1, 53, -1, -1, 56, -1, -1,
- -1, -1, -1, -1, -1, -1, 65, 66, 67, 68,
- -1, 70, -1, 72, -1, 74, -1, 76, -1, -1,
- -1, -1, 81, 82, 83, -1, -1, -1, 87, -1,
- -1, -1, -1, -1, -1, 94, 95, 96, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 11, 12, 13,
- -1, -1, -1, -1, -1, -1, -1, -1, 22, -1,
- -1, -1, -1, -1, -1, 29, 30, -1, -1, 33,
- 34, -1, 36, -1, -1, -1, 40, -1, 42, 43,
- 44, -1, -1, 47, -1, -1, -1, 51, -1, 53,
- -1, -1, -1, -1, -1, -1, -1, 61, -1, -1,
- -1, 65, 66, 67, 68, 69, 70, -1, 72, 73,
- 74, -1, 76, -1, 78, -1, -1, 81, 82, 83,
- -1, -1, -1, 87, -1, -1, -1, -1, -1, -1,
- 94, 95, 96, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 11, 12, 13, -1, -1, -1, -1, -1,
- -1, -1, -1, 22, -1, -1, -1, -1, -1, -1,
- 29, 30, -1, -1, 33, 34, -1, 36, -1, -1,
- -1, 40, -1, 42, 43, 44, -1, -1, 47, -1,
- -1, -1, 51, -1, 53, -1, -1, -1, -1, -1,
- -1, -1, 61, -1, -1, -1, 65, 66, 67, 68,
- 69, 70, -1, 72, 73, 74, -1, 76, -1, 78,
- -1, -1, 81, 82, 83, -1, -1, -1, 87, -1,
- -1, -1, -1, -1, -1, 94, 95, 96, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 11, 12, 13,
- -1, -1, -1, -1, -1, -1, -1, -1, 22, -1,
- -1, -1, -1, -1, -1, 29, 30, -1, -1, 33,
- 34, -1, 36, -1, -1, -1, 40, -1, 42, 43,
- 44, -1, -1, 47, -1, -1, -1, 51, -1, 53,
- -1, -1, -1, -1, -1, -1, -1, 61, -1, -1,
- -1, 65, 66, 67, 68, 69, 70, -1, 72, 73,
- 74, -1, 76, -1, 78, -1, -1, 81, 82, 83,
- -1, -1, -1, 87, -1, -1, -1, -1, -1, -1,
- 94, 95, 96, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4, 5, 6, -1, -1, 9, 10, 11,
- -1, -1, 14, -1, 16, -1, -1, -1, 20, 21,
- 22, -1, -1, -1, -1, -1, -1, 29, 30, 31,
- 32, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 43, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 59, -1, -1,
- -1, -1, -1, -1, 66, 67, 68, 69, 70, 71,
- -1, 73, 74, 75, 76, 77, 78, -1, -1, 81,
- 82, 83, 84, 85, 86, -1, -1, -1, -1, -1,
- -1, -1, 94, 95, 96, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4, 5, 6, -1, -1, 9,
- 10, 11, -1, -1, 14, -1, 16, -1, -1, -1,
- 20, 21, 22, -1, -1, -1, -1, -1, -1, 29,
- 30, 31, 32, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 43, -1, -1, -1, 47, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 59,
- -1, -1, -1, -1, -1, 65, 66, 67, 68, 69,
- 70, 71, -1, 73, 74, 75, 76, 77, 78, -1,
- -1, 81, 82, 83, 84, 85, 86, -1, -1, -1,
- -1, -1, -1, -1, 94, 95, 96, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4, 5, 6, -1,
- -1, 9, 10, 11, -1, -1, 14, -1, 16, -1,
- -1, -1, 20, 21, 22, -1, -1, -1, -1, -1,
- -1, 29, 30, 31, 32, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 43, -1, -1, -1, 47,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 59, -1, -1, -1, -1, -1, 65, 66, 67,
- 68, 69, 70, 71, -1, 73, 74, 75, 76, 77,
- 78, -1, -1, 81, 82, 83, 84, 85, 86, -1,
- -1, -1, -1, -1, -1, -1, 94, 95, 96, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 4, 5,
- 6, -1, -1, 9, 10, 11, -1, -1, 14, -1,
- 16, -1, -1, -1, 20, 21, 22, -1, -1, -1,
- -1, -1, -1, 29, 30, 31, 32, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 43, -1, -1,
- -1, 47, -1, -1, -1, -1, -1, -1, -1, 55,
- -1, -1, -1, 59, -1, -1, -1, -1, -1, 65,
- 66, 67, 68, 69, 70, 71, -1, 73, 74, 75,
- 76, 77, 78, -1, -1, 81, 82, 83, 84, 85,
- 86, -1, -1, -1, -1, -1, -1, -1, 94, 95,
- 96, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 4, -1, -1, -1, -1, 9, -1, 11, 12, 13,
- 14, -1, -1, -1, -1, -1, -1, 21, 22, -1,
- -1, -1, -1, -1, -1, 29, 30, -1, -1, 33,
- 34, -1, 36, -1, -1, -1, 40, -1, 42, 43,
- 44, -1, -1, 47, -1, -1, -1, 51, -1, 53,
- -1, -1, -1, -1, -1, 59, -1, 61, -1, -1,
- -1, 65, 66, 67, 68, 69, 70, 71, 72, 73,
- 74, 75, 76, 77, 78, -1, -1, 81, 82, 83,
- 84, 85, -1, 87, -1, -1, -1, -1, -1, -1,
- 94, 95, 96, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4, -1, -1, -1, -1, 9, -1, 11,
- 12, 13, 14, -1, -1, -1, -1, -1, -1, 21,
- 22, -1, -1, -1, -1, -1, -1, 29, 30, -1,
- -1, 33, 34, -1, 36, -1, -1, -1, 40, -1,
- 42, 43, 44, -1, -1, 47, -1, -1, -1, 51,
- -1, 53, -1, -1, -1, -1, -1, 59, -1, 61,
- -1, -1, -1, 65, 66, 67, 68, 69, 70, 71,
- 72, 73, 74, 75, 76, 77, 78, -1, -1, 81,
- 82, 83, 84, 85, -1, 87, -1, -1, -1, -1,
- -1, -1, 94, 95, 96, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4, 5, 6, -1, -1, 9,
- 10, 11, 12, 13, 14, -1, 16, -1, -1, -1,
- 20, 21, 22, -1, -1, -1, -1, -1, -1, 29,
- 30, 31, 32, 33, 34, -1, 36, -1, -1, -1,
- 40, -1, 42, 43, 44, -1, -1, 47, -1, -1,
- -1, 51, -1, 53, -1, -1, -1, -1, -1, 59,
- -1, 61, -1, -1, -1, 65, 66, 67, 68, 69,
- 70, 71, 72, 73, 74, 75, 76, 77, 78, -1,
- -1, 81, 82, 83, 84, 85, 86, 87, -1, -1,
- -1, -1, -1, -1, 94, 95, 96, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4, 5, 6, -1,
- -1, 9, 10, 11, 12, 13, 14, -1, 16, -1,
- -1, -1, 20, 21, 22, -1, -1, -1, -1, -1,
- -1, 29, 30, 31, 32, 33, 34, -1, 36, -1,
- -1, -1, 40, -1, 42, 43, 44, -1, -1, 47,
- -1, -1, -1, 51, -1, 53, -1, 55, -1, -1,
- -1, 59, -1, 61, -1, -1, -1, 65, 66, 67,
- 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
- 78, -1, -1, 81, 82, 83, 84, 85, 86, 87,
- -1, -1, -1, -1, -1, -1, 94, 95, 96, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
+ 7, 33, 33, 7, 55, 8, 36, 36, 7, 7,
+ 7, 36, 36, 7, 7, 7, 33, 36, 7, 55,
+ 33, 55, 7, 7, 36, 36, 17, 7, 7, 34,
+ 8, 7, 7, 7, 36, 5, 7, 33, 20, 55,
+ 66, 5, 29, 33, 66, 33, 29, 33, 29, 7,
+ 60, 60, 29, 7, 55, 61, 7, 5, 1, 79,
+ 60, 33, 7, 36, 33, 60, 8, 7, 36, 36,
+ 33, 37, 29, 2, 36, 36, 8, 33, 8, 1,
+ 33, 1, 37, 33, 8, 2, 7, -1, -1, 36,
+ -1, -1, 36, 1, -1, 60, 55, 0, -1, 33,
+ 60, 7, 2, 55, 8, 36, 2, 48, 17, 16,
+ 33, 60, 7, 48, 60, 48, 8, 36, 36, 8,
+ 36, 60, 36, 61, 60, 36, 36, 15, 8, 55,
+ 7, 8, 8, 8, 61, 60, 48, 8, 6, 40,
+ 77, 8, 40, 40, 8, -1, 34, 60, -1, 8,
+ 51, 79, 20, 51, 51, 40, 61, 62, 42, 61,
+ 62, 8, 61, 62, 79, 8, 51, 56, 60, 53,
+ 61, 62, 50, 15, 61, 62, 54, 15, 61, 62,
+ 60, 15, 61, 62, 60, 60, 24, 61, 62, 60,
+ 24, 15, 34, 60, 8, 61, 62, 61, 8, 93,
+ 94, 60, 31, 93, 94, 61, 62, 61, 62, 56,
+ 34, 50, 8, 56, 29, 54, 10, 8, 25, 7,
+ 27, 61, 62, 15, -1, 7, 7, -1, -1, 29,
+ 29, 38, 12, 61, 62, 7, 25, -1, 27, 29,
+ 8, 55, 34, -1, 36, 29, 56, 12, -1, 38,
+ 90, 33, 25, -1, 27, 25, 25, 27, 27, 12,
+ 75, 55, 29, -1, 60, 38, -1, 95, 38, 38,
+ 61, 62, 87, 61, 62, 75, 75, 57, 8, 8,
+ 61, 62, 25, 63, 27, 75, -1, 87, 87, 61,
+ 62, 75, 57, 61, 62, 38, 15, 87, 63, 25,
+ 15, 27, 29, 87, 57, 25, -1, 27, 75, 25,
+ 63, 27, 38, 36, 96, 34, -1, 36, 38, 34,
+ 87, 36, 38, 25, 25, 27, 27, 56, 25, -1,
+ 27, 61, 62, 25, 15, 27, 38, 38, 61, 62,
+ -1, 38, 18, 19, 18, 19, 38, 47, 75, 18,
+ 19, -1, 33, 34, -1, 36, 18, 19, -1, -1,
+ 87, 61, 62, -1, -1, -1, -1, 15, -1, 45,
+ 46, 45, 46, -1, -1, 29, 45, 46, -1, 15,
+ 23, 24, -1, 45, 46, 33, 34, -1, 36, 32,
+ -1, -1, 35, -1, 37, 95, -1, -1, 34, -1,
+ 36, 100, 101, 102, 103, 104, 105, 23, 24, -1,
+ -1, -1, 66, 67, 68, 31, 32, 23, 24, 35,
+ -1, 37, -1, -1, -1, 31, 32, 23, 24, 35,
+ 29, 37, -1, -1, -1, 31, 32, 23, 24, 35,
+ 29, 37, 96, 97, 98, 31, 32, 23, 24, 35,
+ 29, 37, -1, -1, 29, 31, 32, 29, -1, 35,
+ -1, 37, -1, 29, -1, -1, 29, 66, 67, 68,
+ -1, -1, 23, 24, 29, -1, -1, 66, 67, 68,
+ -1, 32, -1, -1, 35, -1, 37, 66, 67, 68,
+ -1, 66, 67, 68, 66, 67, 68, 96, 97, 98,
+ 66, 67, 68, 66, 67, 68, -1, 96, 97, 98,
+ -1, 66, 67, 68, -1, -1, -1, 96, 97, 98,
+ -1, 96, 97, 98, 96, 97, 98, -1, -1, -1,
+ 96, 97, 98, 96, 97, 98, 15, 29, -1, 15,
+ 29, 96, 97, 98, 36, 29, -1, 36, -1, -1,
+ 29, -1, 36, 29, -1, -1, -1, 29, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 66, 67, 68, 66, 67, 68,
+ -1, -1, 66, 67, 68, -1, -1, 66, 67, 68,
+ 66, 67, 68, -1, 66, 67, 68, -1, -1, -1,
+ 29, -1, -1, -1, 96, 97, 98, 96, 97, 98,
+ 29, -1, 96, 97, 98, -1, -1, 96, 97, 98,
+ 96, 97, 98, 29, 96, 97, 98, -1, -1, -1,
+ -1, -1, 61, 62, -1, -1, 15, 66, 67, 68,
+ -1, -1, 61, 62, -1, -1, -1, 66, 67, 68,
+ 29, -1, -1, -1, -1, 61, 62, -1, -1, -1,
+ 66, 67, 68, 29, -1, -1, 29, 96, 97, 98,
+ -1, -1, -1, -1, -1, -1, -1, 96, 97, 98,
+ -1, -1, -1, -1, -1, -1, -1, 66, 67, 68,
+ 96, 97, 98, -1, -1, 61, 62, -1, 61, 62,
+ 66, 67, 68, 66, 67, 68, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3, -1, -1, 96, 97, 98,
+ -1, -1, -1, -1, 13, -1, -1, -1, 17, 29,
+ 96, 97, 98, 96, 97, 98, -1, 26, -1, 28,
+ -1, -1, 31, -1, -1, -1, -1, -1, -1, -1,
+ 39, -1, 41, 42, -1, -1, -1, -1, -1, -1,
+ 49, 61, 62, 52, 53, -1, 66, 67, 68, 58,
+ -1, -1, -1, -1, -1, 64, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 80, -1, -1, -1, -1, 96, 97, 98, -1,
+ -1, -1, -1, -1, -1, -1, 12, 13, 3, -1,
+ -1, -1, -1, -1, -1, -1, 22, -1, 13, -1,
+ -1, -1, 17, 29, -1, -1, -1, 33, 34, -1,
+ 36, 26, -1, 28, -1, -1, -1, 43, -1, -1,
+ -1, 47, -1, -1, 39, -1, 41, 42, -1, -1,
+ -1, -1, -1, -1, 49, -1, -1, 52, 53, 65,
+ 66, 67, 68, 58, 70, -1, -1, -1, -1, 64,
+ -1, -1, -1, -1, -1, 81, 82, 83, -1, -1,
+ -1, -1, 88, -1, -1, 80, -1, -1, -1, -1,
+ 96, 97, 98, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 12, 13, -1, -1, -1, -1, -1,
+ -1, -1, -1, 22, -1, -1, -1, -1, -1, -1,
+ 29, -1, -1, -1, 33, 34, -1, 36, -1, -1,
+ -1, -1, -1, -1, 43, -1, -1, -1, 47, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 65, 66, 67, 68,
+ -1, 70, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 81, 82, 83, -1, -1, -1, -1, 88,
+ -1, -1, -1, -1, -1, -1, -1, 96, 97, 98,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 12,
+ 13, -1, -1, -1, -1, -1, -1, -1, -1, 22,
+ -1, -1, -1, -1, -1, -1, 29, -1, -1, -1,
+ 33, 34, -1, 36, -1, -1, -1, -1, -1, -1,
+ 43, -1, -1, -1, 47, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 65, 66, 67, 68, -1, 70, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 81, 82,
+ 83, -1, -1, -1, -1, 88, -1, -1, -1, -1,
+ -1, -1, -1, 96, 97, 98, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 10, -1, 12, 13, -1,
+ -1, -1, -1, -1, -1, -1, -1, 22, -1, -1,
+ -1, -1, -1, -1, 29, -1, -1, -1, 33, 34,
+ -1, 36, -1, -1, -1, -1, -1, -1, 43, -1,
+ -1, -1, 47, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 65, 66, 67, 68, -1, 70, -1, -1, -1, -1,
+ 75, -1, -1, -1, -1, -1, 81, 82, 83, 84,
+ 85, -1, -1, 88, -1, -1, 91, -1, -1, -1,
+ -1, 96, 97, 98, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 10, -1, 12, 13, -1, -1, -1,
+ -1, -1, -1, -1, -1, 22, -1, -1, -1, -1,
+ -1, -1, 29, -1, -1, -1, 33, 34, -1, 36,
+ -1, -1, -1, -1, -1, -1, 43, -1, -1, -1,
+ 47, -1, -1, -1, -1, -1, -1, -1, 55, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 65, 66,
+ 67, 68, -1, 70, -1, -1, -1, -1, 75, -1,
+ -1, -1, -1, -1, 81, 82, 83, 84, 85, -1,
+ -1, 88, -1, -1, 91, -1, -1, -1, -1, 96,
+ 97, 98, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 10, -1, 12, 13, -1, -1, -1, -1, -1,
+ -1, -1, -1, 22, -1, -1, -1, -1, -1, -1,
+ 29, -1, -1, -1, 33, 34, -1, 36, -1, -1,
+ -1, -1, -1, -1, 43, -1, -1, -1, 47, -1,
+ -1, -1, -1, -1, -1, -1, 55, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 65, 66, 67, 68,
+ -1, 70, -1, -1, -1, -1, 75, -1, -1, -1,
+ -1, -1, 81, 82, 83, 84, 85, -1, -1, 88,
+ -1, -1, 91, -1, -1, -1, -1, 96, 97, 98,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 11,
+ 12, 13, -1, -1, -1, -1, -1, -1, -1, -1,
+ 22, -1, -1, -1, -1, -1, -1, 29, -1, -1,
+ -1, 33, 34, -1, 36, -1, -1, -1, 40, -1,
+ 42, 43, 44, -1, -1, 47, -1, -1, -1, 51,
+ -1, 53, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 65, 66, 67, 68, -1, 70, -1,
+ 72, -1, 74, -1, 76, -1, -1, -1, -1, 81,
+ 82, 83, -1, -1, -1, -1, 88, -1, -1, -1,
+ -1, -1, -1, -1, 96, 97, 98, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 7, -1, -1, -1,
+ 11, 12, 13, -1, -1, -1, -1, -1, -1, -1,
+ -1, 22, -1, -1, -1, -1, -1, -1, 29, -1,
+ -1, -1, 33, 34, -1, 36, -1, -1, -1, 40,
+ -1, 42, 43, 44, -1, -1, 47, -1, -1, -1,
+ 51, -1, 53, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 65, 66, 67, 68, -1, 70,
+ -1, 72, -1, 74, -1, 76, -1, -1, -1, -1,
+ 81, 82, 83, -1, -1, -1, -1, 88, -1, -1,
+ -1, -1, -1, -1, -1, 96, 97, 98, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 11, 12, 13,
+ -1, -1, -1, -1, -1, -1, -1, -1, 22, -1,
+ -1, -1, -1, -1, -1, 29, -1, -1, -1, 33,
+ 34, -1, 36, -1, -1, -1, 40, -1, 42, 43,
+ 44, -1, -1, 47, -1, -1, -1, 51, -1, 53,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 65, 66, 67, 68, -1, 70, -1, 72, -1,
+ 74, 75, 76, -1, -1, -1, -1, 81, 82, 83,
+ -1, -1, -1, -1, 88, -1, -1, -1, -1, -1,
+ -1, -1, 96, 97, 98, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 8, -1, -1, 11, 12, 13,
+ -1, -1, -1, -1, -1, -1, -1, -1, 22, -1,
+ -1, -1, -1, -1, -1, 29, -1, -1, -1, 33,
+ 34, -1, 36, -1, -1, -1, 40, -1, 42, 43,
+ 44, -1, -1, 47, -1, -1, -1, 51, -1, 53,
+ -1, -1, 56, -1, -1, -1, -1, -1, -1, -1,
+ -1, 65, 66, 67, 68, -1, 70, -1, 72, -1,
+ 74, -1, 76, -1, -1, -1, -1, 81, 82, 83,
+ -1, -1, -1, -1, 88, -1, -1, -1, -1, -1,
+ -1, -1, 96, 97, 98, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 8, -1, -1, 11, 12, 13,
+ -1, -1, -1, -1, -1, -1, -1, -1, 22, -1,
+ -1, -1, -1, -1, -1, 29, -1, -1, -1, 33,
+ 34, -1, 36, -1, -1, -1, 40, -1, 42, 43,
+ 44, -1, -1, 47, -1, -1, -1, 51, -1, 53,
+ -1, -1, 56, -1, -1, -1, -1, -1, -1, -1,
+ -1, 65, 66, 67, 68, -1, 70, -1, 72, -1,
+ 74, -1, 76, -1, -1, -1, -1, 81, 82, 83,
+ -1, -1, -1, -1, 88, -1, -1, -1, -1, -1,
+ -1, -1, 96, 97, 98, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 8, -1, -1, 11, 12, 13,
+ -1, -1, -1, -1, -1, -1, -1, -1, 22, -1,
+ -1, -1, -1, -1, -1, 29, -1, -1, -1, 33,
+ 34, -1, 36, -1, -1, -1, 40, -1, 42, 43,
+ 44, -1, -1, 47, -1, -1, -1, 51, -1, 53,
+ -1, -1, 56, -1, -1, -1, -1, -1, -1, -1,
+ -1, 65, 66, 67, 68, -1, 70, -1, 72, -1,
+ 74, -1, 76, -1, -1, -1, -1, 81, 82, 83,
+ -1, -1, -1, -1, 88, -1, -1, -1, -1, -1,
+ -1, -1, 96, 97, 98, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 8, -1, -1, 11, 12, 13,
+ -1, -1, -1, -1, -1, -1, -1, -1, 22, -1,
+ -1, -1, -1, -1, -1, 29, -1, -1, -1, 33,
+ 34, -1, 36, -1, -1, -1, 40, -1, 42, 43,
+ 44, -1, -1, 47, -1, -1, -1, 51, -1, 53,
+ -1, -1, 56, -1, -1, -1, -1, -1, -1, -1,
+ -1, 65, 66, 67, 68, -1, 70, -1, 72, -1,
+ 74, -1, 76, -1, -1, -1, -1, 81, 82, 83,
+ -1, -1, -1, -1, 88, -1, -1, -1, -1, -1,
+ -1, -1, 96, 97, 98, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 11, 12, 13, -1, -1, -1,
+ -1, -1, -1, -1, -1, 22, -1, -1, -1, -1,
+ -1, -1, 29, 30, -1, -1, 33, 34, -1, 36,
+ -1, -1, -1, 40, -1, 42, 43, 44, -1, -1,
+ 47, -1, -1, -1, 51, -1, 53, -1, -1, -1,
+ -1, -1, -1, -1, 61, -1, -1, -1, 65, 66,
+ 67, 68, 69, 70, -1, 72, 73, 74, -1, 76,
+ -1, 78, -1, -1, 81, 82, 83, -1, -1, -1,
+ -1, 88, -1, -1, -1, -1, -1, -1, -1, 96,
+ 97, 98, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 11, 12, 13, -1, -1, -1, -1, -1, -1,
+ -1, -1, 22, -1, -1, -1, -1, -1, -1, 29,
+ 30, -1, -1, 33, 34, -1, 36, -1, -1, -1,
+ 40, -1, 42, 43, 44, -1, -1, 47, -1, -1,
+ -1, 51, -1, 53, -1, -1, -1, -1, -1, -1,
+ -1, 61, -1, -1, -1, 65, 66, 67, 68, 69,
+ 70, -1, 72, 73, 74, -1, 76, -1, 78, -1,
+ -1, 81, 82, 83, -1, -1, -1, -1, 88, -1,
+ -1, -1, -1, -1, -1, -1, 96, 97, 98, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 11, 12,
+ 13, -1, -1, -1, -1, -1, -1, -1, -1, 22,
+ -1, -1, -1, -1, -1, -1, 29, 30, -1, -1,
+ 33, 34, -1, 36, -1, -1, -1, 40, -1, 42,
+ 43, 44, -1, -1, 47, -1, -1, -1, 51, -1,
+ 53, -1, -1, -1, -1, -1, -1, -1, 61, -1,
+ -1, -1, 65, 66, 67, 68, 69, 70, -1, 72,
+ 73, 74, -1, 76, -1, 78, -1, -1, 81, 82,
+ 83, -1, -1, -1, -1, 88, -1, -1, -1, -1,
+ -1, -1, -1, 96, 97, 98, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4, 5, 6, -1, -1,
+ 9, 10, 11, -1, -1, 14, -1, 16, -1, -1,
+ -1, 20, 21, 22, -1, -1, -1, -1, -1, -1,
+ 29, 30, 31, 32, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 43, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 59, -1, -1, -1, -1, -1, -1, 66, 67, 68,
+ 69, 70, 71, -1, 73, 74, 75, 76, 77, 78,
+ -1, -1, 81, 82, 83, 84, 85, 86, 87, -1,
+ -1, -1, 91, -1, -1, -1, -1, 96, 97, 98,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 4,
+ 5, 6, -1, -1, 9, 10, 11, -1, -1, 14,
+ -1, 16, -1, -1, -1, 20, 21, 22, -1, -1,
+ -1, -1, -1, -1, 29, 30, 31, 32, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 43, -1,
+ -1, -1, 47, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 59, -1, -1, -1, -1, -1,
+ 65, 66, 67, 68, 69, 70, 71, -1, 73, 74,
+ 75, 76, 77, 78, -1, -1, 81, 82, 83, 84,
+ 85, 86, 87, -1, -1, -1, 91, -1, -1, -1,
+ -1, 96, 97, 98, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4, 5, 6, -1, -1, 9, 10,
+ 11, -1, -1, 14, -1, 16, -1, -1, -1, 20,
+ 21, 22, -1, -1, -1, -1, -1, -1, 29, 30,
+ 31, 32, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 43, -1, -1, -1, 47, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 59, -1,
+ -1, -1, -1, -1, 65, 66, 67, 68, 69, 70,
+ 71, -1, 73, 74, 75, 76, 77, 78, -1, -1,
+ 81, 82, 83, 84, 85, 86, 87, -1, -1, -1,
+ 91, -1, -1, -1, -1, 96, 97, 98, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4, 5, 6,
+ -1, -1, 9, 10, 11, -1, -1, 14, -1, 16,
+ -1, -1, -1, 20, 21, 22, -1, -1, -1, -1,
+ -1, -1, 29, 30, 31, 32, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 43, -1, -1, -1,
+ 47, -1, -1, -1, -1, -1, -1, -1, 55, -1,
+ -1, -1, 59, -1, -1, -1, -1, -1, 65, 66,
+ 67, 68, 69, 70, 71, -1, 73, 74, 75, 76,
+ 77, 78, -1, -1, 81, 82, 83, 84, 85, 86,
+ 87, -1, -1, -1, 91, -1, -1, -1, -1, 96,
+ 97, 98, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4, -1, -1, -1, -1, 9, -1, 11, 12,
+ 13, 14, -1, -1, -1, -1, -1, -1, 21, 22,
+ -1, -1, -1, -1, -1, -1, 29, 30, -1, -1,
+ 33, 34, -1, 36, -1, -1, -1, 40, -1, 42,
+ 43, 44, -1, -1, 47, -1, -1, -1, 51, -1,
+ 53, -1, -1, -1, -1, -1, 59, -1, 61, -1,
+ -1, -1, 65, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78, -1, -1, 81, 82,
+ 83, 84, 85, 86, -1, 88, -1, -1, -1, -1,
+ -1, -1, -1, 96, 97, 98, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4, -1, -1, -1, -1,
+ 9, -1, 11, 12, 13, 14, -1, -1, -1, -1,
+ -1, -1, 21, 22, -1, -1, -1, -1, -1, -1,
+ 29, 30, -1, -1, 33, 34, -1, 36, -1, -1,
+ -1, 40, -1, 42, 43, 44, -1, -1, 47, -1,
+ -1, -1, 51, -1, 53, -1, -1, -1, -1, -1,
+ 59, -1, 61, -1, -1, -1, 65, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ -1, -1, 81, 82, 83, 84, 85, 86, -1, 88,
+ -1, -1, -1, -1, -1, -1, -1, 96, 97, 98,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 4,
+ 5, 6, -1, -1, 9, 10, 11, 12, 13, 14,
+ -1, 16, -1, -1, -1, 20, 21, 22, -1, -1,
+ -1, -1, -1, -1, 29, 30, 31, 32, 33, 34,
+ -1, 36, -1, -1, -1, 40, -1, 42, 43, 44,
+ -1, -1, 47, -1, -1, -1, 51, -1, 53, -1,
+ -1, -1, -1, -1, 59, -1, 61, -1, -1, -1,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, -1, -1, 81, 82, 83, 84,
+ 85, 86, 87, 88, -1, -1, 91, -1, -1, -1,
+ -1, 96, 97, 98, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4, 5, 6, -1, -1, 9, 10,
+ 11, 12, 13, 14, -1, 16, -1, -1, -1, 20,
+ 21, 22, -1, -1, -1, -1, -1, -1, 29, 30,
+ 31, 32, 33, 34, -1, 36, -1, -1, -1, 40,
+ -1, 42, 43, 44, -1, -1, 47, -1, -1, -1,
+ 51, -1, 53, -1, 55, -1, -1, -1, 59, -1,
+ 61, -1, -1, -1, 65, 66, 67, 68, 69, 70,
+ 71, 72, 73, 74, 75, 76, 77, 78, -1, -1,
+ 81, 82, 83, 84, 85, 86, 87, 88, -1, -1,
+ 91, -1, -1, -1, -1, 96, 97, 98, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
- 77, 14, 18, 18, 18, 32, 18, 3, 32, 42,
- 9, 3, 3, 18, 42, 3, 18, 18, 3, 22,
- 18, 32, 32, 18, 18, 25, 32, 3, 18, 18,
- 3, 18, 3, 42, 18, 14, 22, 18, 18, 22,
- 22, 18, 100, 18, 18, 42, 18, 3, 105, 42,
- 3, 3, 18, 14, 32, 18, 3, 25, 25, 18,
- 3, 25, 3, 18, 18, 3, 103, 18, 18, 2,
- -1, 3, 42, 42, 18, 14, 25, 42, 14, 2,
- 42, -1, 42, 18, 42, 18, 2, 4, -1, -1,
- 18, -1, -1, 18, -1, 18, -1, 54, -1, 56,
- 44, 18, 18, 18, 18, -1, 54, -1, 54, 54,
- 56, 56, 51, 42, 54, 51, 56, 54, 46, 56,
- 45, 50, 70, 54, 54, 56, 56, 3, 54, 42,
- 45, 18, 46, 59, 54, 54, 54, 50, 2, 59,
- 59, 59, 54, 54, 11, 12, 78, 59, 59, 54,
- 54, 56, 56, 54, 18, 2, 14, 18, 4, 54,
- 54, 56, 56, 54, 54, 23, 3, 68, 58, 60,
- 54, 18, 18, 14, 109, 2, 60, 2, 19, 54,
- 54, 54, 43, 38, 59, 59, 59, 42, 54, 54,
- 56, 18, 54, 18, 59, 54, 2, 59, 54, 58,
- 54, 2, 58, 18, 54, 59, 2, 94, 2, 54,
- 18, 4, 18, 2, 18, 3, 66, 18, 18, 64,
- 3, 54, 18, 56, 18, 18, 54, 2, 56, 18,
- 45, 54, 18, 56, 54, 14, 14, 57, 2, 47,
- 19, 78, 46, 18, 44, 54, 2, 18, 57, 54,
- 2, 54, 2, 56, 18, 60, 54, 54, 56, 56,
- 14, -1, 18, 54, 54, 19, 18, -1, 18, 60,
- 54, 18, 62, 51, 45, 59, -1, 54, -1, -1,
- 54, 54, 59, 67, 54, 59, 59, 54, 2, 59,
- 78, -1, 59, 63, 61, 78, 69, 71, -1, 76,
- 47, 48, -1, 54, 18, 54, 92, -1, 59, 54,
- 59, 54, 61, 54, 59, -1, 59, 54, 59, 54,
- 65, -1, 59, 54, 59, 76, 61, -1, 59, 14,
- 61, 14, 2, 76, 19, 76, 21, 5, 88, 76,
- 23, -1, -1, -1, -1, -1, 14, -1, 18, -1,
- -1, -1, 35, 36, -1, 23, -1, 42, 25, 26,
- 27, 28, 29, 30, 31, -1, 14, 35, 36, -1,
- -1, -1, -1, -1, 88, 23, 24, 25, 26, 27,
- 28, 29, 30, 31, 14, -1, -1, -1, -1, -1,
- -1, -1, -1, 23, 24, 25, 26, 27, 28, 29,
- 30, 31, 14, -1, -1, -1, -1, -1, -1, -1,
- -1, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5, -1, -1, -1, -1, -1, -1, -1, -1,
- 14, -1, -1, -1, -1, -1, -1, -1, -1, 23,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 35, 36, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1};
+ 3, 43, 32, 18, 32, 9, 18, 18, 78, 18,
+ 18, 3, 18, 18, 32, 25, 18, 3, 3, 43,
+ 18, 3, 3, 22, 18, 18, 22, 18, 18, 3,
+ 18, 32, 32, 22, 14, 22, 14, 3, 3, 18,
+ 3, 25, 106, 18, 3, 3, 43, 18, 43, 25,
+ 3, 18, 25, 3, 104, 3, 101, 18, 3, 3,
+ 43, 25, 18, 18, 18, 14, 43, 18, 2, -1,
+ 3, 43, 32, 43, 43, 43, 18, 18, 18, 18,
+ 2, 43, 18, 18, 18, 14, 2, 18, 3, -1,
+ 18, 2, 4, 18, 14, 14, 18, -1, 55, 19,
+ 57, -1, 18, 55, 23, 57, 18, 18, 55, 3,
+ 57, 47, 55, 18, 57, 46, 44, 55, 55, 57,
+ 57, 46, 43, 52, 2, 55, 18, 57, 55, 55,
+ 51, 55, 55, 60, 60, 4, 60, 55, 55, 57,
+ 18, 55, 47, 60, 14, 55, 79, 55, 71, 18,
+ 60, 55, 60, 57, 55, 69, 57, 43, 55, 39,
+ 57, 14, 55, 43, 79, 51, 19, 60, 55, 2,
+ 14, 55, 55, 60, 55, 110, 60, 60, 18, 60,
+ 55, 2, 52, 55, 59, 18, 3, 59, 55, 55,
+ 55, 57, 59, 2, 55, 60, 3, 18, 18, 4,
+ 55, 2, 18, 95, 2, 45, 67, 2, 52, 18,
+ 65, 2, 18, 18, 2, 18, 55, 18, 11, 12,
+ 18, 2, 61, 18, 55, 2, 57, 18, 48, 18,
+ 18, 47, 55, 55, 57, 57, 55, 18, 18, 58,
+ 46, 18, 55, 46, 55, 58, -1, 55, 2, 57,
+ 14, 55, 63, 55, -1, 19, 45, 61, 55, 61,
+ 57, 55, 79, 55, 18, 57, 2, 61, 55, 55,
+ 55, -1, 79, 60, 60, 60, 55, 62, 64, 55,
+ 55, 60, 18, 62, 60, 60, 62, 62, 55, 55,
+ 77, 18, 55, 60, 60, 2, 55, 60, 55, 55,
+ 66, 60, 55, 60, 60, 68, 14, 60, -1, 55,
+ 77, 18, -1, 93, 60, 23, 72, 70, 77, 2,
+ 77, 48, 49, -1, -1, 14, -1, 35, 36, 5,
+ 19, 77, 21, -1, -1, 18, -1, -1, 14, 25,
+ 26, 27, 28, 29, 30, 31, -1, 23, -1, -1,
+ -1, -1, 14, 89, 43, -1, -1, -1, -1, 35,
+ 36, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ -1, -1, -1, -1, 14, -1, -1, -1, -1, -1,
+ -1, -1, 89, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 14, -1, -1, -1, -1, -1, -1, -1,
+ -1, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 5,
+ -1, -1, -1, -1, -1, -1, -1, -1, 14, -1,
+ -1, -1, -1, -1, -1, -1, -1, 23, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 35,
+ 36, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1
+};
QT_END_NAMESPACE
diff --git a/src/qml/parser/qqmljsgrammar_p.h b/src/qml/parser/qqmljsgrammar_p.h
index 050ef6c288..aa8450f218 100644
--- a/src/qml/parser/qqmljsgrammar_p.h
+++ b/src/qml/parser/qqmljsgrammar_p.h
@@ -59,152 +59,154 @@ QT_BEGIN_NAMESPACE
class QQmlJSGrammar
{
public:
- enum VariousConstants {
- EOF_SYMBOL = 0,
- REDUCE_HERE = 105,
- SHIFT_THERE = 104,
- T_AND = 1,
- T_AND_AND = 2,
- T_AND_EQ = 3,
- T_AS = 93,
- T_AUTOMATIC_SEMICOLON = 62,
- T_BREAK = 4,
- T_CASE = 5,
- T_CATCH = 6,
- T_COLON = 7,
- T_COMMA = 8,
- T_COMMENT = 88,
- T_COMPATIBILITY_SEMICOLON = 89,
- T_CONST = 84,
- T_CONTINUE = 9,
- T_DEBUGGER = 85,
- T_DEFAULT = 10,
- T_DELETE = 11,
- T_DIVIDE_ = 12,
- T_DIVIDE_EQ = 13,
- T_DO = 14,
- T_DOT = 15,
- T_ELSE = 16,
- T_EQ = 17,
- T_EQ_EQ = 18,
- T_EQ_EQ_EQ = 19,
- T_ERROR = 97,
- T_FALSE = 83,
- T_FEED_JS_EXPRESSION = 101,
- T_FEED_JS_PROGRAM = 103,
- T_FEED_JS_SOURCE_ELEMENT = 102,
- T_FEED_JS_STATEMENT = 100,
- T_FEED_UI_OBJECT_MEMBER = 99,
- T_FEED_UI_PROGRAM = 98,
- T_FINALLY = 20,
- T_FOR = 21,
- T_FUNCTION = 22,
- T_GE = 23,
- T_GET = 95,
- T_GT = 24,
- T_GT_GT = 25,
- T_GT_GT_EQ = 26,
- T_GT_GT_GT = 27,
- T_GT_GT_GT_EQ = 28,
- T_IDENTIFIER = 29,
- T_IF = 30,
- T_IMPORT = 91,
- T_IN = 31,
- T_INSTANCEOF = 32,
- T_LBRACE = 33,
- T_LBRACKET = 34,
- T_LE = 35,
- T_LPAREN = 36,
- T_LT = 37,
- T_LT_LT = 38,
- T_LT_LT_EQ = 39,
- T_MINUS = 40,
- T_MINUS_EQ = 41,
- T_MINUS_MINUS = 42,
- T_MULTILINE_STRING_LITERAL = 87,
- T_NEW = 43,
- T_NOT = 44,
- T_NOT_EQ = 45,
- T_NOT_EQ_EQ = 46,
- T_NULL = 81,
- T_NUMERIC_LITERAL = 47,
- T_ON = 94,
- T_OR = 48,
- T_OR_EQ = 49,
- T_OR_OR = 50,
- T_PLUS = 51,
- T_PLUS_EQ = 52,
- T_PLUS_PLUS = 53,
- T_PRAGMA = 92,
- T_PROPERTY = 66,
- T_PUBLIC = 90,
- T_QUESTION = 54,
- T_RBRACE = 55,
- T_RBRACKET = 56,
- T_READONLY = 68,
- T_REMAINDER = 57,
- T_REMAINDER_EQ = 58,
- T_RESERVED_WORD = 86,
- T_RETURN = 59,
- T_RPAREN = 60,
- T_SEMICOLON = 61,
- T_SET = 96,
- T_SIGNAL = 67,
- T_STAR = 63,
- T_STAR_EQ = 64,
- T_STRING_LITERAL = 65,
- T_SWITCH = 69,
- T_THIS = 70,
- T_THROW = 71,
- T_TILDE = 72,
- T_TRUE = 82,
- T_TRY = 73,
- T_TYPEOF = 74,
- T_VAR = 75,
- T_VOID = 76,
- T_WHILE = 77,
- T_WITH = 78,
- T_XOR = 79,
- T_XOR_EQ = 80,
-
- ACCEPT_STATE = 674,
- RULE_COUNT = 361,
- STATE_COUNT = 675,
- TERMINAL_COUNT = 106,
- NON_TERMINAL_COUNT = 111,
-
- GOTO_INDEX_OFFSET = 675,
- GOTO_INFO_OFFSET = 3078,
- GOTO_CHECK_OFFSET = 3078
- };
-
- static const char *const spell [];
- static const short lhs [];
- static const short rhs [];
- static const short goto_default [];
- static const short action_default [];
- static const short action_index [];
- static const short action_info [];
- static const short action_check [];
-
- static inline int nt_action (int state, int nt)
- {
- const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt;
- if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt)
- return goto_default [nt];
-
- return action_info [GOTO_INFO_OFFSET + yyn];
- }
-
- static inline int t_action (int state, int token)
- {
- const int yyn = action_index [state] + token;
-
- if (yyn < 0 || action_check [yyn] != token)
- return - action_default [state];
-
- return action_info [yyn];
- }
+ enum VariousConstants {
+ EOF_SYMBOL = 0,
+ REDUCE_HERE = 107,
+ SHIFT_THERE = 106,
+ T_AND = 1,
+ T_AND_AND = 2,
+ T_AND_EQ = 3,
+ T_AS = 95,
+ T_AUTOMATIC_SEMICOLON = 62,
+ T_BREAK = 4,
+ T_CASE = 5,
+ T_CATCH = 6,
+ T_COLON = 7,
+ T_COMMA = 8,
+ T_COMMENT = 89,
+ T_COMPATIBILITY_SEMICOLON = 90,
+ T_CONST = 84,
+ T_CONTINUE = 9,
+ T_DEBUGGER = 86,
+ T_DEFAULT = 10,
+ T_DELETE = 11,
+ T_DIVIDE_ = 12,
+ T_DIVIDE_EQ = 13,
+ T_DO = 14,
+ T_DOT = 15,
+ T_ELSE = 16,
+ T_ENUM = 91,
+ T_EQ = 17,
+ T_EQ_EQ = 18,
+ T_EQ_EQ_EQ = 19,
+ T_ERROR = 99,
+ T_FALSE = 83,
+ T_FEED_JS_EXPRESSION = 103,
+ T_FEED_JS_PROGRAM = 105,
+ T_FEED_JS_SOURCE_ELEMENT = 104,
+ T_FEED_JS_STATEMENT = 102,
+ T_FEED_UI_OBJECT_MEMBER = 101,
+ T_FEED_UI_PROGRAM = 100,
+ T_FINALLY = 20,
+ T_FOR = 21,
+ T_FUNCTION = 22,
+ T_GE = 23,
+ T_GET = 97,
+ T_GT = 24,
+ T_GT_GT = 25,
+ T_GT_GT_EQ = 26,
+ T_GT_GT_GT = 27,
+ T_GT_GT_GT_EQ = 28,
+ T_IDENTIFIER = 29,
+ T_IF = 30,
+ T_IMPORT = 93,
+ T_IN = 31,
+ T_INSTANCEOF = 32,
+ T_LBRACE = 33,
+ T_LBRACKET = 34,
+ T_LE = 35,
+ T_LET = 85,
+ T_LPAREN = 36,
+ T_LT = 37,
+ T_LT_LT = 38,
+ T_LT_LT_EQ = 39,
+ T_MINUS = 40,
+ T_MINUS_EQ = 41,
+ T_MINUS_MINUS = 42,
+ T_MULTILINE_STRING_LITERAL = 88,
+ T_NEW = 43,
+ T_NOT = 44,
+ T_NOT_EQ = 45,
+ T_NOT_EQ_EQ = 46,
+ T_NULL = 81,
+ T_NUMERIC_LITERAL = 47,
+ T_ON = 96,
+ T_OR = 48,
+ T_OR_EQ = 49,
+ T_OR_OR = 50,
+ T_PLUS = 51,
+ T_PLUS_EQ = 52,
+ T_PLUS_PLUS = 53,
+ T_PRAGMA = 94,
+ T_PROPERTY = 66,
+ T_PUBLIC = 92,
+ T_QUESTION = 54,
+ T_RBRACE = 55,
+ T_RBRACKET = 56,
+ T_READONLY = 68,
+ T_REMAINDER = 57,
+ T_REMAINDER_EQ = 58,
+ T_RESERVED_WORD = 87,
+ T_RETURN = 59,
+ T_RPAREN = 60,
+ T_SEMICOLON = 61,
+ T_SET = 98,
+ T_SIGNAL = 67,
+ T_STAR = 63,
+ T_STAR_EQ = 64,
+ T_STRING_LITERAL = 65,
+ T_SWITCH = 69,
+ T_THIS = 70,
+ T_THROW = 71,
+ T_TILDE = 72,
+ T_TRUE = 82,
+ T_TRY = 73,
+ T_TYPEOF = 74,
+ T_VAR = 75,
+ T_VOID = 76,
+ T_WHILE = 77,
+ T_WITH = 78,
+ T_XOR = 79,
+ T_XOR_EQ = 80,
+
+ ACCEPT_STATE = 687,
+ RULE_COUNT = 367,
+ STATE_COUNT = 688,
+ TERMINAL_COUNT = 108,
+ NON_TERMINAL_COUNT = 112,
+
+ GOTO_INDEX_OFFSET = 688,
+ GOTO_INFO_OFFSET = 3217,
+ GOTO_CHECK_OFFSET = 3217
+ };
+
+ static const char *const spell[];
+ static const short lhs[];
+ static const short rhs[];
+ static const short goto_default[];
+ static const short action_default[];
+ static const short action_index[];
+ static const short action_info[];
+ static const short action_check[];
+
+ static inline int nt_action (int state, int nt)
+ {
+ const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt;
+ if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt)
+ return goto_default [nt];
+
+ return action_info [GOTO_INFO_OFFSET + yyn];
+ }
+
+ static inline int t_action (int state, int token)
+ {
+ const int yyn = action_index [state] + token;
+
+ if (yyn < 0 || action_check [yyn] != token)
+ return - action_default [state];
+
+ return action_info [yyn];
+ }
};
diff --git a/src/qml/parser/qqmljskeywords_p.h b/src/qml/parser/qqmljskeywords_p.h
index 84ebe5f210..20daf545a9 100644
--- a/src/qml/parser/qqmljskeywords_p.h
+++ b/src/qml/parser/qqmljskeywords_p.h
@@ -106,6 +106,13 @@ static inline int classify3(const QChar *s, bool qmlMode) {
}
}
}
+ else if (s[0].unicode() == 'l') {
+ if (s[1].unicode() == 'e') {
+ if (s[2].unicode() == 't') {
+ return int(Lexer::T_LET);
+ }
+ }
+ }
else if (s[0].unicode() == 'n') {
if (s[1].unicode() == 'e') {
if (s[2].unicode() == 'w') {
@@ -174,7 +181,7 @@ static inline int classify4(const QChar *s, bool qmlMode) {
else if (s[1].unicode() == 'n') {
if (s[2].unicode() == 'u') {
if (s[3].unicode() == 'm') {
- return Lexer::T_ENUM;
+ return qmlMode ? int(Lexer::T_ENUM) : int(Lexer::T_RESERVED_WORD);
}
}
}
@@ -278,7 +285,7 @@ static inline int classify5(const QChar *s, bool qmlMode) {
if (s[2].unicode() == 'n') {
if (s[3].unicode() == 's') {
if (s[4].unicode() == 't') {
- return qmlMode ? int(Lexer::T_CONST) : int(Lexer::T_RESERVED_WORD);
+ return int(Lexer::T_CONST);
}
}
}
diff --git a/src/qml/parser/qqmljslexer_p.h b/src/qml/parser/qqmljslexer_p.h
index af5597b625..11d8081713 100644
--- a/src/qml/parser/qqmljslexer_p.h
+++ b/src/qml/parser/qqmljslexer_p.h
@@ -99,7 +99,6 @@ public:
T_CHAR = T_RESERVED_WORD,
T_CLASS = T_RESERVED_WORD,
T_DOUBLE = T_RESERVED_WORD,
- T_ENUM = T_RESERVED_WORD,
T_EXPORT = T_RESERVED_WORD,
T_EXTENDS = T_RESERVED_WORD,
T_FINAL = T_RESERVED_WORD,
diff --git a/src/qml/parser/qqmljsparser.cpp b/src/qml/parser/qqmljsparser.cpp
index 50518a92ee..3844fe4473 100644
--- a/src/qml/parser/qqmljsparser.cpp
+++ b/src/qml/parser/qqmljsparser.cpp
@@ -656,49 +656,71 @@ case 75: {
sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node);
} break;
-case 83: {
+case 76: {
+ AST::UiEnumDeclaration *enumDeclaration = new (pool) AST::UiEnumDeclaration(stringRef(2), sym(4).UiEnumMemberList->finish());
+ enumDeclaration->enumToken = loc(1);
+ enumDeclaration->rbraceToken = loc(5);
+ sym(1).Node = enumDeclaration;
+ break;
+}
+
+case 77: {
+ AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(stringRef(1));
+ node->memberToken = loc(1);
+ sym(1).Node = node;
+ break;
+}
+
+case 78: {
+ AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(sym(1).UiEnumMemberList, stringRef(3));
+ node->memberToken = loc(3);
+ sym(1).Node = node;
+ break;
+}
+
+case 86: {
AST::ThisExpression *node = new (pool) AST::ThisExpression();
node->thisToken = loc(1);
sym(1).Node = node;
} break;
-case 84: {
+case 87: {
AST::IdentifierExpression *node = new (pool) AST::IdentifierExpression(stringRef(1));
node->identifierToken = loc(1);
sym(1).Node = node;
} break;
-case 85: {
+case 88: {
AST::NullExpression *node = new (pool) AST::NullExpression();
node->nullToken = loc(1);
sym(1).Node = node;
} break;
-case 86: {
+case 89: {
AST::TrueLiteral *node = new (pool) AST::TrueLiteral();
node->trueToken = loc(1);
sym(1).Node = node;
} break;
-case 87: {
+case 90: {
AST::FalseLiteral *node = new (pool) AST::FalseLiteral();
node->falseToken = loc(1);
sym(1).Node = node;
} break;
-case 88: {
+case 91: {
AST::NumericLiteral *node = new (pool) AST::NumericLiteral(sym(1).dval);
node->literalToken = loc(1);
sym(1).Node = node;
} break;
-case 89:
-case 90: {
+case 92:
+case 93: {
AST::StringLiteral *node = new (pool) AST::StringLiteral(stringRef(1));
node->literalToken = loc(1);
sym(1).Node = node;
} break;
-case 91: {
+case 94: {
bool rx = lexer->scanRegExp(Lexer::NoPrefix);
if (!rx) {
diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
@@ -714,7 +736,7 @@ case 91: {
sym(1).Node = node;
} break;
-case 92: {
+case 95: {
bool rx = lexer->scanRegExp(Lexer::EqualPrefix);
if (!rx) {
diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
@@ -730,28 +752,28 @@ case 92: {
sym(1).Node = node;
} break;
-case 93: {
+case 96: {
AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral((AST::Elision *) 0);
node->lbracketToken = loc(1);
node->rbracketToken = loc(2);
sym(1).Node = node;
} break;
-case 94: {
+case 97: {
AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).Elision->finish());
node->lbracketToken = loc(1);
node->rbracketToken = loc(3);
sym(1).Node = node;
} break;
-case 95: {
+case 98: {
AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish ());
node->lbracketToken = loc(1);
node->rbracketToken = loc(3);
sym(1).Node = node;
} break;
-case 96: {
+case 99: {
AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (),
(AST::Elision *) 0);
node->lbracketToken = loc(1);
@@ -760,7 +782,7 @@ case 96: {
sym(1).Node = node;
} break;
-case 97: {
+case 100: {
AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (),
sym(4).Elision->finish());
node->lbracketToken = loc(1);
@@ -769,7 +791,7 @@ case 97: {
sym(1).Node = node;
} break;
-case 98: {
+case 101: {
AST::ObjectLiteral *node = 0;
if (sym(2).Node)
node = new (pool) AST::ObjectLiteral(
@@ -781,7 +803,7 @@ case 98: {
sym(1).Node = node;
} break;
-case 99: {
+case 102: {
AST::ObjectLiteral *node = new (pool) AST::ObjectLiteral(
sym(2).PropertyAssignmentList->finish ());
node->lbraceToken = loc(1);
@@ -789,14 +811,14 @@ case 99: {
sym(1).Node = node;
} break;
-case 100: {
+case 103: {
AST::NestedExpression *node = new (pool) AST::NestedExpression(sym(2).Expression);
node->lparenToken = loc(1);
node->rparenToken = loc(3);
sym(1).Node = node;
} break;
-case 101: {
+case 104: {
if (AST::ArrayMemberExpression *mem = AST::cast<AST::ArrayMemberExpression *>(sym(1).Expression)) {
diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken,
QLatin1String("Ignored annotation")));
@@ -816,48 +838,48 @@ case 101: {
}
} break;
-case 102: {
+case 105: {
sym(1).Node = new (pool) AST::ElementList((AST::Elision *) 0, sym(1).Expression);
} break;
-case 103: {
+case 106: {
sym(1).Node = new (pool) AST::ElementList(sym(1).Elision->finish(), sym(2).Expression);
} break;
-case 104: {
+case 107: {
AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList,
(AST::Elision *) 0, sym(3).Expression);
node->commaToken = loc(2);
sym(1).Node = node;
} break;
-case 105: {
+case 108: {
AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, sym(3).Elision->finish(),
sym(4).Expression);
node->commaToken = loc(2);
sym(1).Node = node;
} break;
-case 106: {
+case 109: {
AST::Elision *node = new (pool) AST::Elision();
node->commaToken = loc(1);
sym(1).Node = node;
} break;
-case 107: {
+case 110: {
AST::Elision *node = new (pool) AST::Elision(sym(1).Elision);
node->commaToken = loc(2);
sym(1).Node = node;
} break;
-case 108: {
+case 111: {
AST::PropertyNameAndValue *node = new (pool) AST::PropertyNameAndValue(
sym(1).PropertyName, sym(3).Expression);
node->colonToken = loc(2);
sym(1).Node = node;
} break;
-case 109: {
+case 112: {
AST::PropertyGetterSetter *node = new (pool) AST::PropertyGetterSetter(
sym(2).PropertyName, sym(6).FunctionBody);
node->getSetToken = loc(1);
@@ -868,7 +890,7 @@ case 109: {
sym(1).Node = node;
} break;
-case 110: {
+case 113: {
AST::PropertyGetterSetter *node = new (pool) AST::PropertyGetterSetter(
sym(2).PropertyName, sym(4).FormalParameterList, sym(7).FunctionBody);
node->getSetToken = loc(1);
@@ -879,56 +901,56 @@ case 110: {
sym(1).Node = node;
} break;
-case 111: {
+case 114: {
sym(1).Node = new (pool) AST::PropertyAssignmentList(sym(1).PropertyAssignment);
} break;
-case 112: {
+case 115: {
AST::PropertyAssignmentList *node = new (pool) AST::PropertyAssignmentList(
sym(1).PropertyAssignmentList, sym(3).PropertyAssignment);
node->commaToken = loc(2);
sym(1).Node = node;
} break;
-case 113: {
+case 116: {
AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1));
node->propertyNameToken = loc(1);
sym(1).Node = node;
} break;
-case 114: {
+case 117: {
AST::StringLiteralPropertyName *node = new (pool) AST::StringLiteralPropertyName(stringRef(1));
node->propertyNameToken = loc(1);
sym(1).Node = node;
} break;
-case 115: {
+case 118: {
AST::NumericLiteralPropertyName *node = new (pool) AST::NumericLiteralPropertyName(sym(1).dval);
node->propertyNameToken = loc(1);
sym(1).Node = node;
} break;
-case 116: {
+case 119: {
AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1));
node->propertyNameToken = loc(1);
sym(1).Node = node;
} break;
-case 152: {
+case 157: {
AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression);
node->lbracketToken = loc(2);
node->rbracketToken = loc(4);
sym(1).Node = node;
} break;
-case 153: {
+case 158: {
AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3));
node->dotToken = loc(2);
node->identifierToken = loc(3);
sym(1).Node = node;
} break;
-case 154: {
+case 159: {
AST::NewMemberExpression *node = new (pool) AST::NewMemberExpression(sym(2).Expression, sym(4).ArgumentList);
node->newToken = loc(1);
node->lparenToken = loc(3);
@@ -936,384 +958,384 @@ case 154: {
sym(1).Node = node;
} break;
-case 156: {
+case 161: {
AST::NewExpression *node = new (pool) AST::NewExpression(sym(2).Expression);
node->newToken = loc(1);
sym(1).Node = node;
} break;
-case 157: {
+case 162: {
AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList);
node->lparenToken = loc(2);
node->rparenToken = loc(4);
sym(1).Node = node;
} break;
-case 158: {
+case 163: {
AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList);
node->lparenToken = loc(2);
node->rparenToken = loc(4);
sym(1).Node = node;
} break;
-case 159: {
+case 164: {
AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression);
node->lbracketToken = loc(2);
node->rbracketToken = loc(4);
sym(1).Node = node;
} break;
-case 160: {
+case 165: {
AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3));
node->dotToken = loc(2);
node->identifierToken = loc(3);
sym(1).Node = node;
} break;
-case 161: {
+case 166: {
sym(1).Node = 0;
} break;
-case 162: {
+case 167: {
sym(1).Node = sym(1).ArgumentList->finish();
} break;
-case 163: {
+case 168: {
sym(1).Node = new (pool) AST::ArgumentList(sym(1).Expression);
} break;
-case 164: {
+case 169: {
AST::ArgumentList *node = new (pool) AST::ArgumentList(sym(1).ArgumentList, sym(3).Expression);
node->commaToken = loc(2);
sym(1).Node = node;
} break;
-case 168: {
+case 173: {
AST::PostIncrementExpression *node = new (pool) AST::PostIncrementExpression(sym(1).Expression);
node->incrementToken = loc(2);
sym(1).Node = node;
} break;
-case 169: {
+case 174: {
AST::PostDecrementExpression *node = new (pool) AST::PostDecrementExpression(sym(1).Expression);
node->decrementToken = loc(2);
sym(1).Node = node;
} break;
-case 171: {
+case 176: {
AST::DeleteExpression *node = new (pool) AST::DeleteExpression(sym(2).Expression);
node->deleteToken = loc(1);
sym(1).Node = node;
} break;
-case 172: {
+case 177: {
AST::VoidExpression *node = new (pool) AST::VoidExpression(sym(2).Expression);
node->voidToken = loc(1);
sym(1).Node = node;
} break;
-case 173: {
+case 178: {
AST::TypeOfExpression *node = new (pool) AST::TypeOfExpression(sym(2).Expression);
node->typeofToken = loc(1);
sym(1).Node = node;
} break;
-case 174: {
+case 179: {
AST::PreIncrementExpression *node = new (pool) AST::PreIncrementExpression(sym(2).Expression);
node->incrementToken = loc(1);
sym(1).Node = node;
} break;
-case 175: {
+case 180: {
AST::PreDecrementExpression *node = new (pool) AST::PreDecrementExpression(sym(2).Expression);
node->decrementToken = loc(1);
sym(1).Node = node;
} break;
-case 176: {
+case 181: {
AST::UnaryPlusExpression *node = new (pool) AST::UnaryPlusExpression(sym(2).Expression);
node->plusToken = loc(1);
sym(1).Node = node;
} break;
-case 177: {
+case 182: {
AST::UnaryMinusExpression *node = new (pool) AST::UnaryMinusExpression(sym(2).Expression);
node->minusToken = loc(1);
sym(1).Node = node;
} break;
-case 178: {
+case 183: {
AST::TildeExpression *node = new (pool) AST::TildeExpression(sym(2).Expression);
node->tildeToken = loc(1);
sym(1).Node = node;
} break;
-case 179: {
+case 184: {
AST::NotExpression *node = new (pool) AST::NotExpression(sym(2).Expression);
node->notToken = loc(1);
sym(1).Node = node;
} break;
-case 181: {
+case 186: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::Mul, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 182: {
+case 187: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::Div, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 183: {
+case 188: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::Mod, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 185: {
+case 190: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::Add, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 186: {
+case 191: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::Sub, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 188: {
+case 193: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::LShift, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 189: {
+case 194: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::RShift, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 190: {
+case 195: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::URShift, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 192: {
+case 197: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::Lt, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 193: {
+case 198: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::Gt, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 194: {
+case 199: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::Le, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 195: {
+case 200: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::Ge, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 196: {
+case 201: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::InstanceOf, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 197: {
+case 202: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::In, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 199: {
+case 204: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::Lt, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 200: {
+case 205: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::Gt, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 201: {
+case 206: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::Le, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 202: {
+case 207: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::Ge, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 203: {
+case 208: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::InstanceOf, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 205: {
+case 210: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::Equal, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 206: {
+case 211: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::NotEqual, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 207: {
+case 212: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::StrictEqual, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 208: {
+case 213: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::StrictNotEqual, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 210: {
+case 215: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::Equal, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 211: {
+case 216: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::NotEqual, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 212: {
+case 217: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::StrictEqual, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 213: {
+case 218: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::StrictNotEqual, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 215: {
+case 220: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::BitAnd, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 217: {
+case 222: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::BitAnd, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 219: {
+case 224: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::BitXor, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 221: {
+case 226: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::BitXor, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 223: {
+case 228: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::BitOr, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 225: {
+case 230: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::BitOr, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 227: {
+case 232: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::And, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 229: {
+case 234: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::And, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 231: {
+case 236: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::Or, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 233: {
+case 238: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
QSOperator::Or, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 235: {
+case 240: {
AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression,
sym(3).Expression, sym(5).Expression);
node->questionToken = loc(2);
@@ -1321,7 +1343,7 @@ case 235: {
sym(1).Node = node;
} break;
-case 237: {
+case 242: {
AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression,
sym(3).Expression, sym(5).Expression);
node->questionToken = loc(2);
@@ -1329,189 +1351,200 @@ case 237: {
sym(1).Node = node;
} break;
-case 239: {
+case 244: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
sym(2).ival, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 241: {
+case 246: {
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
sym(2).ival, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
} break;
-case 242: {
+case 247: {
sym(1).ival = QSOperator::Assign;
} break;
-case 243: {
+case 248: {
sym(1).ival = QSOperator::InplaceMul;
} break;
-case 244: {
+case 249: {
sym(1).ival = QSOperator::InplaceDiv;
} break;
-case 245: {
+case 250: {
sym(1).ival = QSOperator::InplaceMod;
} break;
-case 246: {
+case 251: {
sym(1).ival = QSOperator::InplaceAdd;
} break;
-case 247: {
+case 252: {
sym(1).ival = QSOperator::InplaceSub;
} break;
-case 248: {
+case 253: {
sym(1).ival = QSOperator::InplaceLeftShift;
} break;
-case 249: {
+case 254: {
sym(1).ival = QSOperator::InplaceRightShift;
} break;
-case 250: {
+case 255: {
sym(1).ival = QSOperator::InplaceURightShift;
} break;
-case 251: {
+case 256: {
sym(1).ival = QSOperator::InplaceAnd;
} break;
-case 252: {
+case 257: {
sym(1).ival = QSOperator::InplaceXor;
} break;
-case 253: {
+case 258: {
sym(1).ival = QSOperator::InplaceOr;
} break;
-case 255: {
+case 260: {
AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression);
node->commaToken = loc(2);
sym(1).Node = node;
} break;
-case 256: {
+case 261: {
sym(1).Node = 0;
} break;
-case 259: {
+case 264: {
AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression);
node->commaToken = loc(2);
sym(1).Node = node;
} break;
-case 260: {
+case 265: {
sym(1).Node = 0;
} break;
-case 277: {
+case 282: {
AST::Block *node = new (pool) AST::Block(sym(2).StatementList);
node->lbraceToken = loc(1);
node->rbraceToken = loc(3);
sym(1).Node = node;
} break;
-case 278: {
+case 283: {
sym(1).Node = new (pool) AST::StatementList(sym(1).Statement);
} break;
-case 279: {
+case 284: {
sym(1).Node = new (pool) AST::StatementList(sym(1).StatementList, sym(2).Statement);
} break;
-case 280: {
+case 285: {
sym(1).Node = 0;
} break;
-case 281: {
+case 286: {
sym(1).Node = sym(1).StatementList->finish ();
} break;
-case 283: {
- AST::VariableStatement *node = new (pool) AST::VariableStatement(
- sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST));
+case 288: {
+ AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope;
+ if (sym(1).ival == T_LET)
+ s = AST::VariableDeclaration::BlockScope;
+ else if (sym(1).ival == T_CONST)
+ s = AST::VariableDeclaration::ReadOnlyBlockScope;
+
+ AST::VariableStatement *node = new (pool) AST::VariableStatement(sym(2).VariableDeclarationList->finish(s));
node->declarationKindToken = loc(1);
node->semicolonToken = loc(3);
sym(1).Node = node;
} break;
-case 284: {
+case 289: {
+ sym(1).ival = T_LET;
+} break;
+
+case 290: {
sym(1).ival = T_CONST;
} break;
-case 285: {
+case 291: {
sym(1).ival = T_VAR;
} break;
-case 286: {
+case 292: {
sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration);
} break;
-case 287: {
+case 293: {
AST::VariableDeclarationList *node = new (pool) AST::VariableDeclarationList(
sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
node->commaToken = loc(2);
sym(1).Node = node;
} break;
-case 288: {
+case 294: {
sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration);
} break;
-case 289: {
+case 295: {
sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
} break;
-case 290: {
- AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression);
+case 296: {
+ AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope;
+ AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression, s);
node->identifierToken = loc(1);
sym(1).Node = node;
} break;
-case 291: {
- AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression);
+case 297: {
+ AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope;
+ AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression, s);
node->identifierToken = loc(1);
sym(1).Node = node;
} break;
-case 292: {
+case 298: {
// ### TODO: AST for initializer
sym(1) = sym(2);
} break;
-case 293: {
+case 299: {
sym(1).Node = 0;
} break;
-case 295: {
+case 301: {
// ### TODO: AST for initializer
sym(1) = sym(2);
} break;
-case 296: {
+case 302: {
sym(1).Node = 0;
} break;
-case 298: {
+case 304: {
AST::EmptyStatement *node = new (pool) AST::EmptyStatement();
node->semicolonToken = loc(1);
sym(1).Node = node;
} break;
-case 300: {
+case 306: {
AST::ExpressionStatement *node = new (pool) AST::ExpressionStatement(sym(1).Expression);
node->semicolonToken = loc(2);
sym(1).Node = node;
} break;
-case 301: {
+case 307: {
AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement, sym(7).Statement);
node->ifToken = loc(1);
node->lparenToken = loc(2);
@@ -1520,7 +1553,7 @@ case 301: {
sym(1).Node = node;
} break;
-case 302: {
+case 308: {
AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement);
node->ifToken = loc(1);
node->lparenToken = loc(2);
@@ -1528,7 +1561,7 @@ case 302: {
sym(1).Node = node;
} break;
-case 305: {
+case 311: {
AST::DoWhileStatement *node = new (pool) AST::DoWhileStatement(sym(2).Statement, sym(5).Expression);
node->doToken = loc(1);
node->whileToken = loc(3);
@@ -1538,7 +1571,7 @@ case 305: {
sym(1).Node = node;
} break;
-case 306: {
+case 312: {
AST::WhileStatement *node = new (pool) AST::WhileStatement(sym(3).Expression, sym(5).Statement);
node->whileToken = loc(1);
node->lparenToken = loc(2);
@@ -1546,7 +1579,7 @@ case 306: {
sym(1).Node = node;
} break;
-case 307: {
+case 313: {
AST::ForStatement *node = new (pool) AST::ForStatement(sym(3).Expression,
sym(5).Expression, sym(7).Expression, sym(9).Statement);
node->forToken = loc(1);
@@ -1557,9 +1590,10 @@ case 307: {
sym(1).Node = node;
} break;
-case 308: {
+case 314: {
+ AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope;
AST::LocalForStatement *node = new (pool) AST::LocalForStatement(
- sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression,
+ sym(4).VariableDeclarationList->finish(s), sym(6).Expression,
sym(8).Expression, sym(10).Statement);
node->forToken = loc(1);
node->lparenToken = loc(2);
@@ -1570,7 +1604,7 @@ case 308: {
sym(1).Node = node;
} break;
-case 309: {
+case 315: {
AST:: ForEachStatement *node = new (pool) AST::ForEachStatement(sym(3).Expression,
sym(5).Expression, sym(7).Statement);
node->forToken = loc(1);
@@ -1580,7 +1614,7 @@ case 309: {
sym(1).Node = node;
} break;
-case 310: {
+case 316: {
AST::LocalForEachStatement *node = new (pool) AST::LocalForEachStatement(
sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement);
node->forToken = loc(1);
@@ -1591,14 +1625,14 @@ case 310: {
sym(1).Node = node;
} break;
-case 312: {
+case 318: {
AST::ContinueStatement *node = new (pool) AST::ContinueStatement();
node->continueToken = loc(1);
node->semicolonToken = loc(2);
sym(1).Node = node;
} break;
-case 314: {
+case 320: {
AST::ContinueStatement *node = new (pool) AST::ContinueStatement(stringRef(2));
node->continueToken = loc(1);
node->identifierToken = loc(2);
@@ -1606,14 +1640,14 @@ case 314: {
sym(1).Node = node;
} break;
-case 316: {
+case 322: {
AST::BreakStatement *node = new (pool) AST::BreakStatement(QStringRef());
node->breakToken = loc(1);
node->semicolonToken = loc(2);
sym(1).Node = node;
} break;
-case 318: {
+case 324: {
AST::BreakStatement *node = new (pool) AST::BreakStatement(stringRef(2));
node->breakToken = loc(1);
node->identifierToken = loc(2);
@@ -1621,14 +1655,14 @@ case 318: {
sym(1).Node = node;
} break;
-case 320: {
+case 326: {
AST::ReturnStatement *node = new (pool) AST::ReturnStatement(sym(2).Expression);
node->returnToken = loc(1);
node->semicolonToken = loc(3);
sym(1).Node = node;
} break;
-case 321: {
+case 327: {
AST::WithStatement *node = new (pool) AST::WithStatement(sym(3).Expression, sym(5).Statement);
node->withToken = loc(1);
node->lparenToken = loc(2);
@@ -1636,7 +1670,7 @@ case 321: {
sym(1).Node = node;
} break;
-case 322: {
+case 328: {
AST::SwitchStatement *node = new (pool) AST::SwitchStatement(sym(3).Expression, sym(5).CaseBlock);
node->switchToken = loc(1);
node->lparenToken = loc(2);
@@ -1644,83 +1678,83 @@ case 322: {
sym(1).Node = node;
} break;
-case 323: {
+case 329: {
AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses);
node->lbraceToken = loc(1);
node->rbraceToken = loc(3);
sym(1).Node = node;
} break;
-case 324: {
+case 330: {
AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses);
node->lbraceToken = loc(1);
node->rbraceToken = loc(5);
sym(1).Node = node;
} break;
-case 325: {
+case 331: {
sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClause);
} break;
-case 326: {
+case 332: {
sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClauses, sym(2).CaseClause);
} break;
-case 327: {
+case 333: {
sym(1).Node = 0;
} break;
-case 328: {
+case 334: {
sym(1).Node = sym(1).CaseClauses->finish ();
} break;
-case 329: {
+case 335: {
AST::CaseClause *node = new (pool) AST::CaseClause(sym(2).Expression, sym(4).StatementList);
node->caseToken = loc(1);
node->colonToken = loc(3);
sym(1).Node = node;
} break;
-case 330: {
+case 336: {
AST::DefaultClause *node = new (pool) AST::DefaultClause(sym(3).StatementList);
node->defaultToken = loc(1);
node->colonToken = loc(2);
sym(1).Node = node;
} break;
-case 331: {
+case 337: {
AST::LabelledStatement *node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement);
node->identifierToken = loc(1);
node->colonToken = loc(2);
sym(1).Node = node;
} break;
-case 333: {
+case 339: {
AST::ThrowStatement *node = new (pool) AST::ThrowStatement(sym(2).Expression);
node->throwToken = loc(1);
node->semicolonToken = loc(3);
sym(1).Node = node;
} break;
-case 334: {
+case 340: {
AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch);
node->tryToken = loc(1);
sym(1).Node = node;
} break;
-case 335: {
+case 341: {
AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Finally);
node->tryToken = loc(1);
sym(1).Node = node;
} break;
-case 336: {
+case 342: {
AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch, sym(4).Finally);
node->tryToken = loc(1);
sym(1).Node = node;
} break;
-case 337: {
+case 343: {
AST::Catch *node = new (pool) AST::Catch(stringRef(3), sym(5).Block);
node->catchToken = loc(1);
node->lparenToken = loc(2);
@@ -1729,20 +1763,20 @@ case 337: {
sym(1).Node = node;
} break;
-case 338: {
+case 344: {
AST::Finally *node = new (pool) AST::Finally(sym(2).Block);
node->finallyToken = loc(1);
sym(1).Node = node;
} break;
-case 340: {
+case 346: {
AST::DebuggerStatement *node = new (pool) AST::DebuggerStatement();
node->debuggerToken = loc(1);
node->semicolonToken = loc(2);
sym(1).Node = node;
} break;
-case 342: {
+case 348: {
AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody);
node->functionToken = loc(1);
node->identifierToken = loc(2);
@@ -1753,7 +1787,7 @@ case 342: {
sym(1).Node = node;
} break;
-case 343: {
+case 349: {
AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody);
node->functionToken = loc(1);
if (! stringRef(2).isNull())
@@ -1765,7 +1799,7 @@ case 343: {
sym(1).Node = node;
} break;
-case 344: {
+case 350: {
AST::FunctionExpression *node = new (pool) AST::FunctionExpression(QStringRef(), sym(3).FormalParameterList, sym(6).FunctionBody);
node->functionToken = loc(1);
node->lparenToken = loc(2);
@@ -1775,56 +1809,56 @@ case 344: {
sym(1).Node = node;
} break;
-case 345: {
+case 351: {
AST::FormalParameterList *node = new (pool) AST::FormalParameterList(stringRef(1));
node->identifierToken = loc(1);
sym(1).Node = node;
} break;
-case 346: {
+case 352: {
AST::FormalParameterList *node = new (pool) AST::FormalParameterList(sym(1).FormalParameterList, stringRef(3));
node->commaToken = loc(2);
node->identifierToken = loc(3);
sym(1).Node = node;
} break;
-case 347: {
+case 353: {
sym(1).Node = 0;
} break;
-case 348: {
+case 354: {
sym(1).Node = sym(1).FormalParameterList->finish ();
} break;
-case 349: {
+case 355: {
sym(1).Node = 0;
} break;
-case 351: {
+case 357: {
sym(1).Node = new (pool) AST::FunctionBody(sym(1).SourceElements->finish ());
} break;
-case 353: {
+case 359: {
sym(1).Node = new (pool) AST::Program(sym(1).SourceElements->finish ());
} break;
-case 354: {
+case 360: {
sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElement);
} break;
-case 355: {
+case 361: {
sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElements, sym(2).SourceElement);
} break;
-case 356: {
+case 362: {
sym(1).Node = new (pool) AST::StatementSourceElement(sym(1).Statement);
} break;
-case 357: {
+case 363: {
sym(1).Node = new (pool) AST::FunctionSourceElement(sym(1).FunctionDeclaration);
} break;
-case 358: {
+case 364: {
sym(1).Node = 0;
} break;
diff --git a/src/qml/parser/qqmljsparser_p.h b/src/qml/parser/qqmljsparser_p.h
index f382cd7563..6273ed48b3 100644
--- a/src/qml/parser/qqmljsparser_p.h
+++ b/src/qml/parser/qqmljsparser_p.h
@@ -125,6 +125,7 @@ public:
AST::UiArrayMemberList *UiArrayMemberList;
AST::UiQualifiedId *UiQualifiedId;
AST::UiQualifiedPragmaId *UiQualifiedPragmaId;
+ AST::UiEnumMemberList *UiEnumMemberList;
};
public:
@@ -246,9 +247,9 @@ protected:
-#define J_SCRIPT_REGEXPLITERAL_RULE1 91
+#define J_SCRIPT_REGEXPLITERAL_RULE1 94
-#define J_SCRIPT_REGEXPLITERAL_RULE2 92
+#define J_SCRIPT_REGEXPLITERAL_RULE2 95
QT_QML_END_NAMESPACE
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 325f752cd5..84f30af066 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -195,7 +195,7 @@ class QQmlNonbindingBinding: public QQmlBinding
{
protected:
void doUpdate(const DeleteWatcher &watcher,
- QQmlPropertyData::WriteFlags flags, QV4::Scope &scope) Q_DECL_OVERRIDE Q_DECL_FINAL
+ QQmlPropertyData::WriteFlags flags, QV4::Scope &scope) Q_DECL_OVERRIDE
{
auto ep = QQmlEnginePrivate::get(scope.engine);
ep->referenceScarceResources();
@@ -296,6 +296,50 @@ protected:
}
};
+class QQmlTranslationBinding : public GenericBinding<QMetaType::QString> {
+public:
+ QQmlTranslationBinding(QV4::CompiledData::CompilationUnit *compilationUnit, const QV4::CompiledData::Binding *binding)
+ {
+ setCompilationUnit(compilationUnit);
+ m_binding = binding;
+ setSourceLocation(QQmlSourceLocation(compilationUnit->fileName(), binding->valueLocation.line, binding->valueLocation.column));
+ }
+
+ void doUpdate(const DeleteWatcher &watcher,
+ QQmlPropertyData::WriteFlags flags, QV4::Scope &) Q_DECL_OVERRIDE Q_DECL_FINAL
+ {
+ if (watcher.wasDeleted())
+ return;
+
+ if (!isAddedToObject() || hasError())
+ return;
+
+ const QString result = m_binding->valueAsString(m_compilationUnit->data);
+
+ Q_ASSERT(targetObject());
+
+ QQmlPropertyData *pd;
+ QQmlPropertyData vpd;
+ getPropertyData(&pd, &vpd);
+ Q_ASSERT(pd);
+ doStore(result, pd, flags);
+ }
+
+private:
+ const QV4::CompiledData::Binding *m_binding;
+};
+
+QQmlBinding *QQmlBinding::createTranslationBinding(QV4::CompiledData::CompilationUnit *unit, const QV4::CompiledData::Binding *binding, QObject *obj, QQmlContextData *ctxt)
+{
+ QQmlTranslationBinding *b = new QQmlTranslationBinding(unit, binding);
+
+ b->setNotifyOnValueChanged(true);
+ b->QQmlJavaScriptExpression::setContext(ctxt);
+ b->setScopeObject(obj);
+
+ return b;
+}
+
Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core,
const QQmlPropertyData &valueTypeData,
const QV4::Value &result,
diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h
index 0f2fb329f5..1c894148e4 100644
--- a/src/qml/qml/qqmlbinding_p.h
+++ b/src/qml/qml/qqmlbinding_p.h
@@ -77,6 +77,8 @@ public:
const QString &url = QString(), quint16 lineNumber = 0);
static QQmlBinding *create(const QQmlPropertyData *property, QV4::Function *function,
QObject *obj, QQmlContextData *ctxt, QV4::ExecutionContext *scope);
+ static QQmlBinding *createTranslationBinding(QV4::CompiledData::CompilationUnit *unit, const QV4::CompiledData::Binding *binding,
+ QObject *obj, QQmlContextData *ctxt);
~QQmlBinding();
void setTarget(const QQmlProperty &);
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index ce35846c88..e7a45482e6 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -1040,20 +1040,53 @@ void QQmlComponent::create(QQmlIncubator &incubator, QQmlContext *context,
enginePriv->incubate(incubator, forContextData);
}
+/*
+ This is essentially a copy of QQmlComponent::create(); except it takes the QQmlContextData
+ arguments instead of QQmlContext which means we don't have to construct the rather weighty
+ wrapper class for every delegate item.
+
+ This is used by QQmlDelegateModel.
+*/
+void QQmlComponentPrivate::incubateObject(
+ QQmlIncubator *incubationTask,
+ QQmlComponent *component,
+ QQmlEngine *engine,
+ QQmlContextData *context,
+ QQmlContextData *forContext)
+{
+ QQmlIncubatorPrivate *incubatorPriv = QQmlIncubatorPrivate::get(incubationTask);
+ QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(engine);
+ QQmlComponentPrivate *componentPriv = QQmlComponentPrivate::get(component);
+
+ incubatorPriv->compilationUnit = componentPriv->compilationUnit;
+ incubatorPriv->compilationUnit->addref();
+ incubatorPriv->enginePriv = enginePriv;
+ incubatorPriv->creator.reset(new QQmlObjectCreator(context, componentPriv->compilationUnit, componentPriv->creationContext));
+ incubatorPriv->subComponentToCreate = componentPriv->start;
+
+ enginePriv->incubate(*incubationTask, forContext);
+}
+
+
+
class QQmlComponentIncubator;
namespace QV4 {
namespace Heap {
-struct QmlIncubatorObject : Object {
+#define QmlIncubatorObjectMembers(class, Member) \
+ Member(class, HeapValue, HeapValue, valuemap) \
+ Member(class, HeapValue, HeapValue, statusChanged) \
+ Member(class, Pointer, QmlContext *, qmlContext) \
+ Member(class, NoMark, QQmlComponentIncubator *, incubator) \
+ Member(class, NoMark, QQmlQPointer<QObject>, parent)
+
+DECLARE_HEAP_OBJECT(QmlIncubatorObject, Object) {
+ DECLARE_MARK_TABLE(QmlIncubatorObject);
+
void init(QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous);
inline void destroy();
- QQmlComponentIncubator *incubator;
- QQmlQPointer<QObject> parent;
- QV4::Value valuemap;
- QV4::Value statusChanged;
- Pointer<Heap::QmlContext> qmlContext;
};
}
@@ -1069,8 +1102,6 @@ struct QmlIncubatorObject : public QV4::Object
static void method_get_object(const BuiltinFunction *, Scope &scope, CallData *callData);
static void method_forceCompletion(const BuiltinFunction *, Scope &scope, CallData *callData);
- static void markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e);
-
void statusChanged(QQmlIncubator::Status);
void setInitialState(QObject *);
};
@@ -1374,8 +1405,8 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
r->setPrototype(p);
if (!valuemap->isUndefined())
- r->d()->valuemap = valuemap;
- r->d()->qmlContext = v4->qmlContext();
+ r->d()->valuemap.set(scope.engine, valuemap);
+ r->d()->qmlContext.set(scope.engine, v4->qmlContext());
r->d()->parent = parent;
QQmlIncubator *incubator = r->d()->incubator;
@@ -1459,7 +1490,7 @@ void QV4::QmlIncubatorObject::method_set_statusChanged(const BuiltinFunction *,
if (!o || callData->argc < 1)
THROW_TYPE_ERROR();
- o->d()->statusChanged = callData->args[0];
+ o->d()->statusChanged.set(scope.engine, callData->args[0]);
RETURN_UNDEFINED();
}
@@ -1471,10 +1502,10 @@ QQmlComponentExtension::~QQmlComponentExtension()
void QV4::Heap::QmlIncubatorObject::init(QQmlIncubator::IncubationMode m)
{
Object::init();
- valuemap = QV4::Primitive::undefinedValue();
- statusChanged = QV4::Primitive::undefinedValue();
+ valuemap.set(internalClass->engine, QV4::Primitive::undefinedValue());
+ statusChanged.set(internalClass->engine, QV4::Primitive::undefinedValue());
parent.init();
- qmlContext = nullptr;
+ qmlContext.set(internalClass->engine, nullptr);
incubator = new QQmlComponentIncubator(this, m);
}
@@ -1497,16 +1528,6 @@ void QV4::QmlIncubatorObject::setInitialState(QObject *o)
}
}
-void QV4::QmlIncubatorObject::markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e)
-{
- QmlIncubatorObject::Data *o = static_cast<QmlIncubatorObject::Data *>(that);
- o->valuemap.mark(e);
- o->statusChanged.mark(e);
- if (o->qmlContext)
- o->qmlContext->mark(e);
- Object::markObjects(that, e);
-}
-
void QV4::QmlIncubatorObject::statusChanged(QQmlIncubator::Status s)
{
QV4::Scope scope(engine());
diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h
index d01a987acc..6414025574 100644
--- a/src/qml/qml/qqmlcomponent_p.h
+++ b/src/qml/qml/qqmlcomponent_p.h
@@ -88,6 +88,13 @@ public:
void initializeObjectWithInitialProperties(QV4::QmlContext *qmlContext, const QV4::Value &valuemap, QObject *toCreate);
static void setInitialProperties(QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &o, const QV4::Value &v);
+ void incubateObject(
+ QQmlIncubator *incubationTask,
+ QQmlComponent *component,
+ QQmlEngine *engine,
+ QQmlContextData *context,
+ QQmlContextData *forContext);
+
QQmlTypeData *typeData;
void typeDataReady(QQmlTypeData *) override;
void typeDataProgress(QQmlTypeData *, qreal) override;
diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp
index 0b0bbef795..6ad641b8b1 100644
--- a/src/qml/qml/qqmlcustomparser.cpp
+++ b/src/qml/qml/qqmlcustomparser.cpp
@@ -121,13 +121,16 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const
{
Q_ASSERT_X(ok, "QQmlCustomParser::evaluateEnum", "ok must not be a null pointer");
*ok = false;
+
+ // we support one or two '.' in the enum phrase:
+ // * <TypeName>.<EnumValue>
+ // * <TypeName>.<ScopedEnumName>.<EnumValue>
+
int dot = script.indexOf('.');
- if (dot == -1)
+ if (dot == -1 || dot == script.length()-1)
return -1;
-
QString scope = QString::fromUtf8(script.left(dot));
- QByteArray enumValue = script.mid(dot+1);
if (scope != QLatin1String("Qt")) {
if (imports.isNull())
@@ -142,9 +145,20 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const
type = result.type;
}
- return type ? type->enumValue(engine, QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
+ if (!type)
+ return -1;
+
+ int dot2 = script.indexOf('.', dot+1);
+ const bool dot2Valid = dot2 != -1 && dot2 != script.length()-1;
+ QByteArray enumValue = script.mid(dot2Valid ? dot2 + 1 : dot + 1);
+ QByteArray scopedEnumName = (dot2Valid ? script.mid(dot + 1, dot2 - dot - 1) : QByteArray());
+ if (!scopedEnumName.isEmpty())
+ return type->scopedEnumValue(engine, scopedEnumName, enumValue, ok);
+ else
+ return type->enumValue(engine, QHashedCStringRef(enumValue.constData(), enumValue.length()), ok);
}
+ QByteArray enumValue = script.mid(dot + 1);
const QMetaObject *mo = StaticQtMetaObject::get();
int i = mo->enumeratorCount();
while (i--) {
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index ba22bfde76..38a2978712 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -449,6 +449,12 @@ The following functions are also on the Qt object.
\li \c "windows" - Windows
\li \c "winrt" - WinRT / UWP
\endlist
+
+ \row
+ \li \c platform.pluginName
+ \li This is the name of the platform set on the QGuiApplication instance
+ as returned by \l QGuiApplication::platformName()
+
\endtable
*/
@@ -763,7 +769,7 @@ class QQmlThreadNotifierProxyObject : public QObject
public:
QPointer<QObject> target;
- virtual int qt_metacall(QMetaObject::Call, int methodIndex, void **a) {
+ int qt_metacall(QMetaObject::Call, int methodIndex, void **a) override {
if (!target)
return -1;
@@ -1322,6 +1328,27 @@ void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
}
/*!
+ Refreshes all binding expressions that use strings marked for translation.
+
+ Call this function after you have installed a new translator with
+ QCoreApplication::installTranslator, to ensure that your user-interface
+ shows up-to-date translations.
+
+ \note Due to a limitation in the implementation, this function
+ refreshes all the engine's bindings, not only those that use strings
+ marked for translation.
+ This may be optimized in a future release.
+
+ \since 5.10
+*/
+void QQmlEngine::retranslate()
+{
+ Q_D(QQmlEngine);
+ if (QQmlContextData *firstChildContext = QQmlContextData::get(d->rootContext)->childContexts)
+ firstChildContext->refreshExpressions();
+}
+
+/*!
Returns the QQmlContext for the \a object, or 0 if no
context has been set.
@@ -1441,6 +1468,9 @@ bool QQmlEngine::event(QEvent *e)
Q_D(QQmlEngine);
if (e->type() == QEvent::User)
d->doDeleteInEngineThread();
+ else if (e->type() == QEvent::LanguageChange) {
+ retranslate();
+ }
return QJSEngine::event(e);
}
@@ -1492,9 +1522,9 @@ QQmlEngine *qmlEngine(const QObject *obj)
QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
{
- QQmlData *data = QQmlData::get(object);
+ QQmlData *data = QQmlData::get(object, create);
if (!data)
- return 0; // Attached properties are only on objects created by QML
+ return 0; // Attached properties are only on objects created by QML, unless explicitly requested (create==true)
QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
if (rv || !create)
diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h
index 8cada954fe..2bf4c0497b 100644
--- a/src/qml/qml/qqmlengine.h
+++ b/src/qml/qml/qqmlengine.h
@@ -144,6 +144,10 @@ public:
bool outputWarningsToStandardError() const;
void setOutputWarningsToStandardError(bool);
+public Q_SLOTS:
+ void retranslate();
+
+public:
static QQmlContext *contextForObject(const QObject *);
static void setContextForObject(QObject *, QQmlContext *);
diff --git a/src/qml/qml/qqmlglobal.cpp b/src/qml/qml/qqmlglobal.cpp
index 7939656107..6418812bae 100644
--- a/src/qml/qml/qqmlglobal.cpp
+++ b/src/qml/qml/qqmlglobal.cpp
@@ -343,6 +343,8 @@ QObject *QQmlGuiProvider::styleHints()
return o;
}
+QString QQmlGuiProvider::pluginName() const { return QString(); }
+
static QQmlGuiProvider *guiProvider = 0;
Q_QML_PRIVATE_EXPORT QQmlGuiProvider *QQml_setGuiProvider(QQmlGuiProvider *newProvider)
diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h
index 707814e781..a6c113f5a7 100644
--- a/src/qml/qml/qqmlglobal_p.h
+++ b/src/qml/qml/qqmlglobal_p.h
@@ -311,6 +311,7 @@ public:
virtual QObject *styleHints();
virtual QStringList fontFamilies();
virtual bool openUrlExternally(QUrl &);
+ virtual QString pluginName() const;
};
Q_QML_PRIVATE_EXPORT QQmlGuiProvider *QQml_setGuiProvider(QQmlGuiProvider *);
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index ec748d1ca9..fc8e60e3f2 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -295,7 +295,8 @@ public:
QList<QQmlError> *errors);
bool resolveType(const QHashedStringRef &type, int *vmajor, int *vminor,
- QQmlType** type_return, QList<QQmlError> *errors);
+ QQmlType** type_return, QList<QQmlError> *errors,
+ QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion);
QUrl baseUrl;
QString base;
@@ -620,7 +621,8 @@ QString QQmlImports::versionString(int vmaj, int vmin, ImportVersion version)
*/
bool QQmlImports::resolveType(const QHashedStringRef &type,
QQmlType** type_return, int *vmaj, int *vmin,
- QQmlImportNamespace** ns_return, QList<QQmlError> *errors) const
+ QQmlImportNamespace** ns_return, QList<QQmlError> *errors,
+ QQmlImport::RecursionRestriction recursionRestriction) const
{
QQmlImportNamespace* ns = d->findQualifiedNamespace(type);
if (ns) {
@@ -629,7 +631,7 @@ bool QQmlImports::resolveType(const QHashedStringRef &type,
return true;
}
if (type_return) {
- if (d->resolveType(type,vmaj,vmin,type_return, errors)) {
+ if (d->resolveType(type,vmaj,vmin,type_return, errors, recursionRestriction)) {
if (qmlImportTrace()) {
#define RESOLVE_TYPE_DEBUG qDebug().nospace() << "QQmlImports(" << qPrintable(baseUrl().toString()) \
<< ')' << "::resolveType: " << type.toString() << " => "
@@ -712,7 +714,8 @@ bool QQmlImports::resolveType(QQmlImportNamespace* ns, const QHashedStringRef &t
bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader,
const QHashedStringRef& type, int *vmajor, int *vminor,
- QQmlType** type_return, QString *base, bool *typeRecursionDetected) const
+ QQmlType** type_return, QString *base, bool *typeRecursionDetected,
+ QQmlImport::RecursionRestriction recursionRestriction) const
{
if (majversion >= 0 && minversion >= 0) {
QQmlType *t = QQmlMetaType::qmlType(type, uri, majversion, minversion);
@@ -747,7 +750,7 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader,
if (resolveLocalUrl(*base, c.fileName) != componentUrl)
continue; // failed attempt to access an internal type
}
- if (*base == componentUrl) {
+ if (recursionRestriction == QQmlImport::PreventRecursion && *base == componentUrl) {
if (typeRecursionDetected)
*typeRecursionDetected = true;
continue; // no recursion
@@ -790,7 +793,7 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader,
}
if (exists) {
- if (base && (*base == qmlUrl)) { // no recursion
+ if (recursionRestriction == QQmlImport::PreventRecursion && base && (*base == qmlUrl)) { // no recursion
if (typeRecursionDetected)
*typeRecursionDetected = true;
} else {
@@ -806,7 +809,8 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader,
}
bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor, int *vminor,
- QQmlType** type_return, QList<QQmlError> *errors)
+ QQmlType** type_return, QList<QQmlError> *errors,
+ QQmlImport::RecursionRestriction recursionRestriction)
{
QQmlImportNamespace *s = 0;
int dot = type.indexOf(Dot);
@@ -835,7 +839,7 @@ bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor,
}
QHashedStringRef unqualifiedtype = dot < 0 ? type : QHashedStringRef(type.constData()+dot+1, type.length()-dot-1);
if (s) {
- if (s->resolveType(typeLoader,unqualifiedtype,vmajor,vminor,type_return, &base, errors))
+ if (s->resolveType(typeLoader,unqualifiedtype,vmajor,vminor,type_return, &base, errors, recursionRestriction))
return true;
if (s->imports.count() == 1 && !s->imports.at(0)->isLibrary && type_return && s != &unqualifiedset) {
// qualified, and only 1 url
@@ -858,13 +862,14 @@ QQmlImportInstance *QQmlImportNamespace::findImport(const QString &uri) const
bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type,
int *vmajor, int *vminor, QQmlType** type_return,
- QString *base, QList<QQmlError> *errors)
+ QString *base, QList<QQmlError> *errors,
+ QQmlImport::RecursionRestriction recursionRestriction)
{
bool typeRecursionDetected = false;
for (int i=0; i<imports.count(); ++i) {
const QQmlImportInstance *import = imports.at(i);
if (import->resolveType(typeLoader, type, vmajor, vminor, type_return,
- base, &typeRecursionDetected)) {
+ base, &typeRecursionDetected, recursionRestriction)) {
if (qmlCheckTypes()) {
// check for type clashes
for (int j = i+1; j<imports.count(); ++j) {
@@ -1489,6 +1494,17 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix
if (!url.endsWith(Slash) && !url.endsWith(Backslash))
url += Slash;
+ // ### For enum support, we are now adding the implicit import always (and earlier). Bail early
+ // if the implicit import has already been explicitly added, otherwise we can run into issues
+ // with duplicate imports
+ if (isImplicitImport) {
+ for (QList<QQmlImportInstance *>::const_iterator it = nameSpace->imports.constBegin();
+ it != nameSpace->imports.constEnd(); ++it) {
+ if ((*it)->uri == importUri)
+ return true;
+ }
+ }
+
QQmlImportInstance *inserted = addImportToNamespace(nameSpace, importUri, url, vmaj, vmin, QV4::CompiledData::Import::ImportFile, errors, isImplicitImport);
Q_ASSERT(inserted);
diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h
index 7c691a468c..1a50d5c16a 100644
--- a/src/qml/qml/qqmlimport_p.h
+++ b/src/qml/qml/qqmlimport_p.h
@@ -70,6 +70,10 @@ class QQmlImportDatabase;
class QQmlTypeLoader;
class QQmlTypeLoaderQmldirContent;
+namespace QQmlImport {
+ enum RecursionRestriction { PreventRecursion, AllowRecursion };
+}
+
struct QQmlImportInstance
{
QString uri; // e.g. QtQuick
@@ -87,7 +91,8 @@ struct QQmlImportInstance
bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type,
int *vmajor, int *vminor, QQmlType** type_return,
- QString *base = 0, bool *typeRecursionDetected = 0) const;
+ QString *base = 0, bool *typeRecursionDetected = 0,
+ QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion) const;
};
class QQmlImportNamespace
@@ -102,7 +107,8 @@ public:
bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type,
int *vmajor, int *vminor, QQmlType** type_return,
- QString *base = 0, QList<QQmlError> *errors = 0);
+ QString *base = 0, QList<QQmlError> *errors = 0,
+ QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion);
// Prefix when used as a qualified import. Otherwise empty.
QHashedString prefix;
@@ -128,7 +134,8 @@ public:
QQmlType** type_return,
int *version_major, int *version_minor,
QQmlImportNamespace** ns_return,
- QList<QQmlError> *errors = 0) const;
+ QList<QQmlError> *errors = 0,
+ QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion) const;
bool resolveType(QQmlImportNamespace*,
const QHashedStringRef& type,
QQmlType** type_return, int *version_major, int *version_minor) const;
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index eec5d1ae57..31c277d283 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -350,7 +350,7 @@ void QQmlPropertyCapture::registerQmlDependencies(const QV4::CompiledData::Funct
QV4::Scoped<QV4::QmlContext> context(scope, engine->qmlContext());
QQmlContextData *qmlContext = context->qmlContext();
- const QV4::CompiledData::LEUInt32 *idObjectDependency = compiledFunction->qmlIdObjectDependencyTable();
+ const quint32_le *idObjectDependency = compiledFunction->qmlIdObjectDependencyTable();
const int idObjectDependencyCount = compiledFunction->nDependingIdObjects;
for (int i = 0; i < idObjectDependencyCount; ++i, ++idObjectDependency) {
Q_ASSERT(int(*idObjectDependency) < qmlContext->idValueCount);
@@ -359,7 +359,7 @@ void QQmlPropertyCapture::registerQmlDependencies(const QV4::CompiledData::Funct
}
Q_ASSERT(qmlContext->contextObject);
- const QV4::CompiledData::LEUInt32 *contextPropertyDependency = compiledFunction->qmlContextPropertiesDependencyTable();
+ const quint32_le *contextPropertyDependency = compiledFunction->qmlContextPropertiesDependencyTable();
const int contextPropertyDependencyCount = compiledFunction->nDependingContextProperties;
for (int i = 0; i < contextPropertyDependencyCount; ++i) {
const int propertyIndex = *contextPropertyDependency++;
@@ -369,7 +369,7 @@ void QQmlPropertyCapture::registerQmlDependencies(const QV4::CompiledData::Funct
}
QObject *scopeObject = context->qmlScope();
- const QV4::CompiledData::LEUInt32 *scopePropertyDependency = compiledFunction->qmlScopePropertiesDependencyTable();
+ const quint32_le *scopePropertyDependency = compiledFunction->qmlScopePropertiesDependencyTable();
const int scopePropertyDependencyCount = compiledFunction->nDependingScopeProperties;
for (int i = 0; i < scopePropertyDependencyCount; ++i) {
const int propertyIndex = *scopePropertyDependency++;
@@ -461,7 +461,12 @@ void QQmlJavaScriptExpression::setupFunction(QV4::ExecutionContext *qmlContext,
return;
m_qmlScope.set(qmlContext->engine(), *qmlContext);
m_v4Function = f;
- m_compilationUnit = m_v4Function->compilationUnit;
+ setCompilationUnit(m_v4Function->compilationUnit);
+}
+
+void QQmlJavaScriptExpression::setCompilationUnit(QV4::CompiledData::CompilationUnit *compilationUnit)
+{
+ m_compilationUnit = compilationUnit;
}
void QQmlJavaScriptExpression::clearActiveGuards()
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index eeed272793..8b4b64f4d2 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -160,11 +160,13 @@ protected:
}
void setupFunction(QV4::ExecutionContext *qmlContext, QV4::Function *f);
+ void setCompilationUnit(QV4::CompiledData::CompilationUnit *compilationUnit);
private:
friend class QQmlContextData;
friend class QQmlPropertyCapture;
friend void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *, void **);
+ friend class QQmlTranslationBinding;
QQmlDelayedError *m_error;
diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp
index d94f7c56e4..43677e0d78 100644
--- a/src/qml/qml/qqmllistwrapper.cpp
+++ b/src/qml/qml/qqmllistwrapper.cpp
@@ -140,12 +140,13 @@ ReturnedValue QmlListWrapper::getIndexed(const Managed *m, uint index, bool *has
return Primitive::undefinedValue().asReturnedValue();
}
-void QmlListWrapper::put(Managed *m, String *name, const Value &value)
+bool QmlListWrapper::put(Managed *m, String *name, const Value &value)
{
// doesn't do anything. Should we throw?
Q_UNUSED(m);
Q_UNUSED(name);
Q_UNUSED(value);
+ return false;
}
void QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h
index b914c681f2..84dadba01a 100644
--- a/src/qml/qml/qqmllistwrapper_p.h
+++ b/src/qml/qml/qqmllistwrapper_p.h
@@ -95,7 +95,7 @@ struct Q_QML_EXPORT QmlListWrapper : Object
static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
- static void put(Managed *m, String *name, const Value &value);
+ static bool put(Managed *m, String *name, const Value &value);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
};
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index bb9b69c479..b75508e1e5 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -160,8 +160,9 @@ public:
~QQmlTypePrivate();
void init() const;
- void initEnums() const;
+ void initEnums(const QQmlPropertyCache *cache = 0) const;
void insertEnums(const QMetaObject *metaObject) const;
+ void insertEnumsFromPropertyCache(const QQmlPropertyCache *cache) const;
QQmlType::RegistrationType regType;
@@ -216,6 +217,8 @@ public:
mutable bool haveSuperType:1;
mutable QList<QQmlProxyMetaObject::ProxyData> metaObjects;
mutable QStringHash<int> enums;
+ mutable QStringHash<int> scopedEnumIndex; // maps from enum name to index in scopedEnums
+ mutable QList<QStringHash<int>*> scopedEnums;
static QHash<const QMetaObject *, int> attachedPropertyIds;
};
@@ -313,6 +316,7 @@ QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type)
QQmlTypePrivate::~QQmlTypePrivate()
{
+ qDeleteAll(scopedEnums);
switch (regType) {
case QQmlType::CppType:
delete extraData.cd->customParser;
@@ -497,14 +501,17 @@ QQmlType *QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
return QQmlMetaType::qmlType(mo);
}
-int QQmlType::resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const
+QQmlPropertyCache *QQmlType::compositePropertyCache(QQmlEnginePrivate *engine) const
{
+ // similar logic to resolveCompositeBaseType
Q_ASSERT(isComposite());
- *ok = false;
- QQmlType *type = resolveCompositeBaseType(engine);
- if (!type)
- return -1;
- return type->enumValue(engine, name, ok);
+ if (!engine)
+ return 0;
+ QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()), QQmlRefPointer<QQmlTypeData>::Adopt);
+ if (td.isNull() || !td->isComplete())
+ return 0;
+ QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit();
+ return compilationUnit->rootPropertyCache();
}
static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
@@ -673,7 +680,7 @@ void QQmlTypePrivate::init() const
lock.unlock();
}
-void QQmlTypePrivate::initEnums() const
+void QQmlTypePrivate::initEnums(const QQmlPropertyCache *cache) const
{
if (isEnumSetup) return;
@@ -682,6 +689,8 @@ void QQmlTypePrivate::initEnums() const
QMutexLocker lock(metaTypeDataLock());
if (isEnumSetup) return;
+ if (cache)
+ insertEnumsFromPropertyCache(cache);
if (baseMetaObject) // could be singleton type without metaobject
insertEnums(baseMetaObject);
@@ -702,11 +711,49 @@ void QQmlTypePrivate::insertEnums(const QMetaObject *metaObject) const
// Add any enum values defined by this class, overwriting any inherited values
for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) {
QMetaEnum e = metaObject->enumerator(ii);
- for (int jj = 0; jj < e.keyCount(); ++jj)
- enums.insert(QString::fromUtf8(e.key(jj)), e.value(jj));
+ const bool isScoped = e.isScoped();
+ QStringHash<int> *scoped = isScoped ? new QStringHash<int>() : 0;
+
+ for (int jj = 0; jj < e.keyCount(); ++jj) {
+ const QString key = QString::fromUtf8(e.key(jj));
+ const int value = e.value(jj);
+ enums.insert(key, value);
+ if (isScoped)
+ scoped->insert(key, value);
+ }
+
+ if (isScoped) {
+ scopedEnums << scoped;
+ scopedEnumIndex.insert(QString::fromUtf8(e.name()), scopedEnums.count()-1);
+ }
}
}
+void QQmlTypePrivate::insertEnumsFromPropertyCache(const QQmlPropertyCache *cache) const
+{
+ const QMetaObject *cppMetaObject = cache->firstCppMetaObject();
+
+ while (cache && cache->metaObject() != cppMetaObject) {
+ QStringHash<int> *scoped = new QStringHash<int>();
+
+ int count = cache->qmlEnumCount();
+ for (int ii = 0; ii < count; ++ii) {
+ QQmlEnumData *enumData = cache->qmlEnum(ii);
+
+ for (int jj = 0; jj < enumData->values.count(); ++jj) {
+ const QQmlEnumValue &value = enumData->values.at(jj);
+ enums.insert(value.namedValue, value.value);
+ scoped->insert(value.namedValue, value.value);
+ }
+ scopedEnums << scoped;
+ scopedEnumIndex.insert(enumData->name, scopedEnums.count()-1);
+ }
+ cache = cache->parent();
+ }
+ insertEnums(cppMetaObject);
+}
+
+
QByteArray QQmlType::typeName() const
{
if (d->regType == SingletonType || d->regType == CompositeSingletonType)
@@ -956,11 +1003,11 @@ QUrl QQmlType::sourceUrl() const
int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name, bool *ok) const
{
Q_ASSERT(ok);
- if (isComposite())
- return resolveCompositeEnumValue(engine, name.toString(), ok);
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
+
*ok = true;
- d->initEnums();
+ d->initEnums(cache);
int *rv = d->enums.value(name);
if (rv)
@@ -973,11 +1020,11 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name,
int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &name, bool *ok) const
{
Q_ASSERT(ok);
- if (isComposite())
- return resolveCompositeEnumValue(engine, name.toUtf16(), ok);
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
+
*ok = true;
- d->initEnums();
+ d->initEnums(cache);
int *rv = d->enums.value(name);
if (rv)
@@ -990,11 +1037,10 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &name
int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const
{
Q_ASSERT(ok);
- if (isComposite())
- return resolveCompositeEnumValue(engine, name->toQString(), ok);
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
*ok = true;
- d->initEnums();
+ d->initEnums(cache);
int *rv = d->enums.value(name);
if (rv)
@@ -1004,6 +1050,110 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool
return -1;
}
+int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const
+{
+ Q_ASSERT(ok);
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
+ *ok = true;
+
+ d->initEnums(cache);
+
+ int *rv = d->scopedEnumIndex.value(name);
+ if (rv)
+ return *rv;
+
+ *ok = false;
+ return -1;
+}
+
+int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QString &name, bool *ok) const
+{
+ Q_ASSERT(ok);
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
+ *ok = true;
+
+ d->initEnums(cache);
+
+ int *rv = d->scopedEnumIndex.value(name);
+ if (rv)
+ return *rv;
+
+ *ok = false;
+ return -1;
+}
+
+int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *name, bool *ok) const
+{
+ Q_UNUSED(engine)
+ Q_ASSERT(ok);
+ *ok = true;
+
+ Q_ASSERT(index > -1 && index < d->scopedEnums.count());
+ int *rv = d->scopedEnums.at(index)->value(name);
+ if (rv)
+ return *rv;
+
+ *ok = false;
+ return -1;
+}
+
+int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &name, bool *ok) const
+{
+ Q_UNUSED(engine)
+ Q_ASSERT(ok);
+ *ok = true;
+
+ Q_ASSERT(index > -1 && index < d->scopedEnums.count());
+ int *rv = d->scopedEnums.at(index)->value(name);
+ if (rv)
+ return *rv;
+
+ *ok = false;
+ return -1;
+}
+
+int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &scopedEnumName, const QByteArray &name, bool *ok) const
+{
+ Q_ASSERT(ok);
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
+ *ok = true;
+
+ d->initEnums(cache);
+
+ int *rv = d->scopedEnumIndex.value(QHashedCStringRef(scopedEnumName.constData(), scopedEnumName.length()));
+ if (rv) {
+ int index = *rv;
+ Q_ASSERT(index > -1 && index < d->scopedEnums.count());
+ rv = d->scopedEnums.at(index)->value(QHashedCStringRef(name.constData(), name.length()));
+ if (rv)
+ return *rv;
+ }
+
+ *ok = false;
+ return -1;
+}
+
+int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &scopedEnumName, const QStringRef &name, bool *ok) const
+{
+ Q_ASSERT(ok);
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
+ *ok = true;
+
+ d->initEnums(cache);
+
+ int *rv = d->scopedEnumIndex.value(QHashedStringRef(scopedEnumName));
+ if (rv) {
+ int index = *rv;
+ Q_ASSERT(index > -1 && index < d->scopedEnums.count());
+ rv = d->scopedEnums.at(index)->value(QHashedStringRef(name));
+ if (rv)
+ return *rv;
+ }
+
+ *ok = false;
+ return -1;
+}
+
QQmlTypeModule::QQmlTypeModule()
: d(new QQmlTypeModulePrivate)
{
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index 2b615e645a..ead4f130ec 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -135,6 +135,7 @@ public:
struct QQmlMetaTypeData;
class QHashedCStringRef;
+class QQmlPropertyCache;
class Q_QML_PRIVATE_EXPORT QQmlType
{
public:
@@ -216,10 +217,18 @@ public:
int enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &, bool *ok) const;
int enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &, bool *ok) const;
int enumValue(QQmlEnginePrivate *engine, const QV4::String *, bool *ok) const;
+
+ int scopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *, bool *ok) const;
+ int scopedEnumIndex(QQmlEnginePrivate *engine, const QString &, bool *ok) const;
+ int scopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *, bool *ok) const;
+ int scopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &, bool *ok) const;
+ int scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &, const QByteArray &, bool *ok) const;
+ int scopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &, const QStringRef &, bool *ok) const;
+
private:
QQmlType *superType() const;
QQmlType *resolveCompositeBaseType(QQmlEnginePrivate *engine) const;
- int resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const;
+ QQmlPropertyCache *compositePropertyCache(QQmlEnginePrivate *engine) const;
friend class QQmlTypePrivate;
friend struct QQmlMetaTypeData;
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 2cbcfbbfb6..9206395c8f 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -801,17 +801,13 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
&& !_valueTypeProperty)
QQmlPropertyPrivate::removeBinding(_bindingTarget, QQmlPropertyIndex(property->coreIndex()));
- if (binding->type == QV4::CompiledData::Binding::Type_Script) {
- QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
-
- QV4::Scope scope(v4);
- QV4::Scoped<QV4::QmlContext> qmlContext(scope, currentQmlContext());
-
+ if (binding->type == QV4::CompiledData::Binding::Type_Script || binding->containsTranslations()) {
if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression) {
+ QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
int signalIndex = _propertyCache->methodIndexToSignalIndex(property->coreIndex());
QQmlBoundSignal *bs = new QQmlBoundSignal(_bindingTarget, signalIndex, _scopeObject, engine);
QQmlBoundSignalExpression *expr = new QQmlBoundSignalExpression(_bindingTarget, signalIndex,
- context, _scopeObject, runtimeFunction, qmlContext);
+ context, _scopeObject, runtimeFunction, currentQmlContext());
bs->takeExpression(expr);
} else {
@@ -827,7 +823,12 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
prop = _valueTypeProperty;
subprop = property;
}
- qmlBinding = QQmlBinding::create(prop, runtimeFunction, _scopeObject, context, qmlContext);
+ if (binding->containsTranslations()) {
+ qmlBinding = QQmlBinding::createTranslationBinding(compilationUnit, binding, _scopeObject, context);
+ } else {
+ QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
+ qmlBinding = QQmlBinding::create(prop, runtimeFunction, _scopeObject, context, currentQmlContext());
+ }
qmlBinding->setTarget(_bindingTarget, *prop, subprop);
sharedState->allCreatedBindings.push(QQmlAbstractBinding::Ptr(qmlBinding));
@@ -996,7 +997,7 @@ void QQmlObjectCreator::setupFunctions()
QV4::ScopedValue function(scope);
QV4::ScopedContext qmlContext(scope, currentQmlContext());
- const QV4::CompiledData::LEUInt32 *functionIdx = _compiledObject->functionOffsetTable();
+ const quint32_le *functionIdx = _compiledObject->functionOffsetTable();
for (quint32 i = 0; i < _compiledObject->nFunctions; ++i, ++functionIdx) {
QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[*functionIdx];
const QString name = runtimeFunction->name()->toQString();
@@ -1026,12 +1027,12 @@ void QQmlObjectCreator::registerObjectWithContextById(const QV4::CompiledData::O
context->setIdProperty(object->id, instance);
}
-QV4::Heap::QmlContext *QQmlObjectCreator::currentQmlContext()
+QV4::QmlContext *QQmlObjectCreator::currentQmlContext()
{
if (!_qmlContext->isManaged())
_qmlContext->setM(QV4::QmlContext::create(v4->rootContext(), context, _scopeObject));
- return _qmlContext->d();
+ return _qmlContext;
}
QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isContextObject)
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index 982324be3c..45c14f0963 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -122,7 +122,7 @@ private:
void registerObjectWithContextById(const QV4::CompiledData::Object *object, QObject *instance) const;
- QV4::Heap::QmlContext *currentQmlContext();
+ QV4::QmlContext *currentQmlContext();
enum Phase {
Startup,
diff --git a/src/qml/qml/qqmlplatform.cpp b/src/qml/qml/qqmlplatform.cpp
index 165cde5eb3..a8c402af2e 100644
--- a/src/qml/qml/qqmlplatform.cpp
+++ b/src/qml/qml/qqmlplatform.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qqmlplatform_p.h"
+#include "qqmlglobal_p.h"
QT_BEGIN_NAMESPACE
@@ -78,6 +79,11 @@ QString QQmlPlatform::os()
#endif
}
+QString QQmlPlatform::pluginName() const
+{
+ return QQml_guiProvider()->pluginName();
+}
+
QT_END_NAMESPACE
#include "moc_qqmlplatform_p.cpp"
diff --git a/src/qml/qml/qqmlplatform_p.h b/src/qml/qml/qqmlplatform_p.h
index 6887720adb..6246ca7105 100644
--- a/src/qml/qml/qqmlplatform_p.h
+++ b/src/qml/qml/qqmlplatform_p.h
@@ -61,12 +61,14 @@ class Q_QML_PRIVATE_EXPORT QQmlPlatform : public QObject
{
Q_OBJECT
Q_PROPERTY(QString os READ os CONSTANT)
+ Q_PROPERTY(QString pluginName READ pluginName CONSTANT)
public:
explicit QQmlPlatform(QObject *parent = 0);
virtual ~QQmlPlatform();
static QString os();
+ QString pluginName() const;
private:
Q_DISABLE_COPY(QQmlPlatform)
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index d18159841c..15b9fe8312 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -321,12 +321,13 @@ QQmlPropertyCache *QQmlPropertyCache::copy()
}
QQmlPropertyCache *QQmlPropertyCache::copyAndReserve(int propertyCount, int methodCount,
- int signalCount)
+ int signalCount, int enumCount)
{
QQmlPropertyCache *rv = copy(propertyCount + methodCount + signalCount);
rv->propertyIndexCache.reserve(propertyCount);
rv->methodIndexCache.reserve(methodCount);
rv->signalHandlerIndexCache.reserve(signalCount);
+ rv->enumCache.reserve(enumCount);
rv->_metaObject = 0;
return rv;
@@ -421,6 +422,14 @@ void QQmlPropertyCache::appendMethod(const QString &name, QQmlPropertyData::Flag
setNamedProperty(name, methodIndex + methodOffset(), methodIndexCache.data() + methodIndex, (old != 0));
}
+void QQmlPropertyCache::appendEnum(const QString &name, const QVector<QQmlEnumValue> &values)
+{
+ QQmlEnumData data;
+ data.name = name;
+ data.values = values;
+ enumCache.append(data);
+}
+
// Returns this property cache's metaObject, creating it if necessary.
const QMetaObject *QQmlPropertyCache::createMetaObject()
{
@@ -1245,6 +1254,16 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder)
method.setReturnType(returnType);
}
+ for (int ii = 0; ii < enumCache.count(); ++ii) {
+ const QQmlEnumData &enumData = enumCache.at(ii);
+ QMetaEnumBuilder enumeration = builder.addEnumerator(enumData.name.toUtf8());
+ enumeration.setIsScoped(true);
+ for (int jj = 0; jj < enumData.values.count(); ++jj) {
+ const QQmlEnumValue &value = enumData.values.at(jj);
+ enumeration.addKey(value.namedValue.toUtf8(), value.value);
+ }
+ }
+
if (!_defaultPropertyName.isEmpty()) {
QQmlPropertyData *dp = property(_defaultPropertyName, 0, 0);
if (dp && dp->coreIndex() >= propertyIndexCacheStart) {
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index 64be1cb206..392768c1b1 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -349,6 +349,20 @@ private:
bool notFullyResolved() const { return _flags.notFullyResolved; }
};
+struct QQmlEnumValue
+{
+ QQmlEnumValue() : value(-1) {}
+ QQmlEnumValue(const QString &n, int v) : namedValue(n), value(v) {}
+ QString namedValue;
+ int value;
+};
+
+struct QQmlEnumData
+{
+ QString name;
+ QVector<QQmlEnumValue> values;
+};
+
class QQmlPropertyCacheMethodArguments;
class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount, public QQmlCleanup
{
@@ -374,13 +388,14 @@ public:
QQmlPropertyRawData::Flags signalFlags = QQmlPropertyData::Flags());
QQmlPropertyCache *copyAndReserve(int propertyCount,
- int methodCount, int signalCount);
+ int methodCount, int signalCount, int enumCount);
void appendProperty(const QString &, QQmlPropertyRawData::Flags flags, int coreIndex,
int propType, int notifyIndex);
void appendSignal(const QString &, QQmlPropertyRawData::Flags, int coreIndex,
const int *types = 0, const QList<QByteArray> &names = QList<QByteArray>());
void appendMethod(const QString &, QQmlPropertyData::Flags flags, int coreIndex,
const QList<QByteArray> &names = QList<QByteArray>());
+ void appendEnum(const QString &, const QVector<QQmlEnumValue> &);
const QMetaObject *metaObject() const;
const QMetaObject *createMetaObject();
@@ -395,6 +410,7 @@ public:
QQmlPropertyData *property(int) const;
QQmlPropertyData *method(int) const;
QQmlPropertyData *signal(int index) const;
+ QQmlEnumData *qmlEnum(int) const;
int methodIndexToSignalIndex(int) const;
QString defaultPropertyName() const;
@@ -434,6 +450,7 @@ public:
inline int methodOffset() const;
inline int signalCount() const;
inline int signalOffset() const;
+ inline int qmlEnumCount() const;
static bool isDynamicMetaObject(const QMetaObject *);
@@ -507,6 +524,7 @@ private:
IndexCache signalHandlerIndexCache;
StringCache stringCache;
AllowedRevisionCache allowedRevisionCache;
+ QVector<QQmlEnumData> enumCache;
bool _hasPropertyOverrides : 1;
bool _ownMetaObject : 1;
@@ -747,6 +765,14 @@ inline QQmlPropertyData *QQmlPropertyCache::signal(int index) const
return ensureResolved(rv);
}
+inline QQmlEnumData *QQmlPropertyCache::qmlEnum(int index) const
+{
+ if (index < 0 || index >= enumCache.count())
+ return 0;
+
+ return const_cast<QQmlEnumData *>(&enumCache.at(index));
+}
+
inline int QQmlPropertyCache::methodIndexToSignalIndex(int index) const
{
if (index < 0 || index >= (methodIndexCacheStart + methodIndexCache.count()))
@@ -817,6 +843,11 @@ int QQmlPropertyCache::signalOffset() const
return signalHandlerIndexCacheStart;
}
+int QQmlPropertyCache::qmlEnumCount() const
+{
+ return enumCache.count();
+}
+
bool QQmlPropertyCache::callJSFactoryMethod(QObject *object, void **args) const
{
if (_jsFactoryMethodIndex != -1) {
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index e4293596d8..151a7cd883 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -2651,6 +2651,10 @@ void QQmlTypeData::resolveTypes()
m_resolvedTypes.insert(unresolvedRef.key(), ref);
}
+
+ // ### this allows enums to work without explicit import or instantiation of the type
+ if (!m_implicitImportLoaded)
+ loadImplicitImport();
}
QQmlCompileError QQmlTypeData::buildTypeResolutionCaches(
diff --git a/src/qml/qml/qqmltypenamecache.cpp b/src/qml/qml/qqmltypenamecache.cpp
index c8e2b92c29..35ef8ada57 100644
--- a/src/qml/qml/qqmltypenamecache.cpp
+++ b/src/qml/qml/qqmltypenamecache.cpp
@@ -140,7 +140,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedStringRef &name,
return result;
}
-QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name) const
+QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name, QQmlImport::RecursionRestriction recursionRestriction) const
{
Result result = query(m_namedImports, name);
@@ -156,7 +156,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name) cons
QQmlImportNamespace *typeNamespace = 0;
QList<QQmlError> errors;
QQmlType *t = 0;
- bool typeFound = m_imports.resolveType(typeName, &t, 0, 0, &typeNamespace, &errors);
+ bool typeFound = m_imports.resolveType(typeName, &t, 0, 0, &typeNamespace, &errors, recursionRestriction);
if (typeFound) {
return Result(t);
}
diff --git a/src/qml/qml/qqmltypenamecache_p.h b/src/qml/qml/qqmltypenamecache_p.h
index 7cdcbe91b6..f7ba2a91b7 100644
--- a/src/qml/qml/qqmltypenamecache_p.h
+++ b/src/qml/qml/qqmltypenamecache_p.h
@@ -90,7 +90,7 @@ public:
};
Result query(const QHashedStringRef &) const;
Result query(const QHashedStringRef &, const void *importNamespace) const;
- Result query(const QV4::String *) const;
+ Result query(const QV4::String *, QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion) const;
Result query(const QV4::String *, const void *importNamespace) const;
private:
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index be4ab68831..7a06077c11 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -52,16 +52,17 @@ QT_BEGIN_NAMESPACE
using namespace QV4;
-DEFINE_OBJECT_VTABLE(QmlTypeWrapper);
+DEFINE_OBJECT_VTABLE(QQmlTypeWrapper);
+DEFINE_OBJECT_VTABLE(QQmlScopedEnumWrapper);
-void Heap::QmlTypeWrapper::init()
+void Heap::QQmlTypeWrapper::init()
{
Object::init();
mode = IncludeEnums;
object.init();
}
-void Heap::QmlTypeWrapper::destroy()
+void Heap::QQmlTypeWrapper::destroy()
{
if (typeNamespace)
typeNamespace->release();
@@ -69,12 +70,12 @@ void Heap::QmlTypeWrapper::destroy()
Object::destroy();
}
-bool QmlTypeWrapper::isSingleton() const
+bool QQmlTypeWrapper::isSingleton() const
{
return d()->type && d()->type->isSingleton();
}
-QObject* QmlTypeWrapper::singletonObject() const
+QObject* QQmlTypeWrapper::singletonObject() const
{
if (!isSingleton())
return 0;
@@ -85,7 +86,7 @@ QObject* QmlTypeWrapper::singletonObject() const
return siinfo->qobjectApi(e);
}
-QVariant QmlTypeWrapper::toVariant() const
+QVariant QQmlTypeWrapper::toVariant() const
{
if (d()->type && d()->type->isSingleton()) {
QQmlEngine *e = engine()->qmlEngine();
@@ -103,27 +104,27 @@ QVariant QmlTypeWrapper::toVariant() const
// Returns a type wrapper for type t on o. This allows access of enums, and attached properties.
-ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlType *t,
- Heap::QmlTypeWrapper::TypeNameMode mode)
+ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlType *t,
+ Heap::QQmlTypeWrapper::TypeNameMode mode)
{
Q_ASSERT(t);
Scope scope(engine);
- Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QmlTypeWrapper>());
+ Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QQmlTypeWrapper>());
w->d()->mode = mode; w->d()->object = o; w->d()->type = t;
return w.asReturnedValue();
}
// Returns a type wrapper for importNamespace (of t) on o. This allows nested resolution of a type in a
// namespace.
-ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlTypeNameCache *t, const void *importNamespace,
- Heap::QmlTypeWrapper::TypeNameMode mode)
+ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlTypeNameCache *t, const void *importNamespace,
+ Heap::QQmlTypeWrapper::TypeNameMode mode)
{
Q_ASSERT(t);
Q_ASSERT(importNamespace);
Scope scope(engine);
- Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QmlTypeWrapper>());
+ Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QQmlTypeWrapper>());
w->d()->mode = mode; w->d()->object = o; w->d()->typeNamespace = t; w->d()->importNamespace = importNamespace;
t->addref();
return w.asReturnedValue();
@@ -157,14 +158,14 @@ static ReturnedValue throwLowercaseEnumError(QV4::ExecutionEngine *v4, String *n
return v4->throwTypeError(message);
}
-ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasProperty)
+ReturnedValue QQmlTypeWrapper::get(const Managed *m, String *name, bool *hasProperty)
{
- Q_ASSERT(m->as<QmlTypeWrapper>());
+ Q_ASSERT(m->as<QQmlTypeWrapper>());
- QV4::ExecutionEngine *v4 = static_cast<const QmlTypeWrapper *>(m)->engine();
+ QV4::ExecutionEngine *v4 = static_cast<const QQmlTypeWrapper *>(m)->engine();
QV4::Scope scope(v4);
- Scoped<QmlTypeWrapper> w(scope, static_cast<const QmlTypeWrapper *>(m));
+ Scoped<QQmlTypeWrapper> w(scope, static_cast<const QQmlTypeWrapper *>(m));
if (hasProperty)
*hasProperty = true;
@@ -186,7 +187,7 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope
if (qobjectSingleton) {
// check for enum value
- const bool includeEnums = w->d()->mode == Heap::QmlTypeWrapper::IncludeEnums;
+ const bool includeEnums = w->d()->mode == Heap::QQmlTypeWrapper::IncludeEnums;
if (includeEnums && name->startsWithUpper()) {
const int value = enumForSingleton(v4, name, qobjectSingleton, type);
if (value != -1)
@@ -224,6 +225,14 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope
if (ok)
return QV4::Primitive::fromInt32(value).asReturnedValue();
+ value = type->scopedEnumIndex(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok);
+ if (ok) {
+ Scoped<QQmlScopedEnumWrapper> enumWrapper(scope, v4->memoryManager->allocObject<QQmlScopedEnumWrapper>());
+ enumWrapper->d()->type = type;
+ enumWrapper->d()->scopeEnumIndex = value;
+ return enumWrapper.asReturnedValue();
+ }
+
// Fall through to base implementation
} else if (w->d()->object) {
@@ -280,13 +289,13 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope
}
-void QmlTypeWrapper::put(Managed *m, String *name, const Value &value)
+bool QQmlTypeWrapper::put(Managed *m, String *name, const Value &value)
{
- Q_ASSERT(m->as<QmlTypeWrapper>());
- QmlTypeWrapper *w = static_cast<QmlTypeWrapper *>(m);
+ Q_ASSERT(m->as<QQmlTypeWrapper>());
+ QQmlTypeWrapper *w = static_cast<QQmlTypeWrapper *>(m);
QV4::ExecutionEngine *v4 = w->engine();
if (v4->hasException)
- return;
+ return false;
QV4::Scope scope(v4);
QQmlContextData *context = v4->callingQmlContext();
@@ -297,7 +306,8 @@ void QmlTypeWrapper::put(Managed *m, String *name, const Value &value)
QQmlEngine *e = scope.engine->qmlEngine();
QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(QQmlEnginePrivate::get(e)), object);
if (ao)
- QV4::QObjectWrapper::setQmlProperty(v4, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, value);
+ return QV4::QObjectWrapper::setQmlProperty(v4, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, value);
+ return false;
} else if (type && type->isSingleton()) {
QQmlEngine *e = scope.engine->qmlEngine();
QQmlType::SingletonInstanceInfo *siinfo = type->singletonInstanceInfo();
@@ -305,21 +315,23 @@ void QmlTypeWrapper::put(Managed *m, String *name, const Value &value)
QObject *qobjectSingleton = siinfo->qobjectApi(e);
if (qobjectSingleton) {
- QV4::QObjectWrapper::setQmlProperty(v4, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, value);
+ return QV4::QObjectWrapper::setQmlProperty(v4, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, value);
} else if (!siinfo->scriptApi(e).isUndefined()) {
QV4::ScopedObject apiprivate(scope, QJSValuePrivate::convertedToValue(v4, siinfo->scriptApi(e)));
if (!apiprivate) {
QString error = QLatin1String("Cannot assign to read-only property \"") + name->toQString() + QLatin1Char('\"');
v4->throwError(error);
- return;
+ return false;
} else {
- apiprivate->put(name, value);
+ return apiprivate->put(name, value);
}
}
}
+
+ return false;
}
-PropertyAttributes QmlTypeWrapper::query(const Managed *m, String *name)
+PropertyAttributes QQmlTypeWrapper::query(const Managed *m, String *name)
{
// ### Implement more efficiently.
bool hasProperty = false;
@@ -327,11 +339,11 @@ PropertyAttributes QmlTypeWrapper::query(const Managed *m, String *name)
return hasProperty ? Attr_Data : Attr_Invalid;
}
-bool QmlTypeWrapper::isEqualTo(Managed *a, Managed *b)
+bool QQmlTypeWrapper::isEqualTo(Managed *a, Managed *b)
{
- Q_ASSERT(a->as<QV4::QmlTypeWrapper>());
- QV4::QmlTypeWrapper *qmlTypeWrapperA = static_cast<QV4::QmlTypeWrapper *>(a);
- if (QV4::QmlTypeWrapper *qmlTypeWrapperB = b->as<QV4::QmlTypeWrapper>())
+ Q_ASSERT(a->as<QV4::QQmlTypeWrapper>());
+ QV4::QQmlTypeWrapper *qmlTypeWrapperA = static_cast<QV4::QQmlTypeWrapper *>(a);
+ if (QV4::QQmlTypeWrapper *qmlTypeWrapperB = b->as<QV4::QQmlTypeWrapper>())
return qmlTypeWrapperA->toVariant() == qmlTypeWrapperB->toVariant();
else if (QV4::QObjectWrapper *qobjectWrapper = b->as<QV4::QObjectWrapper>())
return qmlTypeWrapperA->toVariant().value<QObject*>() == qobjectWrapper->object();
@@ -339,4 +351,64 @@ bool QmlTypeWrapper::isEqualTo(Managed *a, Managed *b)
return false;
}
+ReturnedValue QQmlTypeWrapper::instanceOf(const Object *typeObject, const Value &var)
+{
+ Q_ASSERT(typeObject->as<QV4::QQmlTypeWrapper>());
+ const QV4::QQmlTypeWrapper *typeWrapper = static_cast<const QV4::QQmlTypeWrapper *>(typeObject);
+ QV4::ExecutionEngine *engine = typeObject->internalClass()->engine;
+ QQmlEnginePrivate *qenginepriv = QQmlEnginePrivate::get(engine->qmlEngine());
+
+ // can only compare a QObject* against a QML type
+ const QObjectWrapper *wrapper = var.as<QObjectWrapper>();
+ if (!wrapper)
+ return engine->throwTypeError();
+
+ // in case the wrapper outlived the QObject*
+ const QObject *wrapperObject = wrapper->object();
+ if (!wrapperObject)
+ return engine->throwTypeError();
+
+ const int myTypeId = typeWrapper->d()->type->typeId();
+ QQmlMetaObject myQmlType;
+ if (myTypeId == 0) {
+ // we're a composite type; a composite type cannot be equal to a
+ // non-composite object instance (Rectangle{} is never an instance of
+ // CustomRectangle)
+ QQmlData *theirDData = QQmlData::get(wrapperObject, /*create=*/false);
+ Q_ASSERT(theirDData); // must exist, otherwise how do we have a QObjectWrapper for it?!
+ if (!theirDData->compilationUnit)
+ return Encode(false);
+
+ QQmlTypeData *td = qenginepriv->typeLoader.getType(typeWrapper->d()->type->sourceUrl());
+ CompiledData::CompilationUnit *cu = td->compilationUnit();
+ myQmlType = qenginepriv->metaObjectForType(cu->metaTypeId);
+ } else {
+ myQmlType = qenginepriv->metaObjectForType(myTypeId);
+ }
+
+ const QMetaObject *theirType = wrapperObject->metaObject();
+
+ return QV4::Encode(QQmlMetaObject::canConvert(theirType, myQmlType));
+}
+
+ReturnedValue QQmlScopedEnumWrapper::get(const Managed *m, String *name, bool *hasProperty)
+{
+ Q_ASSERT(m->as<QQmlScopedEnumWrapper>());
+ const QQmlScopedEnumWrapper *resource = static_cast<const QQmlScopedEnumWrapper *>(m);
+ QV4::ExecutionEngine *v4 = resource->engine();
+ QV4::Scope scope(v4);
+
+ QQmlType *type = resource->d()->type;
+ int index = resource->d()->scopeEnumIndex;
+
+ bool ok = false;
+ int value = type->scopedEnumValue(QQmlEnginePrivate::get(v4->qmlEngine()), index, name, &ok);
+ if (hasProperty)
+ *hasProperty = ok;
+ if (ok)
+ return QV4::Primitive::fromInt32(value).asReturnedValue();
+
+ return Encode::undefined();
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h
index 3b0ae04cc1..730bfd6d12 100644
--- a/src/qml/qml/qqmltypewrapper_p.h
+++ b/src/qml/qml/qqmltypewrapper_p.h
@@ -65,7 +65,7 @@ namespace QV4 {
namespace Heap {
-struct QmlTypeWrapper : Object {
+struct QQmlTypeWrapper : Object {
enum TypeNameMode {
IncludeEnums,
ExcludeEnums
@@ -81,11 +81,18 @@ struct QmlTypeWrapper : Object {
const void *importNamespace;
};
+struct QQmlScopedEnumWrapper : Object {
+ void init() { Object::init(); }
+ void destroy() { Object::destroy(); }
+ int scopeEnumIndex;
+ QQmlType *type;
+};
+
}
-struct Q_QML_EXPORT QmlTypeWrapper : Object
+struct Q_QML_EXPORT QQmlTypeWrapper : Object
{
- V4_OBJECT2(QmlTypeWrapper, Object)
+ V4_OBJECT2(QQmlTypeWrapper, Object)
V4_NEEDS_DESTROY
bool isSingleton() const;
@@ -94,16 +101,24 @@ struct Q_QML_EXPORT QmlTypeWrapper : Object
QVariant toVariant() const;
static ReturnedValue create(ExecutionEngine *, QObject *, QQmlType *,
- Heap::QmlTypeWrapper::TypeNameMode = Heap::QmlTypeWrapper::IncludeEnums);
+ Heap::QQmlTypeWrapper::TypeNameMode = Heap::QQmlTypeWrapper::IncludeEnums);
static ReturnedValue create(ExecutionEngine *, QObject *, QQmlTypeNameCache *, const void *,
- Heap::QmlTypeWrapper::TypeNameMode = Heap::QmlTypeWrapper::IncludeEnums);
+ Heap::QQmlTypeWrapper::TypeNameMode = Heap::QQmlTypeWrapper::IncludeEnums);
static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
- static void put(Managed *m, String *name, const Value &value);
+ static bool put(Managed *m, String *name, const Value &value);
static PropertyAttributes query(const Managed *, String *name);
static bool isEqualTo(Managed *that, Managed *o);
+ static ReturnedValue instanceOf(const Object *typeObject, const Value &var);
+};
+struct Q_QML_EXPORT QQmlScopedEnumWrapper : Object
+{
+ V4_OBJECT2(QQmlScopedEnumWrapper, Object)
+ V4_NEEDS_DESTROY
+
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
};
}
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 41bb85c351..ce47ab9fa9 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -51,9 +51,11 @@
#include <private/qv4alloca_p.h>
#include <private/qv4objectiterator_p.h>
#include <private/qv4qobjectwrapper_p.h>
+#include <QtCore/qloggingcategory.h>
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcBindingRemoval)
DEFINE_OBJECT_VTABLE(QV4::QQmlValueTypeWrapper);
@@ -409,13 +411,13 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha
#undef VALUE_TYPE_ACCESSOR
}
-void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
+bool QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
{
Q_ASSERT(m->as<QQmlValueTypeWrapper>());
ExecutionEngine *v4 = static_cast<QQmlValueTypeWrapper *>(m)->engine();
Scope scope(v4);
if (scope.hasException())
- return;
+ return false;
Scoped<QQmlValueTypeWrapper> r(scope, static_cast<QQmlValueTypeWrapper *>(m));
Scoped<QQmlValueTypeReference> reference(scope, m->d());
@@ -426,7 +428,7 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
QMetaProperty writebackProperty = reference->d()->object->metaObject()->property(reference->d()->property);
if (!writebackProperty.isWritable() || !reference->readReferenceValue())
- return;
+ return false;
writeBackPropertyType = writebackProperty.userType();
}
@@ -434,17 +436,20 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
const QMetaObject *metaObject = r->d()->propertyCache()->metaObject();
const QQmlPropertyData *pd = r->d()->propertyCache()->property(name, 0, 0);
if (!pd)
- return;
+ return false;
if (reference) {
QV4::ScopedFunctionObject f(scope, value);
+ const QQmlQPointer<QObject> &referenceObject = reference->d()->object;
+ const int referencePropertyIndex = reference->d()->property;
+
if (f) {
if (!f->isBinding()) {
// assigning a JS function to a non-var-property is not allowed.
QString error = QStringLiteral("Cannot assign JavaScript function to value-type property");
ScopedString e(scope, v4->newString(error));
v4->throwError(e);
- return;
+ return false;
}
QQmlContextData *context = v4->callingQmlContext();
@@ -452,18 +457,31 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
QQmlPropertyData cacheData;
cacheData.setWritable(true);
cacheData.setPropType(writeBackPropertyType);
- cacheData.setCoreIndex(reference->d()->property);
+ cacheData.setCoreIndex(referencePropertyIndex);
QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f);
QV4::ScopedContext ctx(scope, bindingFunction->scope());
- QQmlBinding *newBinding = QQmlBinding::create(&cacheData, bindingFunction->function(), reference->d()->object, context, ctx);
+ QQmlBinding *newBinding = QQmlBinding::create(&cacheData, bindingFunction->function(), referenceObject, context, ctx);
newBinding->setSourceLocation(bindingFunction->currentLocation());
- newBinding->setTarget(reference->d()->object, cacheData, pd);
+ newBinding->setTarget(referenceObject, cacheData, pd);
QQmlPropertyPrivate::setBinding(newBinding);
- return;
+ return true;
} else {
- QQmlPropertyPrivate::removeBinding(reference->d()->object, QQmlPropertyIndex(reference->d()->property, pd->coreIndex()));
+ if (Q_UNLIKELY(lcBindingRemoval().isInfoEnabled())) {
+ if (auto binding = QQmlPropertyPrivate::binding(referenceObject, QQmlPropertyIndex(referencePropertyIndex, pd->coreIndex()))) {
+ Q_ASSERT(!binding->isValueTypeProxy());
+ const auto qmlBinding = static_cast<const QQmlBinding*>(binding);
+ const auto stackFrame = v4->currentStackFrame();
+ qCInfo(lcBindingRemoval,
+ "Overwriting binding on %s::%s which was initially bound at %s by setting \"%s\" at %s:%d",
+ referenceObject->metaObject()->className(), referenceObject->metaObject()->property(referencePropertyIndex).name(),
+ qPrintable(qmlBinding->expressionIdentifier()),
+ metaObject->property(pd->coreIndex()).name(),
+ qPrintable(stackFrame.source), stackFrame.line);
+ }
+ }
+ QQmlPropertyPrivate::removeBinding(referenceObject, QQmlPropertyIndex(referencePropertyIndex, pd->coreIndex()));
}
}
@@ -495,6 +513,8 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
QMetaObject::metacall(reference->d()->object, QMetaObject::WriteProperty, reference->d()->property, a);
}
}
+
+ return true;
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index 87f9116056..c8aac719ab 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -106,7 +106,7 @@ public:
bool write(QObject *target, int propertyIndex) const;
static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
- static void put(Managed *m, String *name, const Value &value);
+ static bool put(Managed *m, String *name, const Value &value);
static bool isEqualTo(Managed *m, Managed *other);
static PropertyAttributes query(const Managed *, String *name);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 490a4e19ab..a2ab9bdfed 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -104,8 +104,10 @@ void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *)
if (v4) {
QV4::Scope scope(v4);
QV4::Scoped<QV4::MemberData> sp(scope, m_target->propertyAndMethodStorage.value());
- if (sp)
- *(sp->data() + m_index) = QV4::Primitive::nullValue();
+ if (sp) {
+ QV4::MemberData::Index index{ sp->d(), sp->d()->values.values + m_index };
+ index.set(v4, QV4::Primitive::nullValue());
+ }
}
m_target->activate(m_target->object, m_target->methodOffset() + m_index, 0);
@@ -329,7 +331,7 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
if (size) {
QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, size);
propertyAndMethodStorage.set(v4, data);
- std::fill(data->data, data->data + data->size, QV4::Encode::undefined());
+ std::fill(data->values.values, data->values.values + data->values.size, QV4::Encode::undefined());
}
// Need JS wrapper to ensure properties/methods are marked.
@@ -364,77 +366,77 @@ void QQmlVMEMetaObject::writeProperty(int id, int v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = QV4::Primitive::fromInt32(v);
+ md->set(cache->engine, id, QV4::Primitive::fromInt32(v));
}
void QQmlVMEMetaObject::writeProperty(int id, bool v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = QV4::Primitive::fromBoolean(v);
+ md->set(cache->engine, id, QV4::Primitive::fromBoolean(v));
}
void QQmlVMEMetaObject::writeProperty(int id, double v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = QV4::Primitive::fromDouble(v);
+ md->set(cache->engine, id, QV4::Primitive::fromDouble(v));
}
void QQmlVMEMetaObject::writeProperty(int id, const QString& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = cache->engine->newString(v);
+ md->set(cache->engine, id, cache->engine->newString(v));
}
void QQmlVMEMetaObject::writeProperty(int id, const QUrl& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
+ md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v)));
}
void QQmlVMEMetaObject::writeProperty(int id, const QDate& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
+ md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v)));
}
void QQmlVMEMetaObject::writeProperty(int id, const QDateTime& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
+ md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v)));
}
void QQmlVMEMetaObject::writeProperty(int id, const QPointF& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
+ md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v)));
}
void QQmlVMEMetaObject::writeProperty(int id, const QSizeF& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
+ md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v)));
}
void QQmlVMEMetaObject::writeProperty(int id, const QRectF& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
+ md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v)));
}
void QQmlVMEMetaObject::writeProperty(int id, QObject* v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = QV4::QObjectWrapper::wrap(cache->engine, v);
+ md->set(cache->engine, id, QV4::Value::fromReturnedValue(QV4::QObjectWrapper::wrap(cache->engine, v)));
QQmlVMEVariantQObjectPtr *guard = getQObjectGuardForProperty(id);
if (v && !guard) {
@@ -592,7 +594,7 @@ QList<QObject *> *QQmlVMEMetaObject::readPropertyAsList(int id) const
if (!v || (int)v->d()->data().userType() != qMetaTypeId<QList<QObject *> >()) {
QVariant variant(qVariantFromValue(QList<QObject*>()));
v = cache->engine->newVariantObject(variant);
- *(md->data() + id) = v;
+ md->set(cache->engine, id, v);
}
return static_cast<QList<QObject *> *>(v->d()->data().data());
}
@@ -742,7 +744,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
Q_ASSERT(fallbackMetaType != QMetaType::UnknownType);
if (QV4::MemberData *md = propertyAndMethodStorageAsMemberData()) {
QVariant propertyAsVariant;
- if (QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>())
+ if (const QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>())
propertyAsVariant = v->d()->data();
QQml_valueTypeProvider()->readValueType(propertyAsVariant, a[0], fallbackMetaType);
}
@@ -815,9 +817,9 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
case QV4::CompiledData::Property::Quaternion:
Q_ASSERT(fallbackMetaType != QMetaType::UnknownType);
if (QV4::MemberData *md = propertyAndMethodStorageAsMemberData()) {
- QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
+ const QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
if (!v) {
- *(md->data() + id) = cache->engine->newVariantObject(QVariant());
+ md->set(cache->engine, id, cache->engine->newVariantObject(QVariant()));
v = (md->data() + id)->as<QV4::VariantObject>();
QQml_valueTypeProvider()->initValueType(fallbackMetaType, v->d()->data());
}
@@ -1028,7 +1030,7 @@ void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value)
// Importantly, if the current value is a scarce resource, we need to ensure that it
// gets automatically released by the engine if no other references to it exist.
- QV4::VariantObject *oldVariant = (md->data() + id)->as<QV4::VariantObject>();
+ const QV4::VariantObject *oldVariant = (md->data() + id)->as<QV4::VariantObject>();
if (oldVariant)
oldVariant->removeVmePropertyReference();
@@ -1054,7 +1056,7 @@ void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value)
guard->setGuardedValue(valueObject, this, id);
// Write the value and emit change signal as appropriate.
- *(md->data() + id) = value;
+ md->set(cache->engine, id, value);
activate(object, methodOffset() + id, 0);
}
@@ -1067,7 +1069,7 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
// Importantly, if the current value is a scarce resource, we need to ensure that it
// gets automatically released by the engine if no other references to it exist.
- QV4::VariantObject *oldv = (md->data() + id)->as<QV4::VariantObject>();
+ const QV4::VariantObject *oldv = (md->data() + id)->as<QV4::VariantObject>();
if (oldv)
oldv->removeVmePropertyReference();
@@ -1081,7 +1083,7 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
// Write the value and emit change signal as appropriate.
QVariant currentValue = readPropertyAsVariant(id);
- *(md->data() + id) = newv;
+ md->set(cache->engine, id, newv);
if ((currentValue.userType() != value.userType() || currentValue != value))
activate(object, methodOffset() + id, 0);
} else {
@@ -1093,14 +1095,14 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
} else {
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md) {
- QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
+ const QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
needActivate = (!v ||
v->d()->data().userType() != value.userType() ||
v->d()->data() != value);
if (v)
v->removeVmePropertyReference();
- *(md->data() + id) = cache->engine->newVariantObject(value);
- v = static_cast<QV4::VariantObject *>(md->data() + id);
+ md->set(cache->engine, id, cache->engine->newVariantObject(value));
+ v = static_cast<const QV4::VariantObject *>(md->data() + id);
v->addVmePropertyReference();
}
}
@@ -1139,7 +1141,7 @@ void QQmlVMEMetaObject::setVmeMethod(int index, const QV4::Value &function)
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (!md)
return;
- *(md->data() + methodIndex + compiledObject->nProperties) = function;
+ md->set(cache->engine, methodIndex + compiledObject->nProperties, function);
}
QV4::ReturnedValue QQmlVMEMetaObject::vmeProperty(int index) const
@@ -1168,16 +1170,16 @@ void QQmlVMEMetaObject::ensureQObjectWrapper()
QV4::QObjectWrapper::wrap(v4, object);
}
-void QQmlVMEMetaObject::mark(QV4::ExecutionEngine *e)
+void QQmlVMEMetaObject::mark(QV4::MarkStack *markStack)
{
QV4::ExecutionEngine *v4 = cache ? cache->engine : 0;
- if (v4 != e)
+ if (v4 != markStack->engine)
return;
- propertyAndMethodStorage.markOnce(e);
+ propertyAndMethodStorage.markOnce(markStack);
if (QQmlVMEMetaObject *parent = parentVMEMetaObject())
- parent->mark(e);
+ parent->mark(markStack);
}
bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index bb6fede7c8..031a9a9ddd 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -203,7 +203,7 @@ public:
void ensureQObjectWrapper();
- void mark(QV4::ExecutionEngine *e);
+ void mark(QV4::MarkStack *markStack);
void connectAlias(int aliasId);
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index f3a39313c1..113ef0c412 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -1597,10 +1597,12 @@ struct QQmlXMLHttpRequestWrapper : Object {
QQmlXMLHttpRequest *request;
};
-struct QQmlXMLHttpRequestCtor : FunctionObject {
- void init(ExecutionEngine *engine);
+#define QQmlXMLHttpRequestCtorMembers(class, Member) \
+ Member(class, Pointer, Object *, proto)
- Pointer<Object> proto;
+DECLARE_HEAP_OBJECT(QQmlXMLHttpRequestCtor, FunctionObject) {
+ DECLARE_MARK_TABLE(QQmlXMLHttpRequestCtor);
+ void init(ExecutionEngine *engine);
};
}
@@ -1614,12 +1616,7 @@ struct QQmlXMLHttpRequestWrapper : public Object
struct QQmlXMLHttpRequestCtor : public FunctionObject
{
V4_OBJECT2(QQmlXMLHttpRequestCtor, FunctionObject)
- static void markObjects(Heap::Base *that, ExecutionEngine *e) {
- QQmlXMLHttpRequestCtor::Data *c = static_cast<QQmlXMLHttpRequestCtor::Data *>(that);
- if (c->proto)
- c->proto->mark(e);
- FunctionObject::markObjects(that, e);
- }
+
static void construct(const Managed *that, Scope &scope, QV4::CallData *)
{
Scoped<QQmlXMLHttpRequestCtor> ctor(scope, that->as<QQmlXMLHttpRequestCtor>());
@@ -1686,7 +1683,7 @@ void QQmlXMLHttpRequestCtor::setupProto()
ExecutionEngine *v4 = engine();
Scope scope(v4);
ScopedObject p(scope, v4->newObject());
- d()->proto = p->d();
+ d()->proto.set(scope.engine, p->d());
// Methods
p->defineDefaultProperty(QStringLiteral("open"), method_open);
@@ -1826,8 +1823,13 @@ void QQmlXMLHttpRequestCtor::method_send(const QV4::BuiltinFunction *, QV4::Scop
THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
QByteArray data;
- if (callData->argc > 0)
- data = callData->args[0].toQStringNoThrow().toUtf8();
+ if (callData->argc > 0) {
+ if (const ArrayBuffer *buffer = callData->args[0].as<ArrayBuffer>()) {
+ data = buffer->asByteArray();
+ } else {
+ data = callData->args[0].toQStringNoThrow().toUtf8();
+ }
+ }
scope.result = r->send(w, scope.engine->callingQmlContext(), data);
}
diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp
index 7607c19374..e218cdcfe4 100644
--- a/src/qml/types/qqmlconnections.cpp
+++ b/src/qml/types/qqmlconnections.cpp
@@ -235,14 +235,13 @@ void QQmlConnectionsParser::verifyBindings(const QV4::CompiledData::Unit *qmlUni
{
for (int ii = 0; ii < props.count(); ++ii) {
const QV4::CompiledData::Binding *binding = props.at(ii);
- QString propName = qmlUnit->stringAt(binding->propertyNameIndex);
+ const QString &propName = qmlUnit->stringAt(binding->propertyNameIndex);
- if (!propName.startsWith(QLatin1String("on")) || !propName.at(2).isUpper()) {
+ if (!propName.startsWith(QLatin1String("on")) || (propName.length() < 3 || !propName.at(2).isUpper())) {
error(props.at(ii), QQmlConnections::tr("Cannot assign to non-existent property \"%1\"").arg(propName));
return;
}
-
if (binding->type >= QV4::CompiledData::Binding::Type_Object) {
const QV4::CompiledData::Object *target = qmlUnit->objectAt(binding->value.objectIndex);
if (!qmlUnit->stringAt(target->inheritedTypeNameIndex).isEmpty())
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index 8f4b9cd519..9620df6af9 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -988,7 +988,9 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, bo
}
}
- cacheItem->incubateObject(
+ QQmlComponentPrivate *cp = QQmlComponentPrivate::get(m_delegate);
+ cp->incubateObject(
+ cacheItem->incubationTask,
m_delegate,
m_context->engine(),
ctxt,
@@ -1935,30 +1937,6 @@ void QQmlDelegateModelItem::Dispose()
delete this;
}
-/*
- This is essentially a copy of QQmlComponent::create(); except it takes the QQmlContextData
- arguments instead of QQmlContext which means we don't have to construct the rather weighty
- wrapper class for every delegate item.
-*/
-void QQmlDelegateModelItem::incubateObject(
- QQmlComponent *component,
- QQmlEngine *engine,
- QQmlContextData *context,
- QQmlContextData *forContext)
-{
- QQmlIncubatorPrivate *incubatorPriv = QQmlIncubatorPrivate::get(incubationTask);
- QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(engine);
- QQmlComponentPrivate *componentPriv = QQmlComponentPrivate::get(component);
-
- incubatorPriv->compilationUnit = componentPriv->compilationUnit;
- incubatorPriv->compilationUnit->addref();
- incubatorPriv->enginePriv = enginePriv;
- incubatorPriv->creator.reset(new QQmlObjectCreator(context, componentPriv->compilationUnit, componentPriv->creationContext));
- incubatorPriv->subComponentToCreate = componentPriv->start;
-
- enginePriv->incubate(*incubationTask, forContext);
-}
-
void QQmlDelegateModelItem::destroyObject()
{
Q_ASSERT(object);
diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h
index cb4a1f79ba..4ebfd9b938 100644
--- a/src/qml/types/qqmldelegatemodel_p_p.h
+++ b/src/qml/types/qqmldelegatemodel_p_p.h
@@ -112,11 +112,6 @@ public:
QObject *modelObject() { return this; }
- void incubateObject(
- QQmlComponent *component,
- QQmlEngine *engine,
- QQmlContextData *context,
- QQmlContextData *forContext);
void destroyObject();
static QQmlDelegateModelItem *dataForObject(QObject *object);
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index 9d0f1afb32..20000557ee 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -359,7 +359,7 @@ int ListModel::appendElement()
void ListModel::insertElement(int index)
{
newElement(index);
- updateCacheIndices();
+ updateCacheIndices(index);
}
void ListModel::move(int from, int to, int n)
@@ -381,7 +381,7 @@ void ListModel::move(int from, int to, int n)
for (int i=0 ; i < store.count() ; ++i)
elements[from+i] = store[i];
- updateCacheIndices();
+ updateCacheIndices(from, to + n);
}
void ListModel::newElement(int index)
@@ -390,9 +390,14 @@ void ListModel::newElement(int index)
elements.insert(index, e);
}
-void ListModel::updateCacheIndices()
+void ListModel::updateCacheIndices(int start, int end)
{
- for (int i=0 ; i < elements.count() ; ++i) {
+ int count = elements.count();
+
+ if (end < 0 || end > count)
+ end = count;
+
+ for (int i = start; i < end; ++i) {
ListElement *e = elements.at(i);
if (ModelNodeMetaObject *mo = e->objectCache())
mo->m_elementIndex = i;
@@ -574,7 +579,7 @@ void ListModel::remove(int index, int count)
delete elements[index+i];
}
elements.remove(index, count);
- updateCacheIndices();
+ updateCacheIndices(index);
}
void ListModel::insert(int elementIndex, QV4::Object *object)
@@ -1334,7 +1339,7 @@ void ModelNodeMetaObject::emitDirectNotifies(const int *changedRoles, int roleCo
namespace QV4 {
-void ModelObject::put(Managed *m, String *name, const Value &value)
+bool ModelObject::put(Managed *m, String *name, const Value &value)
{
ModelObject *that = static_cast<ModelObject*>(m);
@@ -1348,6 +1353,7 @@ void ModelObject::put(Managed *m, String *name, const Value &value)
ModelNodeMetaObject *mo = ModelNodeMetaObject::get(that->object());
if (mo->initialized())
mo->emitPropertyNotification(name->toQString().toUtf8());
+ return true;
}
ReturnedValue ModelObject::get(const Managed *m, String *name, bool *hasProperty)
@@ -1983,12 +1989,12 @@ void QQmlListModel::setDynamicRoles(bool enableDynamicRoles)
if (m_mainThread && m_agent == 0) {
if (enableDynamicRoles) {
if (m_layout->roleCount())
- qmlWarning(this) << tr("unable to enable dynamic roles as this model is not empty!");
+ qmlWarning(this) << tr("unable to enable dynamic roles as this model is not empty");
else
m_dynamicRoles = true;
} else {
if (m_roles.count()) {
- qmlWarning(this) << tr("unable to enable static roles as this model is not empty!");
+ qmlWarning(this) << tr("unable to enable static roles as this model is not empty");
} else {
m_dynamicRoles = false;
}
diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h
index cdce78e542..e2653c220d 100644
--- a/src/qml/types/qqmllistmodel_p_p.h
+++ b/src/qml/types/qqmllistmodel_p_p.h
@@ -179,7 +179,7 @@ struct ModelObject : public QObjectWrapper {
struct ModelObject : public QObjectWrapper
{
- static void put(Managed *m, String *name, const Value& value);
+ static bool put(Managed *m, String *name, const Value& value);
static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
@@ -397,7 +397,7 @@ private:
void newElement(int index);
- void updateCacheIndices();
+ void updateCacheIndices(int start = 0, int end = -1);
friend class ListElement;
friend class QQmlListModelWorkerAgent;
diff --git a/src/qml/types/qquickpackage.cpp b/src/qml/types/qquickpackage.cpp
index 7fb14a95f6..e0d1888f33 100644
--- a/src/qml/types/qquickpackage.cpp
+++ b/src/qml/types/qquickpackage.cpp
@@ -89,7 +89,7 @@ public:
{
DataGuard(QObject *obj, QList<DataGuard> *l) : list(l) { (QQmlGuard<QObject>&)*this = obj; }
QList<DataGuard> *list;
- void objectDestroyed(QObject *) {
+ void objectDestroyed(QObject *) override {
// we assume priv will always be destroyed after objectDestroyed calls
list->removeOne(*this);
}
diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp
index d4aa2e19ed..b9f6ea461a 100644
--- a/src/qml/util/qqmladaptormodel.cpp
+++ b/src/qml/util/qqmladaptormodel.cpp
@@ -102,8 +102,8 @@ public:
virtual QVariant value(int role) const = 0;
virtual void setValue(int role, const QVariant &value) = 0;
- void setValue(const QString &role, const QVariant &value);
- bool resolveIndex(const QQmlAdaptorModel &model, int idx);
+ void setValue(const QString &role, const QVariant &value) override;
+ bool resolveIndex(const QQmlAdaptorModel &model, int idx) override;
static QV4::ReturnedValue get_property(QV4::CallContext *ctx, uint propertyId);
static QV4::ReturnedValue set_property(QV4::CallContext *ctx, uint propertyId);
@@ -140,7 +140,7 @@ public:
const QList<QQmlDelegateModelItem *> &items,
int index,
int count,
- const QVector<int> &roles) const
+ const QVector<int> &roles) const override
{
bool changed = roles.isEmpty() && !watchedRoles.isEmpty();
if (!changed && !watchedRoles.isEmpty() && watchedRoleIds.isEmpty()) {
@@ -184,7 +184,7 @@ public:
void replaceWatchedRoles(
QQmlAdaptorModel &,
const QList<QByteArray> &oldRoles,
- const QList<QByteArray> &newRoles) const
+ const QList<QByteArray> &newRoles) const override
{
VDMModelDelegateDataType *dataType = const_cast<VDMModelDelegateDataType *>(this);
@@ -237,12 +237,12 @@ public:
// QAbstractDynamicMetaObject
- void objectDestroyed(QObject *)
+ void objectDestroyed(QObject *) override
{
release();
}
- int metaCall(QObject *object, QMetaObject::Call call, int id, void **arguments)
+ int metaCall(QObject *object, QMetaObject::Call call, int id, void **arguments) override
{
return static_cast<QQmlDMCachedModelData *>(object)->metaCall(call, id, arguments);
}
@@ -413,18 +413,18 @@ public:
}
}
- QVariant value(int role) const
+ QVariant value(int role) const override
{
return type->model->aim()->index(index, 0, type->model->rootIndex).data(role);
}
- void setValue(int role, const QVariant &value)
+ void setValue(int role, const QVariant &value) override
{
type->model->aim()->setData(
type->model->aim()->index(index, 0, type->model->rootIndex), value, role);
}
- QV4::ReturnedValue get()
+ QV4::ReturnedValue get() override
{
if (type->prototype.isUndefined()) {
QQmlAdaptorModelEngineData * const data = engineData(v4);
@@ -447,12 +447,12 @@ public:
{
}
- int count(const QQmlAdaptorModel &model) const
+ int count(const QQmlAdaptorModel &model) const override
{
return model.aim()->rowCount(model.rootIndex);
}
- void cleanup(QQmlAdaptorModel &model, QQmlDelegateModel *vdm) const
+ void cleanup(QQmlAdaptorModel &model, QQmlDelegateModel *vdm) const override
{
QAbstractItemModel * const aim = model.aim();
if (aim && vdm) {
@@ -475,7 +475,7 @@ public:
const_cast<VDMAbstractItemModelDataType *>(this)->release();
}
- QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const
+ QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override
{
QHash<QByteArray, int>::const_iterator it = roleNames.find(role.toUtf8());
if (it != roleNames.end()) {
@@ -487,26 +487,26 @@ public:
}
}
- QVariant parentModelIndex(const QQmlAdaptorModel &model) const
+ QVariant parentModelIndex(const QQmlAdaptorModel &model) const override
{
return model
? QVariant::fromValue(model.aim()->parent(model.rootIndex))
: QVariant();
}
- QVariant modelIndex(const QQmlAdaptorModel &model, int index) const
+ QVariant modelIndex(const QQmlAdaptorModel &model, int index) const override
{
return model
? QVariant::fromValue(model.aim()->index(index, 0, model.rootIndex))
: QVariant();
}
- bool canFetchMore(const QQmlAdaptorModel &model) const
+ bool canFetchMore(const QQmlAdaptorModel &model) const override
{
return model && model.aim()->canFetchMore(model.rootIndex);
}
- void fetchMore(QQmlAdaptorModel &model) const
+ void fetchMore(QQmlAdaptorModel &model) const override
{
if (model)
model.aim()->fetchMore(model.rootIndex);
@@ -516,7 +516,7 @@ public:
QQmlAdaptorModel &model,
QQmlDelegateModelItemMetaType *metaType,
QQmlEngine *engine,
- int index) const
+ int index) const override
{
VDMAbstractItemModelDataType *dataType = const_cast<VDMAbstractItemModelDataType *>(this);
if (!metaObject)
@@ -602,7 +602,7 @@ public:
RETURN_RESULT(QV4::Encode::undefined());
}
- QV4::ReturnedValue get()
+ QV4::ReturnedValue get() override
{
QQmlAdaptorModelEngineData *data = engineData(v4);
QV4::Scope scope(v4);
@@ -613,13 +613,13 @@ public:
return o.asReturnedValue();
}
- void setValue(const QString &role, const QVariant &value)
+ void setValue(const QString &role, const QVariant &value) override
{
if (role == QLatin1String("modelData"))
cachedData = value;
}
- bool resolveIndex(const QQmlAdaptorModel &model, int idx)
+ bool resolveIndex(const QQmlAdaptorModel &model, int idx) override
{
if (index == -1) {
index = idx;
@@ -646,12 +646,12 @@ class VDMListDelegateDataType : public QQmlAdaptorModel::Accessors
public:
inline VDMListDelegateDataType() {}
- int count(const QQmlAdaptorModel &model) const
+ int count(const QQmlAdaptorModel &model) const override
{
return model.list.count();
}
- QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const
+ QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override
{
return role == QLatin1String("modelData")
? model.list.at(index)
@@ -662,7 +662,7 @@ public:
QQmlAdaptorModel &model,
QQmlDelegateModelItemMetaType *metaType,
QQmlEngine *,
- int index) const
+ int index) const override
{
return new QQmlDMListAccessorData(
metaType,
@@ -689,7 +689,7 @@ public:
QObject *object);
QObject *modelData() const { return object; }
- QObject *proxiedObject() { return object; }
+ QObject *proxiedObject() override { return object; }
QPointer<QObject> object;
};
@@ -731,12 +731,12 @@ public:
free(metaObject);
}
- int count(const QQmlAdaptorModel &model) const
+ int count(const QQmlAdaptorModel &model) const override
{
return model.list.count();
}
- QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const
+ QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override
{
if (QObject *object = model.list.at(index).value<QObject *>())
return object->property(role.toUtf8());
@@ -747,7 +747,7 @@ public:
QQmlAdaptorModel &model,
QQmlDelegateModelItemMetaType *metaType,
QQmlEngine *,
- int index) const
+ int index) const override
{
VDMObjectDelegateDataType *dataType = const_cast<VDMObjectDelegateDataType *>(this);
if (!metaObject)
@@ -764,7 +764,7 @@ public:
metaObject = builder.toMetaObject();
}
- void cleanup(QQmlAdaptorModel &, QQmlDelegateModel *) const
+ void cleanup(QQmlAdaptorModel &, QQmlDelegateModel *) const override
{
const_cast<VDMObjectDelegateDataType *>(this)->release();
}
@@ -788,7 +788,7 @@ public:
m_type->release();
}
- int metaCall(QObject *o, QMetaObject::Call call, int id, void **arguments)
+ int metaCall(QObject *o, QMetaObject::Call call, int id, void **arguments) override
{
Q_ASSERT(o == m_data);
Q_UNUSED(o);
@@ -809,7 +809,7 @@ public:
}
}
- int createProperty(const char *name, const char *)
+ int createProperty(const char *name, const char *) override
{
if (!m_data->object)
return -1;
diff --git a/src/qml/util/qqmlpropertymap.cpp b/src/qml/util/qqmlpropertymap.cpp
index 6e6554f2c3..b54e8d901a 100644
--- a/src/qml/util/qqmlpropertymap.cpp
+++ b/src/qml/util/qqmlpropertymap.cpp
@@ -186,9 +186,8 @@ int QQmlPropertyMapMetaObject::createProperty(const char *name, const char *valu
Constructs a bindable map with parent object \a parent.
*/
QQmlPropertyMap::QQmlPropertyMap(QObject *parent)
-: QObject(*allocatePrivate(), parent)
+: QQmlPropertyMap(&staticMetaObject, parent)
{
- init(metaObject());
}
/*!
@@ -339,18 +338,13 @@ QVariant QQmlPropertyMap::updateValue(const QString &key, const QVariant &input)
}
/*! \internal */
-void QQmlPropertyMap::init(const QMetaObject *staticMetaObject)
+QQmlPropertyMap::QQmlPropertyMap(const QMetaObject *staticMetaObject, QObject *parent)
+ : QObject(*(new QQmlPropertyMapPrivate), parent)
{
Q_D(QQmlPropertyMap);
d->mo = new QQmlPropertyMapMetaObject(this, d, staticMetaObject);
}
-/*! \internal */
-QObjectPrivate *QQmlPropertyMap::allocatePrivate()
-{
- return new QQmlPropertyMapPrivate;
-}
-
/*!
\fn void QQmlPropertyMap::valueChanged(const QString &key, const QVariant &value)
This signal is emitted whenever one of the values in the map is changed. \a key
diff --git a/src/qml/util/qqmlpropertymap.h b/src/qml/util/qqmlpropertymap.h
index 01048f3662..8c5ecce48e 100644
--- a/src/qml/util/qqmlpropertymap.h
+++ b/src/qml/util/qqmlpropertymap.h
@@ -80,15 +80,13 @@ protected:
template<class DerivedType>
QQmlPropertyMap(DerivedType *derived, QObject *parentObj)
- : QObject(*allocatePrivate(), parentObj)
+ : QQmlPropertyMap(&DerivedType::staticMetaObject, parentObj)
{
Q_UNUSED(derived)
- init(&DerivedType::staticMetaObject);
}
private:
- void init(const QMetaObject *staticMetaObject);
- static QObjectPrivate *allocatePrivate();
+ QQmlPropertyMap(const QMetaObject *staticMetaObject, QObject *parent);
Q_DECLARE_PRIVATE(QQmlPropertyMap)
Q_DISABLE_COPY(QQmlPropertyMap)
diff --git a/src/qmltest/quicktestresult.cpp b/src/qmltest/quicktestresult.cpp
index 8c62196128..90d11e9734 100644
--- a/src/qmltest/quicktestresult.cpp
+++ b/src/qmltest/quicktestresult.cpp
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2017 Crimson AS <info@crimson.no>
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
@@ -61,7 +62,10 @@
#include <QtCore/QDir>
#include <QtQuick/qquickwindow.h>
#include <QtGui/qvector3d.h>
+#include <QtGui/qimagewriter.h>
#include <QtQml/private/qqmlglobal_p.h>
+#include <QtQml/QQmlEngine>
+#include <QtQml/QQmlContext>
#include <private/qv4qobjectwrapper_p.h>
#include <algorithm>
@@ -77,6 +81,11 @@ extern bool qWaitForSignal(QObject *obj, const char* signal, int timeout = 5000)
class Q_QUICK_TEST_EXPORT QuickTestImageObject : public QObject
{
Q_OBJECT
+
+ Q_PROPERTY(int width READ width CONSTANT)
+ Q_PROPERTY(int height READ height CONSTANT)
+ Q_PROPERTY(QSize size READ size CONSTANT)
+
public:
QuickTestImageObject(const QImage& img, QObject *parent = 0)
: QObject(parent)
@@ -127,6 +136,33 @@ public Q_SLOTS:
return m_image == other->m_image;
}
+
+ void save(const QString &filePath)
+ {
+ QImageWriter writer(filePath);
+ if (!writer.write(m_image)) {
+ QQmlEngine *engine = qmlContext(this)->engine();
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine->handle());
+ v4->throwError(QStringLiteral("Can't save to %1: %2").arg(filePath, writer.errorString()));
+ }
+ }
+
+public:
+ int width() const
+ {
+ return m_image.width();
+ }
+
+ int height() const
+ {
+ return m_image.height();
+ }
+
+ QSize size() const
+ {
+ return m_image.size();
+ }
+
private:
QImage m_image;
};
@@ -718,7 +754,9 @@ QObject *QuickTestResult::grabImage(QQuickItem *item)
QImage grabbed = window->grabWindow();
QRectF rf(item->x(), item->y(), item->width(), item->height());
rf = rf.intersected(QRectF(0, 0, grabbed.width(), grabbed.height()));
- return new QuickTestImageObject(grabbed.copy(rf.toAlignedRect()));
+ QObject *o = new QuickTestImageObject(grabbed.copy(rf.toAlignedRect()));
+ QQmlEngine::setContextForObject(o, qmlContext(this));
+ return o;
}
return 0;
}
diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp
index fbde5d354d..2d6bb02af4 100644
--- a/src/quick/accessible/qaccessiblequickitem.cpp
+++ b/src/quick/accessible/qaccessiblequickitem.cpp
@@ -142,9 +142,6 @@ QAccessibleInterface *QAccessibleQuickItem::child(int index) const
return 0;
QQuickItem *child = children.at(index);
- if (!child) // FIXME can this happen?
- return 0;
-
return QAccessible::queryAccessibleInterface(child);
}
diff --git a/src/quick/designer/qquickdesignersupport.cpp b/src/quick/designer/qquickdesignersupport.cpp
index 749ece8221..88971e3172 100644
--- a/src/quick/designer/qquickdesignersupport.cpp
+++ b/src/quick/designer/qquickdesignersupport.cpp
@@ -90,10 +90,11 @@ void QQuickDesignerSupport::refFromEffectItem(QQuickItem *referencedItem, bool h
QSGRenderContext *rc = QQuickWindowPrivate::get(referencedItem->window())->context;
QSGLayer *texture = rc->sceneGraphContext()->createLayer(rc);
+ QSizeF itemSize = referencedItem->size();
texture->setLive(true);
texture->setItem(QQuickItemPrivate::get(referencedItem)->rootNode());
- texture->setRect(referencedItem->boundingRect());
- texture->setSize(referencedItem->boundingRect().size().toSize());
+ texture->setRect(QRectF(QPointF(0, 0), itemSize));
+ texture->setSize(itemSize.toSize());
texture->setRecursive(true);
#if QT_CONFIG(opengl)
#ifndef QT_OPENGL_ES
diff --git a/src/quick/doc/images/declarative-arcrotation.png b/src/quick/doc/images/declarative-arcrotation.png
new file mode 100644
index 0000000000..03f009bc12
--- /dev/null
+++ b/src/quick/doc/images/declarative-arcrotation.png
Binary files differ
diff --git a/src/quick/doc/images/pathitem-code-example.png b/src/quick/doc/images/pathitem-code-example.png
new file mode 100644
index 0000000000..25dbe8b311
--- /dev/null
+++ b/src/quick/doc/images/pathitem-code-example.png
Binary files differ
diff --git a/src/quick/doc/images/visualpath-code-example.png b/src/quick/doc/images/visualpath-code-example.png
new file mode 100644
index 0000000000..429e85aa32
--- /dev/null
+++ b/src/quick/doc/images/visualpath-code-example.png
Binary files differ
diff --git a/src/quick/doc/snippets/qml/layerblending.qml b/src/quick/doc/snippets/qml/layerblending.qml
index a922f7896c..3e75a607a6 100644
--- a/src/quick/doc/snippets/qml/layerblending.qml
+++ b/src/quick/doc/snippets/qml/layerblending.qml
@@ -62,7 +62,7 @@ Item {
uniform highp vec2 pixelSize;
varying highp vec2 qt_TexCoord0;
void main() {
- highp vec2 tc = sign(sin(3.14152 * qt_TexCoord0 * pixelSize));
+ highp vec2 tc = sign(sin(3.14159265358979323846 * qt_TexCoord0 * pixelSize));
if (tc.x != tc.y)
gl_FragColor = color1;
else
diff --git a/src/quick/doc/snippets/qml/opacitymask.qml b/src/quick/doc/snippets/qml/opacitymask.qml
index beffb633d6..beb5cc6f67 100644
--- a/src/quick/doc/snippets/qml/opacitymask.qml
+++ b/src/quick/doc/snippets/qml/opacitymask.qml
@@ -63,7 +63,7 @@ Item {
uniform highp vec2 pixelSize;
varying highp vec2 qt_TexCoord0;
void main() {
- highp vec2 tc = sign(sin(3.14152 * qt_TexCoord0 * pixelSize));
+ highp vec2 tc = sign(sin(3.14159265358979323846 * qt_TexCoord0 * pixelSize));
if (tc.x != tc.y)
gl_FragColor = color1;
else
diff --git a/src/quick/doc/snippets/qml/path/arcrotation.qml b/src/quick/doc/snippets/qml/path/arcrotation.qml
new file mode 100644
index 0000000000..c73d67ff17
--- /dev/null
+++ b/src/quick/doc/snippets/qml/path/arcrotation.qml
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** 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 The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+//![0]
+Path {
+ startX: 50; startY: 100
+
+ PathArc {
+ x: 150; y: 100
+ radiusX: 50; radiusY: 20
+ xAxisRotation: 45
+ }
+}
+//![0]
diff --git a/src/quick/doc/src/qmltypereference.qdoc b/src/quick/doc/src/qmltypereference.qdoc
index b0aa143505..7c7bdbc137 100644
--- a/src/quick/doc/src/qmltypereference.qdoc
+++ b/src/quick/doc/src/qmltypereference.qdoc
@@ -170,6 +170,7 @@ available when you import \c QtQuick.
\li \l enumeration \c font.capitalization
\li \l real \c font.letterSpacing
\li \l real \c font.wordSpacing
+ \li \l bool \c font.kerning
\li \l enumeration \c font.hintingPreference
\endlist
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index 5674326d6c..9ac7422a39 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -40,6 +40,7 @@
#include "qquickcontext2d_p.h"
#include "qquickcontext2dcommandbuffer_p.h"
#include "qquickcanvasitem_p.h"
+#include <private/qtquickglobal_p.h>
#include <private/qquickcontext2dtexture_p.h>
#include <private/qquickitem_p.h>
#if QT_CONFIG(quick_shadereffect)
@@ -129,8 +130,6 @@ QT_BEGIN_NAMESPACE
Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
-#define DEGREES(t) ((t) * 180.0 / M_PI)
-
#define CHECK_CONTEXT(r) if (!r || !r->d()->context || !r->d()->context->bufferValid()) \
THROW_GENERIC_ERROR("Not a Context2D object");
@@ -138,7 +137,7 @@ Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
THROW_GENERIC_ERROR("Not a Context2D object");
#define qClamp(val, min, max) qMin(qMax(val, min), max)
#define CHECK_RGBA(c) (c == '-' || c == '.' || (c >=0 && c <= 9))
-QColor qt_color_from_string(const QV4::Value &name)
+Q_QUICK_PRIVATE_EXPORT QColor qt_color_from_string(const QV4::Value &name)
{
QByteArray str = name.toQString().toUtf8();
@@ -905,7 +904,7 @@ struct QQuickJSContext2DPixelData : public QV4::Object
V4_NEEDS_DESTROY
static QV4::ReturnedValue getIndexed(const QV4::Managed *m, uint index, bool *hasProperty);
- static void putIndexed(QV4::Managed *m, uint index, const QV4::Value &value);
+ static bool putIndexed(QV4::Managed *m, uint index, const QV4::Value &value);
static void proto_get_length(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
};
@@ -929,9 +928,9 @@ struct QQuickJSContext2DImageData : public QV4::Object
static void method_get_height(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
static void method_get_data(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
- static void markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *engine) {
- static_cast<QQuickJSContext2DImageData::Data *>(that)->pixelData.mark(engine);
- QV4::Object::markObjects(that, engine);
+ static void markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack) {
+ static_cast<QQuickJSContext2DImageData::Data *>(that)->pixelData.mark(markStack);
+ QV4::Object::markObjects(that, markStack);
}
};
@@ -1643,7 +1642,7 @@ void QQuickJSContext2DPrototype::method_createConicalGradient(const QV4::Builtin
if (callData->argc >= 3) {
qreal x = callData->args[0].toNumber();
qreal y = callData->args[1].toNumber();
- qreal angle = DEGREES(callData->args[2].toNumber());
+ qreal angle = qRadiansToDegrees(callData->args[2].toNumber());
if (!qt_is_finite(x) || !qt_is_finite(y)) {
THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createConicalGradient(): Incorrect arguments");
}
@@ -3083,13 +3082,13 @@ QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed(const QV4::Managed *m,
return QV4::Encode::undefined();
}
-void QQuickJSContext2DPixelData::putIndexed(QV4::Managed *m, uint index, const QV4::Value &value)
+bool QQuickJSContext2DPixelData::putIndexed(QV4::Managed *m, uint index, const QV4::Value &value)
{
Q_ASSERT(m->as<QQuickJSContext2DPixelData>());
QV4::ExecutionEngine *v4 = static_cast<QQuickJSContext2DPixelData *>(m)->engine();
QV4::Scope scope(v4);
if (scope.hasException())
- return;
+ return false;
QV4::Scoped<QQuickJSContext2DPixelData> r(scope, static_cast<QQuickJSContext2DPixelData *>(m));
@@ -3115,7 +3114,10 @@ void QQuickJSContext2DPixelData::putIndexed(QV4::Managed *m, uint index, const Q
*pixel = qRgba(qRed(*pixel), qGreen(*pixel), qBlue(*pixel), v);
break;
}
+ return true;
}
+
+ return false;
}
/*!
\qmlmethod CanvasImageData QtQuick::Context2D::createImageData(real sw, real sh)
@@ -3367,7 +3369,7 @@ void QQuickContext2D::rotate(qreal angle)
return;
QTransform newTransform =state.matrix;
- newTransform.rotate(DEGREES(angle));
+ newTransform.rotate(qRadiansToDegrees(angle));
if (!newTransform.isInvertible()) {
state.invertibleCTM = false;
@@ -3376,7 +3378,7 @@ void QQuickContext2D::rotate(qreal angle)
state.matrix = newTransform;
buffer()->updateMatrix(state.matrix);
- m_path = QTransform().rotate(-DEGREES(angle)).map(m_path);
+ m_path = QTransform().rotate(-qRadiansToDegrees(angle)).map(m_path);
}
void QQuickContext2D::shear(qreal h, qreal v)
@@ -3773,8 +3775,8 @@ void QQuickContext2D::arc(qreal xc, qreal yc, qreal radius, qreal sar, qreal ear
antiClockWise = !antiClockWise;
//end hack
- float sa = DEGREES(sar);
- float ea = DEGREES(ear);
+ float sa = qRadiansToDegrees(sar);
+ float ea = qRadiansToDegrees(ear);
double span = 0;
diff --git a/src/quick/items/items.qrc b/src/quick/items/items.qrc
index 6aaf757c29..da9bf0c828 100644
--- a/src/quick/items/items.qrc
+++ b/src/quick/items/items.qrc
@@ -8,5 +8,9 @@
<file>shaders/shadereffect_core.vert</file>
<file>shaders/shadereffectfallback_core.frag</file>
<file>shaders/shadereffectfallback_core.vert</file>
+ <file>shaders/lineargradient.vert</file>
+ <file>shaders/lineargradient.frag</file>
+ <file>shaders/lineargradient_core.vert</file>
+ <file>shaders/lineargradient_core.frag</file>
</qresource>
</RCC>
diff --git a/src/quick/items/qquickanimatedimage_p.h b/src/quick/items/qquickanimatedimage_p.h
index 143fe8904d..54da093259 100644
--- a/src/quick/items/qquickanimatedimage_p.h
+++ b/src/quick/items/qquickanimatedimage_p.h
@@ -97,7 +97,6 @@ Q_SIGNALS:
void playingChanged();
void pausedChanged();
void frameChanged();
- void sourceSizeChanged();
private Q_SLOTS:
void movieUpdate();
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index 3bd647fed6..a3bc7635a1 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -254,6 +254,7 @@ QQuickFlickablePrivate::QQuickFlickablePrivate()
, flickBoost(1.0), fixupMode(Normal), vTime(0), visibleArea(0)
, flickableDirection(QQuickFlickable::AutoFlickDirection)
, boundsBehavior(QQuickFlickable::DragAndOvershootBounds)
+ , boundsMovement(QQuickFlickable::FollowBoundsBehavior)
, rebound(0)
{
}
@@ -563,18 +564,6 @@ void QQuickFlickablePrivate::updateBeginningEnd()
visibleArea->updateVisible();
}
-/*
-XXXTODO add docs describing moving, dragging, flicking properties, e.g.
-
-When the user starts dragging the Flickable, the dragging and moving properties
-will be true.
-
-If the velocity is sufficient when the drag is ended, flicking may begin.
-
-The moving properties will remain true until all dragging and flicking
-is finished.
-*/
-
/*!
\qmlsignal QtQuick::Flickable::dragStarted()
@@ -1573,16 +1562,18 @@ void QQuickFlickablePrivate::replayDelayedPress()
void QQuickFlickablePrivate::setViewportX(qreal x)
{
Q_Q(QQuickFlickable);
- if (pixelAligned)
- x = -Round(-x);
-
- contentItem->setX(x);
- if (contentItem->x() != x)
- return; // reentered
+ qreal effectiveX = pixelAligned ? -Round(-x) : x;
const qreal maxX = q->maxXExtent();
const qreal minX = q->minXExtent();
+ if (boundsMovement == int(QQuickFlickable::StopAtBounds))
+ effectiveX = qBound(maxX, effectiveX, minX);
+
+ contentItem->setX(effectiveX);
+ if (contentItem->x() != effectiveX)
+ return; // reentered
+
qreal overshoot = 0.0;
if (x <= maxX)
overshoot = maxX - x;
@@ -1598,16 +1589,18 @@ void QQuickFlickablePrivate::setViewportX(qreal x)
void QQuickFlickablePrivate::setViewportY(qreal y)
{
Q_Q(QQuickFlickable);
- if (pixelAligned)
- y = -Round(-y);
-
- contentItem->setY(y);
- if (contentItem->y() != y)
- return; // reentered
+ qreal effectiveY = pixelAligned ? -Round(-y) : y;
const qreal maxY = q->maxYExtent();
const qreal minY = q->minYExtent();
+ if (boundsMovement == int(QQuickFlickable::StopAtBounds))
+ effectiveY = qBound(maxY, effectiveY, minY);
+
+ contentItem->setY(effectiveY);
+ if (contentItem->y() != effectiveY)
+ return; // reentered
+
qreal overshoot = 0.0;
if (y <= maxY)
overshoot = maxY - y;
@@ -1867,8 +1860,9 @@ QQmlListProperty<QQuickItem> QQuickFlickable::flickableChildren()
beyond the Flickable's boundaries, or overshoot the
Flickable's boundaries when flicked.
- This enables the feeling that the edges of the view are soft,
- rather than a hard physical boundary.
+ When the \l boundsMovement is \c Flickable.FollowBoundsBehavior, a value
+ other than \c Flickable.StopAtBounds will give a feeling that the edges of
+ the view are soft, rather than a hard physical boundary.
The \c boundsBehavior can be one of:
@@ -1884,7 +1878,7 @@ QQmlListProperty<QQuickItem> QQuickFlickable::flickableChildren()
boundary when flicked.
\endlist
- \sa horizontalOvershoot, verticalOvershoot
+ \sa horizontalOvershoot, verticalOvershoot, boundsMovement
*/
QQuickFlickable::BoundsBehavior QQuickFlickable::boundsBehavior() const
{
@@ -2695,7 +2689,11 @@ void QQuickFlickablePrivate::updateVelocity()
The value is negative when the content is dragged or flicked beyond the beginning,
and positive when beyond the end; \c 0.0 otherwise.
- \sa verticalOvershoot, boundsBehavior
+ Whether the values are reported for dragging and/or flicking is determined by
+ \l boundsBehavior. The overshoot distance is reported even when \l boundsMovement
+ is \c Flickable.StopAtBounds.
+
+ \sa verticalOvershoot, boundsBehavior, boundsMovement
*/
qreal QQuickFlickable::horizontalOvershoot() const
{
@@ -2712,7 +2710,11 @@ qreal QQuickFlickable::horizontalOvershoot() const
The value is negative when the content is dragged or flicked beyond the beginning,
and positive when beyond the end; \c 0.0 otherwise.
- \sa horizontalOvershoot, boundsBehavior
+ Whether the values are reported for dragging and/or flicking is determined by
+ \l boundsBehavior. The overshoot distance is reported even when \l boundsMovement
+ is \c Flickable.StopAtBounds.
+
+ \sa horizontalOvershoot, boundsBehavior, boundsMovement
*/
qreal QQuickFlickable::verticalOvershoot() const
{
@@ -2720,6 +2722,68 @@ qreal QQuickFlickable::verticalOvershoot() const
return d->vData.overshoot;
}
+/*!
+ \qmlproperty enumeration QtQuick::Flickable::boundsMovement
+ \since 5.10
+
+ This property holds whether the flickable will give a feeling that the edges of the
+ view are soft, rather than a hard physical boundary.
+
+ The \c boundsMovement can be one of:
+
+ \list
+ \li Flickable.StopAtBounds - this allows implementing custom edge effects where the
+ contents do not follow drags or flicks beyond the bounds of the flickable. The values
+ of \l horizontalOvershoot and \l verticalOvershoot can be utilized to implement custom
+ edge effects.
+ \li Flickable.FollowBoundsBehavior (default) - whether the contents follow drags or
+ flicks beyond the bounds of the flickable is determined by \l boundsBehavior.
+ \endlist
+
+ The following example keeps the contents within bounds and instead applies a flip
+ effect when flicked over horizontal bounds:
+ \code
+ Flickable {
+ id: flickable
+ boundsMovement: Flickable.StopAtBounds
+ boundsBehavior: Flickable.DragAndOvershootBounds
+ transform: Rotation {
+ axis { x: 0; y: 1; z: 0 }
+ origin.x: flickable.width / 2
+ origin.y: flickable.height / 2
+ angle: Math.min(30, Math.max(-30, flickable.horizontalOvershoot))
+ }
+ }
+ \endcode
+
+ The following example keeps the contents within bounds and instead applies an opacity
+ effect when dragged over vertical bounds:
+ \code
+ Flickable {
+ boundsMovement: Flickable.StopAtBounds
+ boundsBehavior: Flickable.DragOverBounds
+ opacity: Math.max(0.5, 1.0 - Math.abs(verticalOvershoot) / height)
+ }
+ \endcode
+
+ \sa boundsBehavior, verticalOvershoot, horizontalOvershoot
+*/
+QQuickFlickable::BoundsMovement QQuickFlickable::boundsMovement() const
+{
+ Q_D(const QQuickFlickable);
+ return d->boundsMovement;
+}
+
+void QQuickFlickable::setBoundsMovement(BoundsMovement movement)
+{
+ Q_D(QQuickFlickable);
+ if (d->boundsMovement == movement)
+ return;
+
+ d->boundsMovement = movement;
+ emit boundsMovementChanged();
+}
+
QT_END_NAMESPACE
#include "moc_qquickflickable_p.cpp"
diff --git a/src/quick/items/qquickflickable_p.h b/src/quick/items/qquickflickable_p.h
index 52cade1472..7558ee7df8 100644
--- a/src/quick/items/qquickflickable_p.h
+++ b/src/quick/items/qquickflickable_p.h
@@ -80,6 +80,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickFlickable : public QQuickItem
Q_PROPERTY(qreal verticalVelocity READ verticalVelocity NOTIFY verticalVelocityChanged)
Q_PROPERTY(BoundsBehavior boundsBehavior READ boundsBehavior WRITE setBoundsBehavior NOTIFY boundsBehaviorChanged)
+ Q_PROPERTY(BoundsMovement boundsMovement READ boundsMovement WRITE setBoundsMovement NOTIFY boundsMovementChanged REVISION 10)
Q_PROPERTY(QQuickTransition *rebound READ rebound WRITE setRebound NOTIFY reboundChanged)
Q_PROPERTY(qreal maximumFlickVelocity READ maximumFlickVelocity WRITE setMaximumFlickVelocity NOTIFY maximumFlickVelocityChanged)
Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY flickDecelerationChanged)
@@ -132,6 +133,15 @@ public:
BoundsBehavior boundsBehavior() const;
void setBoundsBehavior(BoundsBehavior);
+ enum BoundsMovement {
+ // StopAtBounds = 0x0,
+ FollowBoundsBehavior = 0x1
+ };
+ Q_ENUM(BoundsMovement)
+
+ BoundsMovement boundsMovement() const;
+ void setBoundsMovement(BoundsMovement movement);
+
QQuickTransition *rebound() const;
void setRebound(QQuickTransition *transition);
@@ -237,6 +247,7 @@ Q_SIGNALS:
void flickableDirectionChanged();
void interactiveChanged();
void boundsBehaviorChanged();
+ Q_REVISION(10) void boundsMovementChanged();
void reboundChanged();
void maximumFlickVelocityChanged();
void flickDecelerationChanged();
diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h
index 1ceff22dfc..8609a15fcd 100644
--- a/src/quick/items/qquickflickable_p_p.h
+++ b/src/quick/items/qquickflickable_p_p.h
@@ -247,6 +247,7 @@ public:
QQuickFlickableVisibleArea *visibleArea;
QQuickFlickable::FlickableDirection flickableDirection;
QQuickFlickable::BoundsBehavior boundsBehavior;
+ QQuickFlickable::BoundsMovement boundsMovement;
QQuickTransition *rebound;
void viewportAxisMoved(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
diff --git a/src/quick/items/qquickgenericshadereffect.cpp b/src/quick/items/qquickgenericshadereffect.cpp
index b366071962..305ef7e778 100644
--- a/src/quick/items/qquickgenericshadereffect.cpp
+++ b/src/quick/items/qquickgenericshadereffect.cpp
@@ -546,7 +546,10 @@ void QQuickGenericShaderEffect::updateShaderVars(Shader shaderType)
// Have a QSignalMapper that emits mapped() with an index+type on each property change notify signal.
auto &sm(m_signalMappers[shaderType][i]);
if (!sm.mapper) {
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
sm.mapper = new QSignalMapper;
+QT_WARNING_POP
sm.mapper->setMapping(m_item, i | (shaderType << 16));
}
sm.active = true;
diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp
index dacb43a421..7e13e5e0e1 100644
--- a/src/quick/items/qquickimage.cpp
+++ b/src/quick/items/qquickimage.cpp
@@ -515,37 +515,41 @@ void QQuickImage::updatePaintedGeometry()
setImplicitSize(0, 0);
return;
}
- qreal w = widthValid() ? width() : d->pix.width();
- qreal widthScale = w / qreal(d->pix.width());
- qreal h = heightValid() ? height() : d->pix.height();
- qreal heightScale = h / qreal(d->pix.height());
+ const qreal pixWidth = d->pix.width() / d->devicePixelRatio;
+ const qreal pixHeight = d->pix.height() / d->devicePixelRatio;
+ const qreal w = widthValid() ? width() : pixWidth;
+ const qreal widthScale = w / pixWidth;
+ const qreal h = heightValid() ? height() : pixHeight;
+ const qreal heightScale = h / pixHeight;
if (widthScale <= heightScale) {
d->paintedWidth = w;
- d->paintedHeight = widthScale * qreal(d->pix.height());
+ d->paintedHeight = widthScale * pixHeight;
} else if (heightScale < widthScale) {
- d->paintedWidth = heightScale * qreal(d->pix.width());
+ d->paintedWidth = heightScale * pixWidth;
d->paintedHeight = h;
}
- qreal iHeight = (widthValid() && !heightValid()) ? d->paintedHeight : d->pix.height();
- qreal iWidth = (heightValid() && !widthValid()) ? d->paintedWidth : d->pix.width();
+ const qreal iHeight = (widthValid() && !heightValid()) ? d->paintedHeight : pixHeight;
+ const qreal iWidth = (heightValid() && !widthValid()) ? d->paintedWidth : pixWidth;
setImplicitSize(iWidth, iHeight);
} else if (d->fillMode == PreserveAspectCrop) {
if (!d->pix.width() || !d->pix.height())
return;
- qreal widthScale = width() / qreal(d->pix.width());
- qreal heightScale = height() / qreal(d->pix.height());
+ const qreal pixWidth = d->pix.width() / d->devicePixelRatio;
+ const qreal pixHeight = d->pix.height() / d->devicePixelRatio;
+ qreal widthScale = width() / pixWidth;
+ qreal heightScale = height() / pixHeight;
if (widthScale < heightScale) {
widthScale = heightScale;
} else if (heightScale < widthScale) {
heightScale = widthScale;
}
- d->paintedHeight = heightScale * qreal(d->pix.height());
- d->paintedWidth = widthScale * qreal(d->pix.width());
+ d->paintedHeight = heightScale * pixHeight;
+ d->paintedWidth = widthScale * pixWidth;
} else if (d->fillMode == Pad) {
- d->paintedWidth = d->pix.width();
- d->paintedHeight = d->pix.height();
+ d->paintedWidth = d->pix.width() / d->devicePixelRatio;
+ d->paintedHeight = d->pix.height() / d->devicePixelRatio;
} else {
d->paintedWidth = width();
d->paintedHeight = height();
@@ -556,7 +560,8 @@ void QQuickImage::updatePaintedGeometry()
void QQuickImage::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
QQuickImageBase::geometryChanged(newGeometry, oldGeometry);
- updatePaintedGeometry();
+ if (newGeometry.size() != oldGeometry.size())
+ updatePaintedGeometry();
}
QRectF QQuickImage::boundingRect() const
diff --git a/src/quick/items/qquickimage_p_p.h b/src/quick/items/qquickimage_p_p.h
index 522dbca803..afc33def0f 100644
--- a/src/quick/items/qquickimage_p_p.h
+++ b/src/quick/items/qquickimage_p_p.h
@@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE
class QQuickImageTextureProvider;
-class QQuickImagePrivate : public QQuickImageBasePrivate
+class Q_QUICK_PRIVATE_EXPORT QQuickImagePrivate : public QQuickImageBasePrivate
{
Q_DECLARE_PUBLIC(QQuickImage)
diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp
index e8200bb97f..74ee859f77 100644
--- a/src/quick/items/qquickimagebase.cpp
+++ b/src/quick/items/qquickimagebase.cpp
@@ -49,6 +49,30 @@
QT_BEGIN_NAMESPACE
+// This function gives derived classes the chance set the devicePixelRatio
+// if they're not happy with our implementation of it.
+bool QQuickImageBasePrivate::updateDevicePixelRatio(qreal targetDevicePixelRatio)
+{
+ // QQuickImageProvider and SVG can generate a high resolution image when
+ // sourceSize is set (this function is only called if it's set).
+ // If sourceSize is not set then the provider default size will be used, as usual.
+ bool setDevicePixelRatio = false;
+ if (url.scheme() == QLatin1String("image")) {
+ setDevicePixelRatio = true;
+ } else {
+ QString stringUrl = url.path(QUrl::PrettyDecoded);
+ if (stringUrl.endsWith(QLatin1String("svg")) ||
+ stringUrl.endsWith(QLatin1String("svgz"))) {
+ setDevicePixelRatio = true;
+ }
+ }
+
+ if (setDevicePixelRatio)
+ devicePixelRatio = targetDevicePixelRatio;
+
+ return setDevicePixelRatio;
+}
+
QQuickImageBase::QQuickImageBase(QQuickItem *parent)
: QQuickImplicitSizeItem(*(new QQuickImageBasePrivate), parent)
{
@@ -221,26 +245,11 @@ void QQuickImageBase::load()
QUrl loadUrl = d->url;
- // QQuickImageProvider and SVG can generate a high resolution image when
- // sourceSize is set. If sourceSize is not set then the provider default size
- // will be used, as usual.
- bool setDevicePixelRatio = false;
- if (d->sourcesize.isValid()) {
- if (loadUrl.scheme() == QLatin1String("image")) {
- setDevicePixelRatio = true;
- } else {
- QString stringUrl = loadUrl.path(QUrl::PrettyDecoded);
- if (stringUrl.endsWith(QLatin1String("svg")) ||
- stringUrl.endsWith(QLatin1String("svgz"))) {
- setDevicePixelRatio = true;
- }
- }
-
- if (setDevicePixelRatio)
- d->devicePixelRatio = targetDevicePixelRatio;
- }
+ bool updatedDevicePixelRatio = false;
+ if (d->sourcesize.isValid())
+ updatedDevicePixelRatio = d->updateDevicePixelRatio(targetDevicePixelRatio);
- if (!setDevicePixelRatio) {
+ if (!updatedDevicePixelRatio) {
// (possible) local file: loadUrl and d->devicePixelRatio will be modified if
// an "@2x" file is found.
resolve2xLocalFile(d->url, targetDevicePixelRatio, &loadUrl, &d->devicePixelRatio);
@@ -319,18 +328,18 @@ void QQuickImageBase::requestProgress(qint64 received, qint64 total)
void QQuickImageBase::itemChange(ItemChange change, const ItemChangeData &value)
{
- if (change == ItemSceneChange && value.window)
- connect(value.window, &QQuickWindow::screenChanged, this, &QQuickImageBase::handleScreenChanged);
+ Q_D(QQuickImageBase);
+ // If the screen DPI changed, reload image.
+ if (change == ItemDevicePixelRatioHasChanged && value.realValue != d->devicePixelRatio) {
+ // ### how can we get here with !qmlEngine(this)? that implies
+ // itemChange() on an item pending deletion, which seems strange.
+ if (qmlEngine(this) && isComponentComplete() && d->url.isValid()) {
+ load();
+ }
+ }
QQuickItem::itemChange(change, value);
}
-void QQuickImageBase::handleScreenChanged(QScreen* screen)
-{
- // Screen DPI might have changed, reload images on screen change.
- if (qmlEngine(this) && screen && isComponentComplete())
- load();
-}
-
void QQuickImageBase::componentComplete()
{
Q_D(QQuickImageBase);
diff --git a/src/quick/items/qquickimagebase_p.h b/src/quick/items/qquickimagebase_p.h
index 532f6ce683..54b1f789c9 100644
--- a/src/quick/items/qquickimagebase_p.h
+++ b/src/quick/items/qquickimagebase_p.h
@@ -123,7 +123,6 @@ protected:
private Q_SLOTS:
virtual void requestFinished();
void requestProgress(qint64,qint64);
- void handleScreenChanged(QScreen *screen);
private:
Q_DISABLE_COPY(QQuickImageBase)
diff --git a/src/quick/items/qquickimagebase_p_p.h b/src/quick/items/qquickimagebase_p_p.h
index d9b609c7fe..1b771166a2 100644
--- a/src/quick/items/qquickimagebase_p_p.h
+++ b/src/quick/items/qquickimagebase_p_p.h
@@ -59,7 +59,7 @@
QT_BEGIN_NAMESPACE
class QNetworkReply;
-class QQuickImageBasePrivate : public QQuickImplicitSizeItemPrivate
+class Q_QUICK_PRIVATE_EXPORT QQuickImageBasePrivate : public QQuickImplicitSizeItemPrivate
{
Q_DECLARE_PUBLIC(QQuickImageBase)
@@ -75,6 +75,8 @@ public:
{
}
+ virtual bool updateDevicePixelRatio(qreal targetDevicePixelRatio);
+
QQuickPixmap pix;
QQuickImageBase::Status status;
QUrl url;
diff --git a/src/quick/items/qquickimplicitsizeitem.cpp b/src/quick/items/qquickimplicitsizeitem.cpp
index 1996fb9489..2569b2a224 100644
--- a/src/quick/items/qquickimplicitsizeitem.cpp
+++ b/src/quick/items/qquickimplicitsizeitem.cpp
@@ -45,29 +45,11 @@ QT_BEGIN_NAMESPACE
/*!
\internal
- The purpose of QQuickImplicitSizeItem is not immediately clear, as both
- the implicit size properties and signals exist on QQuickItem. However,
- for some items - where the implicit size has an underlying meaning (such as
- Image, where the implicit size represents the real size of the image)
- having implicit size writable is an undesirable thing.
-
- QQuickImplicitSizeItem redefines the properties as being readonly.
- Unfortunately, this also means they need to redefine the change signals.
- See QTBUG-30258 for more information.
+ QQuickImplicitSizeItem redefines the implicitWidth and implicitHeight
+ properties as readonly, as some items (e.g. Image, where the implicit size
+ represents the real size of the image) should not be able to have their
+ implicit size modified.
*/
-void QQuickImplicitSizeItemPrivate::implicitWidthChanged()
-{
- Q_Q(QQuickImplicitSizeItem);
- QQuickItemPrivate::implicitWidthChanged();
- emit q->implicitWidthChanged2();
-}
-
-void QQuickImplicitSizeItemPrivate::implicitHeightChanged()
-{
- Q_Q(QQuickImplicitSizeItem);
- QQuickItemPrivate::implicitHeightChanged();
- emit q->implicitHeightChanged2();
-}
QQuickImplicitSizeItem::QQuickImplicitSizeItem(QQuickImplicitSizeItemPrivate &dd, QQuickItem *parent)
: QQuickItem(dd, parent)
diff --git a/src/quick/items/qquickimplicitsizeitem_p.h b/src/quick/items/qquickimplicitsizeitem_p.h
index 75b04449f8..8ae8f9f447 100644
--- a/src/quick/items/qquickimplicitsizeitem_p.h
+++ b/src/quick/items/qquickimplicitsizeitem_p.h
@@ -60,16 +60,12 @@ class QQuickImplicitSizeItemPrivate;
class Q_QUICK_PRIVATE_EXPORT QQuickImplicitSizeItem : public QQuickItem
{
Q_OBJECT
- Q_PROPERTY(qreal implicitWidth READ implicitWidth NOTIFY implicitWidthChanged2)
- Q_PROPERTY(qreal implicitHeight READ implicitHeight NOTIFY implicitHeightChanged2)
+ Q_PROPERTY(qreal implicitWidth READ implicitWidth NOTIFY implicitWidthChanged)
+ Q_PROPERTY(qreal implicitHeight READ implicitHeight NOTIFY implicitHeightChanged)
protected:
QQuickImplicitSizeItem(QQuickImplicitSizeItemPrivate &dd, QQuickItem *parent);
-Q_SIGNALS:
- Q_REVISION(1) void implicitWidthChanged2();
- Q_REVISION(1) void implicitHeightChanged2();
-
private:
Q_DISABLE_COPY(QQuickImplicitSizeItem)
Q_DECLARE_PRIVATE(QQuickImplicitSizeItem)
diff --git a/src/quick/items/qquickimplicitsizeitem_p_p.h b/src/quick/items/qquickimplicitsizeitem_p_p.h
index 2c42fa62f2..0495cf87e1 100644
--- a/src/quick/items/qquickimplicitsizeitem_p_p.h
+++ b/src/quick/items/qquickimplicitsizeitem_p_p.h
@@ -65,9 +65,6 @@ public:
QQuickImplicitSizeItemPrivate()
{
}
-
- void implicitWidthChanged() Q_DECL_OVERRIDE;
- void implicitHeightChanged() Q_DECL_OVERRIDE;
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 549575a97f..1e71c20ff3 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -163,7 +163,7 @@ void QQuickTransform::update()
}
QQuickContents::QQuickContents(QQuickItem *item)
-: m_item(item), m_x(0), m_y(0), m_width(0), m_height(0)
+: m_item(item)
{
}
@@ -178,8 +178,8 @@ QQuickContents::~QQuickContents()
bool QQuickContents::calcHeight(QQuickItem *changed)
{
- qreal oldy = m_y;
- qreal oldheight = m_height;
+ qreal oldy = m_contents.y();
+ qreal oldheight = m_contents.height();
if (changed) {
qreal top = oldy;
@@ -189,8 +189,8 @@ bool QQuickContents::calcHeight(QQuickItem *changed)
bottom = y + changed->height();
if (y < top)
top = y;
- m_y = top;
- m_height = bottom - top;
+ m_contents.setY(top);
+ m_contents.setHeight(bottom - top);
} else {
qreal top = std::numeric_limits<qreal>::max();
qreal bottom = -std::numeric_limits<qreal>::max();
@@ -204,17 +204,17 @@ bool QQuickContents::calcHeight(QQuickItem *changed)
top = y;
}
if (!children.isEmpty())
- m_y = top;
- m_height = qMax(bottom - top, qreal(0.0));
+ m_contents.setY(top);
+ m_contents.setHeight(qMax(bottom - top, qreal(0.0)));
}
- return (m_height != oldheight || m_y != oldy);
+ return (m_contents.height() != oldheight || m_contents.y() != oldy);
}
bool QQuickContents::calcWidth(QQuickItem *changed)
{
- qreal oldx = m_x;
- qreal oldwidth = m_width;
+ qreal oldx = m_contents.x();
+ qreal oldwidth = m_contents.width();
if (changed) {
qreal left = oldx;
@@ -224,8 +224,8 @@ bool QQuickContents::calcWidth(QQuickItem *changed)
right = x + changed->width();
if (x < left)
left = x;
- m_x = left;
- m_width = right - left;
+ m_contents.setX(left);
+ m_contents.setWidth(right - left);
} else {
qreal left = std::numeric_limits<qreal>::max();
qreal right = -std::numeric_limits<qreal>::max();
@@ -239,11 +239,11 @@ bool QQuickContents::calcWidth(QQuickItem *changed)
left = x;
}
if (!children.isEmpty())
- m_x = left;
- m_width = qMax(right - left, qreal(0.0));
+ m_contents.setX(left);
+ m_contents.setWidth(qMax(right - left, qreal(0.0)));
}
- return (m_width != oldwidth || m_x != oldx);
+ return (m_contents.width() != oldwidth || m_contents.x() != oldx);
}
void QQuickContents::complete()
@@ -2138,6 +2138,9 @@ void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus)
\value ItemAntialiasingHasChanged The antialiasing has changed. The current
(boolean) value can be found in QQuickItem::antialiasing.
+
+ \value ItemEnabledHasChanged The item's enabled state has changed.
+ ItemChangeData::boolValue contains the new enabled state. (since Qt 5.10)
*/
/*!
@@ -5927,6 +5930,7 @@ void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffec
scope, q, Qt::OtherFocusReason, QQuickWindowPrivate::DontChangeFocusProperty | QQuickWindowPrivate::DontChangeSubFocusItem);
}
+ itemChange(QQuickItem::ItemEnabledHasChanged, effectiveEnable);
emit q->enabledChanged();
}
@@ -6099,6 +6103,18 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt
}
break;
}
+ case QQuickItem::ItemEnabledHasChanged: {
+ q->itemChange(change, data);
+ if (!changeListeners.isEmpty()) {
+ const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732)
+ for (const QQuickItemPrivate::ChangeListener &change : listeners) {
+ if (change.types & QQuickItemPrivate::Enabled) {
+ change.listener->itemEnabledChanged(q);
+ }
+ }
+ }
+ break;
+ }
case QQuickItem::ItemParentHasChanged: {
q->itemChange(change, data);
if (!changeListeners.isEmpty()) {
@@ -6763,8 +6779,27 @@ bool QQuickItem::heightValid() const
}
/*!
- \internal
- */
+ \since 5.10
+
+ Returns the size of the item.
+
+ \sa setSize, width, height
+ */
+
+QSizeF QQuickItem::size() const
+{
+ Q_D(const QQuickItem);
+ return QSizeF(d->width, d->height);
+}
+
+
+/*!
+ \since 5.10
+
+ Sets the size of the item to \a size.
+
+ \sa size, setWidth, setHeight
+ */
void QQuickItem::setSize(const QSizeF &size)
{
Q_D(QQuickItem);
@@ -7886,6 +7921,7 @@ QQuickItemLayer::QQuickItemLayer(QQuickItem *item)
, m_effect(0)
, m_effectSource(0)
, m_textureMirroring(QQuickShaderEffectSource::MirrorVertically)
+ , m_samples(0)
{
}
@@ -7960,6 +7996,7 @@ void QQuickItemLayer::activate()
m_effectSource->setWrapMode(m_wrapMode);
m_effectSource->setFormat(m_format);
m_effectSource->setTextureMirroring(m_textureMirroring);
+ m_effectSource->setSamples(m_samples);
if (m_effectComponent)
activateEffect();
@@ -8253,6 +8290,44 @@ void QQuickItemLayer::setTextureMirroring(QQuickShaderEffectSource::TextureMirro
}
/*!
+ \qmlproperty enumeration QtQuick::Item::layer.samples
+ \since 5.10
+
+ This property allows requesting multisampled rendering in the layer.
+
+ By default multisampling is enabled whenever multisampling is
+ enabled for the entire window, assuming the scenegraph renderer in
+ use and the underlying graphics API supports this.
+
+ By setting the value to 2, 4, etc. multisampled rendering can be requested
+ for a part of the scene without enabling multisampling for the entire
+ scene. This way multisampling is applied only to a given subtree, which can
+ lead to significant performance gains since multisampling is not applied to
+ other parts of the scene.
+
+ \note Enabling multisampling can be potentially expensive regardless of the
+ layer's size, as it incurs a hardware and driver dependent performance and
+ memory cost.
+
+ \note This property is only functional when support for multisample
+ renderbuffers and framebuffer blits is available. Otherwise the value is
+ silently ignored.
+ */
+
+void QQuickItemLayer::setSamples(int count)
+{
+ if (m_samples == count)
+ return;
+
+ m_samples = count;
+
+ if (m_effectSource)
+ m_effectSource->setSamples(m_samples);
+
+ emit samplesChanged(count);
+}
+
+/*!
\qmlproperty string QtQuick::Item::layer.samplerName
Holds the name of the effect's source texture property.
@@ -8401,19 +8476,19 @@ struct QQuickItemWrapper : public QObjectWrapper {
struct QQuickItemWrapper : public QV4::QObjectWrapper {
V4_OBJECT2(QQuickItemWrapper, QV4::QObjectWrapper)
- static void markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e);
+ static void markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack);
};
DEFINE_OBJECT_VTABLE(QQuickItemWrapper);
-void QQuickItemWrapper::markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e)
+void QQuickItemWrapper::markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack)
{
QObjectWrapper::Data *This = static_cast<QObjectWrapper::Data *>(that);
if (QQuickItem *item = static_cast<QQuickItem*>(This->object())) {
for (QQuickItem *child : qAsConst(QQuickItemPrivate::get(item)->childItems))
- QV4::QObjectWrapper::markWrapper(child, e);
+ QV4::QObjectWrapper::markWrapper(child, markStack);
}
- QV4::QObjectWrapper::markObjects(that, e);
+ QV4::QObjectWrapper::markObjects(that, markStack);
}
quint64 QQuickItemPrivate::_q_createJSWrapper(QV4::ExecutionEngine *engine)
diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h
index c9494d91bd..4a832bbf6f 100644
--- a/src/quick/items/qquickitem.h
+++ b/src/quick/items/qquickitem.h
@@ -173,7 +173,8 @@ public:
ItemActiveFocusHasChanged, // value.boolValue
ItemRotationHasChanged, // value.realValue
ItemAntialiasingHasChanged, // value.boolValue
- ItemDevicePixelRatioHasChanged // value.realValue
+ ItemDevicePixelRatioHasChanged, // value.realValue
+ ItemEnabledHasChanged // value.boolValue
};
union ItemChangeData {
@@ -237,6 +238,7 @@ public:
void setImplicitHeight(qreal);
qreal implicitHeight() const;
+ QSizeF size() const;
void setSize(const QSizeF &size);
TransformOrigin transformOrigin() const;
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index c0c9bd46bd..74d70da2bc 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -94,7 +94,7 @@ public:
QQuickContents(QQuickItem *item);
~QQuickContents();
- QRectF rectF() const { return QRectF(m_x, m_y, m_width, m_height); }
+ QRectF rectF() const { return m_contents; }
inline void calcGeometry(QQuickItem *changed = 0);
void complete();
@@ -112,10 +112,7 @@ private:
void updateRect();
QQuickItem *m_item;
- qreal m_x;
- qreal m_y;
- qreal m_width;
- qreal m_height;
+ QRectF m_contents;
};
void QQuickContents::calcGeometry(QQuickItem *changed)
@@ -152,6 +149,8 @@ class QQuickItemLayer : public QObject, public QQuickItemChangeListener
Q_PROPERTY(QByteArray samplerName READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(QQmlComponent *effect READ effect WRITE setEffect NOTIFY effectChanged)
Q_PROPERTY(QQuickShaderEffectSource::TextureMirroring textureMirroring READ textureMirroring WRITE setTextureMirroring NOTIFY textureMirroringChanged)
+ Q_PROPERTY(int samples READ samples WRITE setSamples NOTIFY samplesChanged)
+
public:
QQuickItemLayer(QQuickItem *item);
~QQuickItemLayer();
@@ -189,6 +188,9 @@ public:
QQuickShaderEffectSource::TextureMirroring textureMirroring() const { return m_textureMirroring; }
void setTextureMirroring(QQuickShaderEffectSource::TextureMirroring mirroring);
+ int samples() const { return m_samples; }
+ void setSamples(int count);
+
QQuickShaderEffectSource *effectSource() const { return m_effectSource; }
void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &) Q_DECL_OVERRIDE;
@@ -213,6 +215,7 @@ Q_SIGNALS:
void formatChanged(QQuickShaderEffectSource::Format format);
void sourceRectChanged(const QRectF &sourceRect);
void textureMirroringChanged(QQuickShaderEffectSource::TextureMirroring mirroring);
+ void samplesChanged(int count);
private:
friend class QQuickTransformAnimatorJob;
@@ -237,6 +240,7 @@ private:
QQuickItem *m_effect;
QQuickShaderEffectSource *m_effectSource;
QQuickShaderEffectSource::TextureMirroring m_textureMirroring;
+ int m_samples;
};
#endif
@@ -317,7 +321,8 @@ public:
Children = 0x40,
Rotation = 0x80,
ImplicitWidth = 0x100,
- ImplicitHeight = 0x200
+ ImplicitHeight = 0x200,
+ Enabled = 0x400,
};
Q_DECLARE_FLAGS(ChangeTypes, ChangeType)
diff --git a/src/quick/items/qquickitemanimation.cpp b/src/quick/items/qquickitemanimation.cpp
index 714a1a9012..d4d346def9 100644
--- a/src/quick/items/qquickitemanimation.cpp
+++ b/src/quick/items/qquickitemanimation.cpp
@@ -327,7 +327,7 @@ QAbstractAnimationJob* QQuickParentAnimation::transition(QQuickStateActions &act
}
if (scale != 0)
- rotation = qAtan2(transform.m12()/scale, transform.m11()/scale) * 180/M_PI;
+ rotation = qRadiansToDegrees(qAtan2(transform.m12() / scale, transform.m11() / scale));
else {
qmlWarning(this) << QQuickParentAnimation::tr("Unable to preserve appearance under scale of 0");
ok = false;
diff --git a/src/quick/items/qquickitemchangelistener_p.h b/src/quick/items/qquickitemchangelistener_p.h
index 83c69a9330..cb0af75c4c 100644
--- a/src/quick/items/qquickitemchangelistener_p.h
+++ b/src/quick/items/qquickitemchangelistener_p.h
@@ -125,6 +125,7 @@ public:
virtual void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF & /* oldGeometry */) {}
virtual void itemSiblingOrderChanged(QQuickItem *) {}
virtual void itemVisibilityChanged(QQuickItem *) {}
+ virtual void itemEnabledChanged(QQuickItem *) {}
virtual void itemOpacityChanged(QQuickItem *) {}
virtual void itemDestroyed(QQuickItem *) {}
virtual void itemChildAdded(QQuickItem *, QQuickItem * /* child */ ) {}
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index 5f6d44b54d..e6321e9365 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -376,6 +376,12 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickFlickable, 9>(uri, 2, 9, "Flickable");
qmlRegisterType<QQuickMouseArea, 9>(uri, 2, 9, "MouseArea");
+
+#if QT_CONFIG(quick_path)
+ qmlRegisterType<QQuickPathArc, 2>(uri, 2, 9, "PathArc");
+ qmlRegisterType<QQuickPathMove>(uri, 2, 9, "PathMove");
+#endif
+
qmlRegisterType<QQuickText, 9>(uri, 2, 9, "Text");
qmlRegisterType<QQuickTextInput, 9>(uri, 2, 9, "TextInput");
qmlRegisterType<QQuickTouchPoint>(uri, 2, 9, "TouchPoint");
@@ -385,6 +391,12 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterUncreatableType<QQuickBasePositioner, 9>(uri, 2, 9, "Positioner",
QStringLiteral("Positioner is an abstract type that is only available as an attached property."));
#endif
+
+#if QT_CONFIG(quick_shadereffect)
+ qmlRegisterType<QQuickShaderEffectSource, 2>(uri, 2, 9, "ShaderEffectSource");
+#endif
+
+ qmlRegisterType<QQuickFlickable, 10>(uri, 2, 10, "Flickable");
}
static void initResources()
diff --git a/src/quick/items/qquickopenglshadereffect.cpp b/src/quick/items/qquickopenglshadereffect.cpp
index 4fcfe04b55..c3e0ba05bd 100644
--- a/src/quick/items/qquickopenglshadereffect.cpp
+++ b/src/quick/items/qquickopenglshadereffect.cpp
@@ -230,7 +230,7 @@ void QQuickOpenGLShaderEffectCommon::disconnectPropertySignals(QQuickItem *item,
auto mapper = signalMappers[shaderType].at(i);
void *a = mapper;
QObjectPrivate::disconnect(item, mapper->signalIndex(), &a);
- if (d.specialType == UniformData::Sampler) {
+ if (d.specialType == UniformData::Sampler || d.specialType == UniformData::SamplerExternal) {
QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(d.value));
if (source) {
if (item->window())
@@ -272,7 +272,7 @@ void QQuickOpenGLShaderEffectCommon::connectPropertySignals(QQuickItem *item,
qWarning("QQuickOpenGLShaderEffect: '%s' does not have a matching property!", d.name.constData());
}
- if (d.specialType == UniformData::Sampler) {
+ if (d.specialType == UniformData::Sampler || d.specialType == UniformData::SamplerExternal) {
QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(d.value));
if (source) {
if (item->window())
@@ -335,6 +335,7 @@ void QQuickOpenGLShaderEffectCommon::lookThroughShaderCode(QQuickItem *item,
Q_ASSERT(decl == UniformQualifier);
const int sampLen = sizeof("sampler2D") - 1;
+ const int sampExtLen = sizeof("samplerExternalOES") - 1;
const int opLen = sizeof("qt_Opacity") - 1;
const int matLen = sizeof("qt_Matrix") - 1;
const int srLen = sizeof("qt_SubRect_") - 1;
@@ -357,8 +358,12 @@ void QQuickOpenGLShaderEffectCommon::lookThroughShaderCode(QQuickItem *item,
mapper = new QtPrivate::MappedSlotObject([this, mappedId](){
this->mappedPropertyChanged(mappedId);
});
- bool sampler = typeLength == sampLen && qstrncmp("sampler2D", s + typeIndex, sampLen) == 0;
- d.specialType = sampler ? UniformData::Sampler : UniformData::None;
+ if (typeLength == sampLen && qstrncmp("sampler2D", s + typeIndex, sampLen) == 0)
+ d.specialType = UniformData::Sampler;
+ else if (typeLength == sampExtLen && qstrncmp("samplerExternalOES", s + typeIndex, sampExtLen) == 0)
+ d.specialType = UniformData::SamplerExternal;
+ else
+ d.specialType = UniformData::None;
d.setValueFromProperty(item, itemMetaObject);
}
uniformData[shaderType].append(d);
@@ -451,7 +456,8 @@ void QQuickOpenGLShaderEffectCommon::updateMaterial(QQuickOpenGLShaderEffectNode
int textureProviderCount = 0;
for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) {
for (int i = 0; i < uniformData[shaderType].size(); ++i) {
- if (uniformData[shaderType].at(i).specialType == UniformData::Sampler)
+ if (uniformData[shaderType].at(i).specialType == UniformData::Sampler ||
+ uniformData[shaderType].at(i).specialType == UniformData::SamplerExternal)
++textureProviderCount;
}
material->uniforms[shaderType] = uniformData[shaderType];
@@ -474,7 +480,7 @@ void QQuickOpenGLShaderEffectCommon::updateMaterial(QQuickOpenGLShaderEffectNode
for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) {
for (int i = 0; i < uniformData[shaderType].size(); ++i) {
const UniformData &d = uniformData[shaderType].at(i);
- if (d.specialType != UniformData::Sampler)
+ if (d.specialType != UniformData::Sampler && d.specialType != UniformData::SamplerExternal)
continue;
QSGTextureProvider *oldProvider = material->textureProviders.at(index);
QSGTextureProvider *newProvider = 0;
@@ -513,7 +519,7 @@ void QQuickOpenGLShaderEffectCommon::updateWindow(QQuickWindow *window)
for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) {
for (int i = 0; i < uniformData[shaderType].size(); ++i) {
const UniformData &d = uniformData[shaderType].at(i);
- if (d.specialType == UniformData::Sampler) {
+ if (d.specialType == UniformData::Sampler || d.specialType == UniformData::SamplerExternal) {
QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(d.value));
if (source)
QQuickItemPrivate::get(source)->refWindow(window);
@@ -524,7 +530,7 @@ void QQuickOpenGLShaderEffectCommon::updateWindow(QQuickWindow *window)
for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) {
for (int i = 0; i < uniformData[shaderType].size(); ++i) {
const UniformData &d = uniformData[shaderType].at(i);
- if (d.specialType == UniformData::Sampler) {
+ if (d.specialType == UniformData::Sampler || d.specialType == UniformData::SamplerExternal) {
QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(d.value));
if (source)
QQuickItemPrivate::get(source)->derefWindow();
@@ -539,7 +545,7 @@ void QQuickOpenGLShaderEffectCommon::sourceDestroyed(QObject *object)
for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) {
for (int i = 0; i < uniformData[shaderType].size(); ++i) {
UniformData &d = uniformData[shaderType][i];
- if (d.specialType == UniformData::Sampler && d.value.canConvert<QObject *>()) {
+ if ((d.specialType == UniformData::Sampler || d.specialType == UniformData::SamplerExternal) && d.value.canConvert<QObject *>()) {
if (qvariant_cast<QObject *>(d.value) == object)
d.value = QVariant();
}
@@ -554,7 +560,7 @@ static bool qquick_uniqueInUniformData(QQuickItem *source, const QVector<QQuickO
if (s == typeToSkip && i == indexToSkip)
continue;
const QQuickOpenGLShaderEffectMaterial::UniformData &d = uniformData[s][i];
- if (d.specialType == QQuickOpenGLShaderEffectMaterial::UniformData::Sampler && qvariant_cast<QObject *>(d.value) == source)
+ if ((d.specialType == QQuickOpenGLShaderEffectMaterial::UniformData::Sampler || d.specialType == QQuickOpenGLShaderEffectMaterial::UniformData::SamplerExternal) && qvariant_cast<QObject *>(d.value) == source)
return false;
}
}
@@ -568,7 +574,7 @@ void QQuickOpenGLShaderEffectCommon::propertyChanged(QQuickItem *item,
Key::ShaderType shaderType = Key::ShaderType(mappedId >> 16);
int index = mappedId & 0xffff;
UniformData &d = uniformData[shaderType][index];
- if (d.specialType == UniformData::Sampler) {
+ if (d.specialType == UniformData::Sampler || d.specialType == UniformData::SamplerExternal) {
QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(d.value));
if (source) {
if (item->window())
diff --git a/src/quick/items/qquickopenglshadereffectnode.cpp b/src/quick/items/qquickopenglshadereffectnode.cpp
index e1ea98641d..5dbfee73cb 100644
--- a/src/quick/items/qquickopenglshadereffectnode.cpp
+++ b/src/quick/items/qquickopenglshadereffectnode.cpp
@@ -47,6 +47,10 @@
#include <QtCore/qmutex.h>
#include <QtGui/qopenglfunctions.h>
+#ifndef GL_TEXTURE_EXTERNAL_OES
+#define GL_TEXTURE_EXTERNAL_OES 0x8D65
+#endif
+
QT_BEGIN_NAMESPACE
static bool hasAtlasTexture(const QVector<QSGTextureProvider *> &textureProviders)
@@ -124,7 +128,7 @@ void QQuickCustomMaterialShader::updateState(const RenderState &state, QSGMateri
for (int i = 0; i < material->uniforms[shaderType].size(); ++i) {
const UniformData &d = material->uniforms[shaderType].at(i);
QByteArray name = d.name;
- if (d.specialType == UniformData::Sampler) {
+ if (d.specialType == UniformData::Sampler || d.specialType == UniformData::SamplerExternal) {
program()->setUniformValue(d.name.constData(), textureProviderIndex++);
// We don't need to store the sampler uniform locations, since their values
// only need to be set once. Look for the "qt_SubRect_" uniforms instead.
@@ -143,7 +147,7 @@ void QQuickCustomMaterialShader::updateState(const RenderState &state, QSGMateri
for (int i = 0; i < material->uniforms[shaderType].size(); ++i) {
const UniformData &d = material->uniforms[shaderType].at(i);
int loc = m_uniformLocs[shaderType].at(i);
- if (d.specialType == UniformData::Sampler) {
+ if (d.specialType == UniformData::Sampler || d.specialType == UniformData::SamplerExternal) {
int idx = textureProviderIndex++;
functions->glActiveTexture(GL_TEXTURE0 + idx);
if (QSGTextureProvider *provider = material->textureProviders.at(idx)) {
@@ -164,7 +168,10 @@ void QQuickCustomMaterialShader::updateState(const RenderState &state, QSGMateri
continue;
}
}
- functions->glBindTexture(GL_TEXTURE_2D, 0);
+ if (d.specialType == UniformData::Sampler)
+ functions->glBindTexture(GL_TEXTURE_2D, 0);
+ else if (d.specialType == UniformData::SamplerExternal)
+ functions->glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
} else if (d.specialType == UniformData::Opacity) {
program()->setUniformValue(loc, state.opacity());
} else if (d.specialType == UniformData::Matrix) {
@@ -396,7 +403,7 @@ bool QQuickOpenGLShaderEffectMaterial::UniformData::operator == (const UniformDa
if (name != other.name)
return false;
- if (specialType == UniformData::Sampler) {
+ if (specialType == UniformData::Sampler || specialType == UniformData::SamplerExternal) {
// We can't check the source objects as these live in the GUI thread,
// so return true here and rely on the textureProvider check for
// equality of these..
diff --git a/src/quick/items/qquickopenglshadereffectnode_p.h b/src/quick/items/qquickopenglshadereffectnode_p.h
index aea28e6612..784294d9eb 100644
--- a/src/quick/items/qquickopenglshadereffectnode_p.h
+++ b/src/quick/items/qquickopenglshadereffectnode_p.h
@@ -90,7 +90,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickOpenGLShaderEffectMaterial : public QSGMateri
public:
struct UniformData
{
- enum SpecialType { None, Sampler, SubRect, Opacity, Matrix };
+ enum SpecialType { None, Sampler, SamplerExternal, SubRect, Opacity, Matrix };
QByteArray name;
QVariant value;
diff --git a/src/quick/items/qquickpositioners.cpp b/src/quick/items/qquickpositioners.cpp
index 06b18d714b..e752e2538f 100644
--- a/src/quick/items/qquickpositioners.cpp
+++ b/src/quick/items/qquickpositioners.cpp
@@ -44,9 +44,6 @@
#include <QtQml/qqmlinfo.h>
#include <QtCore/qcoreapplication.h>
-#include <QtQuick/private/qquickstate_p.h>
-#include <QtQuick/private/qquickstategroup_p.h>
-#include <private/qquickstatechangescript_p.h>
#include <QtQuick/private/qquicktransition_p.h>
QT_BEGIN_NAMESPACE
@@ -1137,7 +1134,7 @@ public:
: QQuickBasePositionerPrivate()
{}
- void effectiveLayoutDirectionChange()
+ void effectiveLayoutDirectionChange() override
{
Q_Q(QQuickRow);
// For RTL layout the positioning changes when the width changes.
@@ -1436,7 +1433,7 @@ public:
: QQuickBasePositionerPrivate()
{}
- void effectiveLayoutDirectionChange()
+ void effectiveLayoutDirectionChange() override
{
Q_Q(QQuickGrid);
// For RTL layout the positioning changes when the width changes.
@@ -2023,7 +2020,7 @@ public:
: QQuickBasePositionerPrivate(), flow(QQuickFlow::LeftToRight)
{}
- void effectiveLayoutDirectionChange()
+ void effectiveLayoutDirectionChange() override
{
Q_Q(QQuickFlow);
// Don't postpone, as it might be the only trigger for visible changes.
diff --git a/src/quick/items/qquickpositioners_p.h b/src/quick/items/qquickpositioners_p.h
index ae6e795794..9ae7029d69 100644
--- a/src/quick/items/qquickpositioners_p.h
+++ b/src/quick/items/qquickpositioners_p.h
@@ -58,7 +58,6 @@ QT_REQUIRE_CONFIG(quick_positioners);
#include "qquickimplicitsizeitem_p.h"
#include "qquickitemviewtransition_p.h"
-#include <QtQuick/private/qquickstate_p.h>
#include <private/qpodvector_p.h>
#include <QtCore/qobject.h>
diff --git a/src/quick/items/qquickpositioners_p_p.h b/src/quick/items/qquickpositioners_p_p.h
index 6dd84e6098..0be4c56df6 100644
--- a/src/quick/items/qquickpositioners_p_p.h
+++ b/src/quick/items/qquickpositioners_p_p.h
@@ -58,9 +58,6 @@ QT_REQUIRE_CONFIG(quick_positioners);
#include "qquickpositioners_p.h"
#include "qquickimplicitsizeitem_p_p.h"
-#include <QtQuick/private/qquickstate_p.h>
-#include <private/qquicktransitionmanager_p_p.h>
-#include <private/qquickstatechangescript_p.h>
#include <private/qlazilyallocated_p.h>
#include <QtCore/qobject.h>
diff --git a/src/quick/items/qquickrectangle.cpp b/src/quick/items/qquickrectangle.cpp
index 8ac982f74c..65284eb532 100644
--- a/src/quick/items/qquickrectangle.cpp
+++ b/src/quick/items/qquickrectangle.cpp
@@ -90,6 +90,7 @@ void QQuickPen::setWidth(qreal w)
m_width = w;
m_valid = m_color.alpha() && (qRound(m_width) >= 1 || (!m_aligned && m_width > 0));
+ static_cast<QQuickItem*>(parent())->update();
emit penChanged();
}
@@ -102,6 +103,7 @@ void QQuickPen::setColor(const QColor &c)
{
m_color = c;
m_valid = m_color.alpha() && (qRound(m_width) >= 1 || (!m_aligned && m_width > 0));
+ static_cast<QQuickItem*>(parent())->update();
emit penChanged();
}
@@ -116,6 +118,7 @@ void QQuickPen::setPixelAligned(bool aligned)
return;
m_aligned = aligned;
m_valid = m_color.alpha() && (qRound(m_width) >= 1 || (!m_aligned && m_width > 0));
+ static_cast<QQuickItem*>(parent())->update();
emit penChanged();
}
@@ -356,7 +359,11 @@ void QQuickRectangle::doUpdate()
QQuickPen *QQuickRectangle::border()
{
Q_D(QQuickRectangle);
- return d->getPen();
+ if (!d->pen) {
+ d->pen = new QQuickPen;
+ QQml_setParent_noEvent(d->pen, this);
+ }
+ return d->pen;
}
/*!
diff --git a/src/quick/items/qquickrectangle_p_p.h b/src/quick/items/qquickrectangle_p_p.h
index 50d5817951..3c1aaf7661 100644
--- a/src/quick/items/qquickrectangle_p_p.h
+++ b/src/quick/items/qquickrectangle_p_p.h
@@ -70,7 +70,6 @@ public:
~QQuickRectanglePrivate()
{
- delete pen;
}
QColor color;
@@ -78,20 +77,6 @@ public:
QQuickPen *pen;
qreal radius;
static int doUpdateSlotIdx;
-
- QQuickPen *getPen() {
- if (!pen) {
- Q_Q(QQuickRectangle);
- pen = new QQuickPen;
- static int penChangedSignalIdx = -1;
- if (penChangedSignalIdx < 0)
- penChangedSignalIdx = QMetaMethod::fromSignal(&QQuickPen::penChanged).methodIndex();
- if (doUpdateSlotIdx < 0)
- doUpdateSlotIdx = QQuickRectangle::staticMetaObject.indexOfSlot("doUpdate()");
- QMetaObject::connect(pen, penChangedSignalIdx, q, doUpdateSlotIdx);
- }
- return pen;
- }
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickscreen.cpp b/src/quick/items/qquickscreen.cpp
index 9b54b7fba9..6a3eab957e 100644
--- a/src/quick/items/qquickscreen.cpp
+++ b/src/quick/items/qquickscreen.cpp
@@ -100,6 +100,27 @@ QT_BEGIN_NAMESPACE
The y coordinate of the screen within the virtual desktop.
*/
/*!
+ \qmlattachedproperty string Screen::manufacturer
+ \readonly
+ \since 5.10
+
+ The manufacturer of the screen.
+*/
+/*!
+ \qmlattachedproperty string Screen::model
+ \readonly
+ \since 5.10
+
+ The model of the screen.
+*/
+/*!
+ \qmlattachedproperty string Screen::serialNumber
+ \readonly
+ \since 5.10
+
+ The serial number of the screen.
+*/
+/*!
\qmlattachedproperty int Screen::width
\readonly
@@ -234,6 +255,27 @@ QString QQuickScreenInfo::name() const
return m_screen->name();
}
+QString QQuickScreenInfo::manufacturer() const
+{
+ if (!m_screen)
+ return QString();
+ return m_screen->manufacturer();
+}
+
+QString QQuickScreenInfo::model() const
+{
+ if (!m_screen)
+ return QString();
+ return m_screen->model();
+}
+
+QString QQuickScreenInfo::serialNumber() const
+{
+ if (!m_screen)
+ return QString();
+ return m_screen->serialNumber();
+}
+
int QQuickScreenInfo::width() const
{
if (!m_screen)
@@ -335,6 +377,12 @@ void QQuickScreenInfo::setWrappedScreen(QScreen *screen)
}
if (!oldScreen || screen->name() != oldScreen->name())
emit nameChanged();
+ if (!oldScreen || screen->manufacturer() != oldScreen->manufacturer())
+ emit manufacturerChanged();
+ if (!oldScreen || screen->model() != oldScreen->model())
+ emit modelChanged();
+ if (!oldScreen || screen->serialNumber() != oldScreen->serialNumber())
+ emit serialNumberChanged();
if (!oldScreen || screen->orientation() != oldScreen->orientation())
emit orientationChanged();
if (!oldScreen || screen->primaryOrientation() != oldScreen->primaryOrientation())
diff --git a/src/quick/items/qquickscreen_p.h b/src/quick/items/qquickscreen_p.h
index 99e1466631..e9db07d14c 100644
--- a/src/quick/items/qquickscreen_p.h
+++ b/src/quick/items/qquickscreen_p.h
@@ -68,6 +68,9 @@ class Q_AUTOTEST_EXPORT QQuickScreenInfo : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
+ Q_PROPERTY(QString manufacturer READ manufacturer NOTIFY manufacturerChanged REVISION 10)
+ Q_PROPERTY(QString model READ model NOTIFY modelChanged REVISION 10)
+ Q_PROPERTY(QString serialNumber READ serialNumber NOTIFY serialNumberChanged REVISION 10)
Q_PROPERTY(int width READ width NOTIFY widthChanged)
Q_PROPERTY(int height READ height NOTIFY heightChanged)
Q_PROPERTY(int desktopAvailableWidth READ desktopAvailableWidth NOTIFY desktopGeometryChanged)
@@ -87,6 +90,9 @@ public:
QQuickScreenInfo(QObject *parent = nullptr, QScreen *wrappedScreen = nullptr);
QString name() const;
+ QString manufacturer() const;
+ QString model() const;
+ QString serialNumber() const;
int width() const;
int height() const;
int desktopAvailableWidth() const;
@@ -104,6 +110,9 @@ public:
Q_SIGNALS:
void nameChanged();
+ Q_REVISION(10) void manufacturerChanged();
+ Q_REVISION(10) void modelChanged();
+ Q_REVISION(10) void serialNumberChanged();
void widthChanged();
void heightChanged();
void desktopGeometryChanged();
diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp
index 6b1b16618a..f61bad1179 100644
--- a/src/quick/items/qquickshadereffectsource.cpp
+++ b/src/quick/items/qquickshadereffectsource.cpp
@@ -189,6 +189,7 @@ QQuickShaderEffectSource::QQuickShaderEffectSource(QQuickItem *parent)
, m_sourceItem(0)
, m_textureSize(0, 0)
, m_format(RGBA)
+ , m_samples(0)
, m_live(true)
, m_hideSource(false)
, m_mipmap(false)
@@ -582,6 +583,44 @@ void QQuickShaderEffectSource::setTextureMirroring(TextureMirroring mirroring)
}
/*!
+ \qmlproperty int QtQuick::ShaderEffectSource::samples
+ \since 5.10
+
+ This property allows requesting multisampled rendering.
+
+ By default multisampling is enabled whenever multisampling is enabled for
+ the entire window, assuming the scenegraph renderer in use and the
+ underlying graphics API supports this.
+
+ By setting the value to 2, 4, etc. multisampled rendering can be requested
+ for a part of the scene without enabling multisampling for the entire
+ scene. This way multisampling is applied only to a given subtree, which can
+ lead to significant performance gains since multisampling is not applied to
+ other parts of the scene.
+
+ \note Enabling multisampling can be potentially expensive regardless of the
+ layer's size, as it incurs a hardware and driver dependent performance and
+ memory cost.
+
+ \note This property is only functional when support for multisample
+ renderbuffers and framebuffer blits is available. Otherwise the value is
+ silently ignored.
+ */
+int QQuickShaderEffectSource::samples() const
+{
+ return m_samples;
+}
+
+void QQuickShaderEffectSource::setSamples(int count)
+{
+ if (count == m_samples)
+ return;
+ m_samples = count;
+ update();
+ emit samplesChanged();
+}
+
+/*!
\qmlmethod QtQuick::ShaderEffectSource::scheduleUpdate()
Schedules a re-rendering of the texture for the next frame.
@@ -683,6 +722,7 @@ QSGNode *QQuickShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaint
m_texture->setHasMipmaps(m_mipmap);
m_texture->setMirrorHorizontal(m_textureMirroring & MirrorHorizontally);
m_texture->setMirrorVertical(m_textureMirroring & MirrorVertically);
+ m_texture->setSamples(m_samples);
if (m_grab)
m_texture->scheduleUpdate();
diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h
index 5e7e354feb..d9f9079a3d 100644
--- a/src/quick/items/qquickshadereffectsource_p.h
+++ b/src/quick/items/qquickshadereffectsource_p.h
@@ -88,6 +88,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickShaderEffectSource : public QQuickItem, publi
Q_PROPERTY(bool mipmap READ mipmap WRITE setMipmap NOTIFY mipmapChanged)
Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged)
Q_PROPERTY(TextureMirroring textureMirroring READ textureMirroring WRITE setTextureMirroring NOTIFY textureMirroringChanged REVISION 1)
+ Q_PROPERTY(int samples READ samples WRITE setSamples NOTIFY samplesChanged REVISION 2)
public:
enum WrapMode {
@@ -150,6 +151,9 @@ public:
Q_INVOKABLE void scheduleUpdate();
+ int samples() const;
+ void setSamples(int count);
+
Q_SIGNALS:
void wrapModeChanged();
void sourceItemChanged();
@@ -161,6 +165,7 @@ Q_SIGNALS:
void mipmapChanged();
void recursiveChanged();
void textureMirroringChanged();
+ void samplesChanged();
void scheduledUpdateCompleted();
@@ -185,6 +190,7 @@ private:
QRectF m_sourceRect;
QSize m_textureSize;
Format m_format;
+ int m_samples;
uint m_live : 1;
uint m_hideSource : 1;
uint m_mipmap : 1;
diff --git a/src/quick/items/qquickstateoperations.cpp b/src/quick/items/qquickstateoperations.cpp
index b40a9e2843..a4ce13a199 100644
--- a/src/quick/items/qquickstateoperations.cpp
+++ b/src/quick/items/qquickstateoperations.cpp
@@ -101,7 +101,7 @@ void QQuickParentChangePrivate::doChange(QQuickItem *targetParent, QQuickItem *s
}
if (scale != 0)
- rotation = qAtan2(transform.m12()/scale, transform.m11()/scale) * 180/M_PI;
+ rotation = qRadiansToDegrees(qAtan2(transform.m12() / scale, transform.m11() / scale));
else {
qmlWarning(q) << QQuickParentChange::tr("Unable to preserve appearance under scale of 0");
ok = false;
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index 6d73af80fe..2e66367e85 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -269,9 +269,6 @@ void QQuickTextPrivate::updateLayout()
formatModifiesFontSize = fontSizeModified;
multilengthEos = -1;
} else {
- layout.clearFormats();
- if (elideLayout)
- elideLayout->clearFormats();
QString tmp = text;
multilengthEos = tmp.indexOf(QLatin1Char('\x9c'));
if (multilengthEos != -1)
@@ -359,8 +356,8 @@ void QQuickTextPrivate::updateSize()
}
if (!requireImplicitSize) {
- emit q->implicitWidthChanged();
- emit q->implicitHeightChanged();
+ implicitWidthChanged();
+ implicitHeightChanged();
// if the implicitWidth is used, then updateSize() has already been called (recursively)
if (requireImplicitSize)
return;
@@ -384,6 +381,7 @@ void QQuickTextPrivate::updateSize()
updateBaseline(fm.ascent(), q->height() - fontHeight - vPadding);
q->setImplicitSize(hPadding, fontHeight + vPadding);
layedOutTextRect = QRectF(0, 0, 0, fontHeight);
+ advance = QSizeF();
emit q->contentSizeChanged();
updateType = UpdatePaintNode;
q->update();
@@ -457,8 +455,26 @@ void QQuickTextPrivate::updateSize()
if (iWidth == -1)
q->setImplicitHeight(size.height() + vPadding);
+
+ QTextBlock firstBlock = extra->doc->firstBlock();
+ while (firstBlock.layout()->lineCount() == 0)
+ firstBlock = firstBlock.next();
+
+ QTextBlock lastBlock = extra->doc->lastBlock();
+ while (lastBlock.layout()->lineCount() == 0)
+ lastBlock = lastBlock.previous();
+
+ if (firstBlock.lineCount() > 0 && lastBlock.lineCount() > 0) {
+ QTextLine firstLine = firstBlock.layout()->lineAt(0);
+ QTextLine lastLine = lastBlock.layout()->lineAt(lastBlock.layout()->lineCount() - 1);
+ advance = QSizeF(lastLine.horizontalAdvance(),
+ (lastLine.y() + lastBlock.layout()->position().y()) - (firstLine.y() + firstBlock.layout()->position().y()));
+ } else {
+ advance = QSizeF();
+ }
}
+
if (layedOutTextRect.size() != previousSize)
emit q->contentSizeChanged();
updateType = UpdatePaintNode;
@@ -613,6 +629,13 @@ QString QQuickTextPrivate::elidedText(qreal lineWidth, const QTextLine &line, QT
}
}
+void QQuickTextPrivate::clearFormats()
+{
+ layout.clearFormats();
+ if (elideLayout)
+ elideLayout->clearFormats();
+}
+
/*!
Lays out the QQuickTextPrivate::layout QTextLayout in the constraints of the QQuickText.
@@ -968,6 +991,16 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
br.moveTop(0);
+ // Find the advance of the text layout
+ if (layout.lineCount() > 0) {
+ QTextLine firstLine = layout.lineAt(0);
+ QTextLine lastLine = layout.lineAt(layout.lineCount() - 1);
+ advance = QSizeF(lastLine.horizontalAdvance(),
+ lastLine.y() - firstLine.y());
+ } else {
+ advance = QSizeF();
+ }
+
if (!horizontalFit && !verticalFit)
break;
@@ -1031,7 +1064,8 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
elideLayout = new QTextLayout;
elideLayout->setCacheEnabled(true);
}
- if (styledText) {
+ QTextEngine *engine = layout.engine();
+ if (engine && engine->hasFormats()) {
QVector<QTextLayout::FormatRange> formats;
switch (elideMode) {
case QQuickText::ElideRight:
@@ -1470,6 +1504,19 @@ QQuickText::~QQuickText()
Text { text: "Hello"; renderType: Text.NativeRendering; font.hintingPreference: Font.PreferVerticalHinting }
\endqml
*/
+
+/*!
+ \qmlproperty bool QtQuick::Text::font.kerning
+ \since 5.10
+
+ Enables or disables the kerning OpenType feature when shaping the text. This may improve performance
+ when creating or changing the text, at the expense of some cosmetic features. The default value
+ is true.
+
+ \qml
+ Text { text: "OATS FLAVOUR WAY"; font.kerning: false }
+ \endqml
+*/
QFont QQuickText::font() const
{
Q_D(const QQuickText);
@@ -1570,6 +1617,7 @@ void QQuickText::setText(const QString &n)
d->extra->doc->setText(n);
d->rightToLeftText = d->extra->doc->toPlainText().isRightToLeft();
} else {
+ d->clearFormats();
d->rightToLeftText = d->text.isRightToLeft();
}
d->determineHorizontalAlignment();
@@ -2060,6 +2108,7 @@ void QQuickText::setTextFormat(TextFormat format)
d->extra->doc->setText(d->text);
d->rightToLeftText = d->extra->doc->toPlainText().isRightToLeft();
} else {
+ d->clearFormats();
d->rightToLeftText = d->text.isRightToLeft();
d->textHasChanged = true;
}
@@ -3055,6 +3104,24 @@ QJSValue QQuickText::fontInfo() const
return value;
}
+/*!
+ \qmlproperty size QtQuick::Text::advance
+ \since 5.10
+
+ The distance, in pixels, from the baseline origin of the first
+ character of the text item, to the baseline origin of the first
+ character in a text item occurring directly after this one
+ in a text flow.
+
+ Note that the advance can be negative if the text flows from
+ the right to the left.
+*/
+QSizeF QQuickText::advance() const
+{
+ Q_D(const QQuickText);
+ return d->advance;
+}
+
QT_END_NAMESPACE
#include "moc_qquicktext_p.cpp"
diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h
index b190738cfb..a56bcdb87b 100644
--- a/src/quick/items/qquicktext_p.h
+++ b/src/quick/items/qquicktext_p.h
@@ -99,6 +99,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickText : public QQuickImplicitSizeItem
Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6)
Q_PROPERTY(QJSValue fontInfo READ fontInfo NOTIFY fontInfoChanged REVISION 9)
+ Q_PROPERTY(QSizeF advance READ advance NOTIFY contentSizeChanged REVISION 10)
public:
QQuickText(QQuickItem *parent=0);
@@ -251,6 +252,7 @@ public:
void resetBottomPadding();
QJSValue fontInfo() const;
+ QSizeF advance() const;
Q_SIGNALS:
void textChanged(const QString &text);
diff --git a/src/quick/items/qquicktext_p_p.h b/src/quick/items/qquicktext_p_p.h
index 6456750359..957641ec0a 100644
--- a/src/quick/items/qquicktext_p_p.h
+++ b/src/quick/items/qquicktext_p_p.h
@@ -85,10 +85,12 @@ public:
int lineHeightOffset() const;
QString elidedText(qreal lineWidth, const QTextLine &line, QTextLine *nextLine = 0) const;
void elideFormats(int start, int length, int offset, QVector<QTextLayout::FormatRange> *elidedFormats);
+ void clearFormats();
void processHoverEvent(QHoverEvent *event);
QRectF layedOutTextRect;
+ QSizeF advance;
struct ExtraData {
ExtraData();
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index 61d610520f..aec8666dc4 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -356,6 +356,19 @@ QString QQuickTextEdit::text() const
*/
/*!
+ \qmlproperty bool QtQuick::TextEdit::font.kerning
+ \since 5.10
+
+ Enables or disables the kerning OpenType feature when shaping the text. This may improve performance
+ when creating or changing the text, at the expense of some cosmetic features. The default value
+ is true.
+
+ \qml
+ TextEdit { text: "OATS FLAVOUR WAY"; kerning: font.false }
+ \endqml
+*/
+
+/*!
\qmlproperty string QtQuick::TextEdit::text
The text to display. If the text format is AutoText the text edit will
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index 43899ba457..318a2fd9a3 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -378,6 +378,19 @@ QString QQuickTextInputPrivate::realText() const
TextInput { text: "Hello"; renderType: TextInput.NativeRendering; font.hintingPreference: Font.PreferVerticalHinting }
\endqml
*/
+
+/*!
+ \qmlproperty bool QtQuick::TextInput::font.kerning
+ \since 5.10
+
+ Enables or disables the kerning OpenType feature when shaping the text. This may improve performance
+ when creating or changing the text, at the expense of some cosmetic features. The default value
+ is true.
+
+ \qml
+ TextInput { text: "OATS FLAVOUR WAY"; font.kerning: false }
+ \endqml
+*/
QFont QQuickTextInput::font() const
{
Q_D(const QQuickTextInput);
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index c124150b8d..ce1016579c 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -2798,6 +2798,8 @@ void QQuickWindowPrivate::contextCreationFailureMessage(const QSurfaceFormat &fo
#endif // !Q_OS_WIN32
}
+#if QT_DEPRECATED_SINCE(5, 8)
+
/*!
Propagates an event \a e to a QQuickItem \a item on the window.
@@ -2850,6 +2852,8 @@ bool QQuickWindow::sendEvent(QQuickItem *item, QEvent *e)
return false;
}
+#endif
+
void QQuickWindowPrivate::cleanupNodes()
{
for (int ii = 0; ii < cleanupNodeList.count(); ++ii)
@@ -3451,6 +3455,11 @@ void QQuickWindow::setRenderTarget(QOpenGLFramebufferObject *fbo)
The specified FBO must be created in the context of the window
or one that shares with it.
+ \note \a fboId can also be set to 0. In this case rendering will target the
+ default framebuffer of whichever surface is current when the scenegraph
+ renders. \a size must still be valid, specifying the dimensions of the
+ surface.
+
\note
This function only has an effect when using the default OpenGL scene
graph adaptation.
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index 9c3e7277bc..d1a16fbeb6 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -112,7 +112,9 @@ public:
QQuickItem *mouseGrabberItem() const;
- bool sendEvent(QQuickItem *, QEvent *);
+#if QT_DEPRECATED_SINCE(5, 8)
+ QT_DEPRECATED bool sendEvent(QQuickItem *, QEvent *);
+#endif
QImage grabWindow();
#if QT_CONFIG(opengl)
diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp
index c1cc02568c..45e3f0004d 100644
--- a/src/quick/items/qquickwindowmodule.cpp
+++ b/src/quick/items/qquickwindowmodule.cpp
@@ -200,6 +200,7 @@ void QQuickWindowModule::defineModule()
qmlRegisterUncreatableType<QQuickScreen>(uri, 2, 0, "Screen", QStringLiteral("Screen can only be used via the attached property."));
qmlRegisterUncreatableType<QQuickScreen,1>(uri, 2, 3, "Screen", QStringLiteral("Screen can only be used via the attached property."));
qmlRegisterUncreatableType<QQuickScreenInfo,2>(uri, 2, 3, "ScreenInfo", QStringLiteral("ScreenInfo can only be used via the attached property."));
+ qmlRegisterUncreatableType<QQuickScreenInfo,10>(uri, 2, 10, "ScreenInfo", QStringLiteral("ScreenInfo can only be used via the attached property."));
}
QT_END_NAMESPACE
diff --git a/src/quick/items/shaders/lineargradient.frag b/src/quick/items/shaders/lineargradient.frag
new file mode 100644
index 0000000000..7f4a739109
--- /dev/null
+++ b/src/quick/items/shaders/lineargradient.frag
@@ -0,0 +1,9 @@
+uniform sampler2D gradTabTexture;
+uniform highp float opacity;
+
+varying highp float gradTabIndex;
+
+void main()
+{
+ gl_FragColor = texture2D(gradTabTexture, vec2(gradTabIndex, 0.5)) * opacity;
+}
diff --git a/src/quick/items/shaders/lineargradient.vert b/src/quick/items/shaders/lineargradient.vert
new file mode 100644
index 0000000000..eb21b8886b
--- /dev/null
+++ b/src/quick/items/shaders/lineargradient.vert
@@ -0,0 +1,15 @@
+attribute vec4 vertexCoord;
+attribute vec4 vertexColor;
+
+uniform mat4 matrix;
+uniform vec2 gradStart;
+uniform vec2 gradEnd;
+
+varying float gradTabIndex;
+
+void main()
+{
+ vec2 gradVec = gradEnd - gradStart;
+ gradTabIndex = dot(gradVec, vertexCoord.xy - gradStart) / (gradVec.x * gradVec.x + gradVec.y * gradVec.y);
+ gl_Position = matrix * vertexCoord;
+}
diff --git a/src/quick/items/shaders/lineargradient_core.frag b/src/quick/items/shaders/lineargradient_core.frag
new file mode 100644
index 0000000000..5908acfa67
--- /dev/null
+++ b/src/quick/items/shaders/lineargradient_core.frag
@@ -0,0 +1,12 @@
+#version 150 core
+
+uniform sampler2D gradTabTexture;
+uniform float opacity;
+
+in float gradTabIndex;
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = texture(gradTabTexture, vec2(gradTabIndex, 0.5)) * opacity;
+}
diff --git a/src/quick/items/shaders/lineargradient_core.vert b/src/quick/items/shaders/lineargradient_core.vert
new file mode 100644
index 0000000000..60b56f38e3
--- /dev/null
+++ b/src/quick/items/shaders/lineargradient_core.vert
@@ -0,0 +1,17 @@
+#version 150 core
+
+in vec4 vertexCoord;
+in vec4 vertexColor;
+
+uniform mat4 matrix;
+uniform vec2 gradStart;
+uniform vec2 gradEnd;
+
+out float gradTabIndex;
+
+void main()
+{
+ vec2 gradVec = gradEnd - gradStart;
+ gradTabIndex = dot(gradVec, vertexCoord.xy - gradStart) / (gradVec.x * gradVec.x + gradVec.y * gradVec.y);
+ gl_Position = matrix * vertexCoord;
+}
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer_p.h
index d3f13e40b1..9f5a22e66f 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer_p.h
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer_p.h
@@ -93,6 +93,7 @@ public:
void setDevicePixelRatio(qreal ratio) override;
void setMirrorHorizontal(bool mirror) override;
void setMirrorVertical(bool mirror) override;
+ void setSamples(int) override { }
public slots:
void markDirtyTexture() override;
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp
index f8c1a3d90b..ad6cf39425 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp
@@ -64,7 +64,7 @@ void QSGSoftwarePixmapRenderer::renderScene(uint)
class B : public QSGBindable
{
public:
- void bind() const { }
+ void bind() const override { }
} bindable;
QSGRenderer::renderScene(bindable);
}
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes.cpp
index 384c124a02..77d21ec042 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes.cpp
@@ -101,10 +101,10 @@ void QSGSoftwareImageNode::paint(QPainter *painter)
if (!m_cachedPixmap.isNull()) {
painter->drawPixmap(m_rect, m_cachedPixmap, m_sourceRect);
- } else if (QSGSoftwarePixmapTexture *pt = dynamic_cast<QSGSoftwarePixmapTexture *>(m_texture)) {
+ } else if (QSGSoftwarePixmapTexture *pt = qobject_cast<QSGSoftwarePixmapTexture *>(m_texture)) {
const QPixmap &pm = pt->pixmap();
painter->drawPixmap(m_rect, pm, m_sourceRect);
- } else if (QSGPlainTexture *pt = dynamic_cast<QSGPlainTexture *>(m_texture)) {
+ } else if (QSGPlainTexture *pt = qobject_cast<QSGPlainTexture *>(m_texture)) {
const QImage &im = pt->image();
painter->drawImage(m_rect, im, m_sourceRect);
}
@@ -116,14 +116,14 @@ void QSGSoftwareImageNode::updateCachedMirroredPixmap()
m_cachedPixmap = QPixmap();
} else {
- if (QSGSoftwarePixmapTexture *pt = dynamic_cast<QSGSoftwarePixmapTexture *>(m_texture)) {
+ if (QSGSoftwarePixmapTexture *pt = qobject_cast<QSGSoftwarePixmapTexture *>(m_texture)) {
QTransform mirrorTransform;
if (m_transformMode.testFlag(MirrorVertically))
mirrorTransform = mirrorTransform.scale(1, -1);
if (m_transformMode.testFlag(MirrorHorizontally))
mirrorTransform = mirrorTransform.scale(-1, 1);
m_cachedPixmap = pt->pixmap().transformed(mirrorTransform);
- } else if (QSGPlainTexture *pt = dynamic_cast<QSGPlainTexture *>(m_texture)) {
+ } else if (QSGPlainTexture *pt = qobject_cast<QSGPlainTexture *>(m_texture)) {
m_cachedPixmap = QPixmap::fromImage(pt->image().mirrored(m_transformMode.testFlag(MirrorHorizontally), m_transformMode.testFlag(MirrorVertically)));
} else {
m_cachedPixmap = QPixmap();
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp
index e5b9430236..cecc6c21ca 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp
@@ -277,18 +277,21 @@ QRegion QSGSoftwareRenderableNode::renderNode(QPainter *painter, bool forceOpaqu
QMatrix4x4 m = m_transform;
rd->m_matrix = &m;
rd->m_opacity = m_opacity;
- RenderNodeState rs;
- rs.cr = m_clipRegion;
- const QRect br = m_handle.renderNode->flags().testFlag(QSGRenderNode::BoundedRectRendering)
- ? m_boundingRectMax :
- QRect(0, 0, painter->device()->width(), painter->device()->height());
+ // all the clip region below is in world coordinates, taking m_transform into account already
+ QRegion cr = m_dirtyRegion;
+ if (m_clipRegion.rectCount() > 1)
+ cr &= m_clipRegion;
painter->save();
- painter->setClipRegion(br, Qt::ReplaceClip);
+ RenderNodeState rs;
+ rs.cr = cr;
m_handle.renderNode->render(&rs);
painter->restore();
+ const QRect br = m_handle.renderNode->flags().testFlag(QSGRenderNode::BoundedRectRendering)
+ ? m_boundingRectMax // already mapped to world
+ : QRect(0, 0, painter->device()->width(), painter->device()->height());
m_previousDirtyRegion = QRegion(br);
m_isDirty = false;
m_dirtyRegion = QRegion();
@@ -299,7 +302,7 @@ QRegion QSGSoftwareRenderableNode::renderNode(QPainter *painter, bool forceOpaqu
painter->save();
painter->setOpacity(m_opacity);
- // Set clipRegion to m_dirtyRegion (in world coordinates)
+ // Set clipRegion to m_dirtyRegion (in world coordinates, so must be done before the setTransform below)
// as m_dirtyRegion already accounts for clipRegion
painter->setClipRegion(m_dirtyRegion, Qt::ReplaceClip);
if (m_clipRegion.rectCount() > 1)
@@ -316,10 +319,10 @@ QRegion QSGSoftwareRenderableNode::renderNode(QPainter *painter, bool forceOpaqu
case QSGSoftwareRenderableNode::SimpleTexture:
{
QSGTexture *texture = m_handle.simpleTextureNode->texture();
- if (QSGSoftwarePixmapTexture *pt = dynamic_cast<QSGSoftwarePixmapTexture *>(texture)) {
+ if (QSGSoftwarePixmapTexture *pt = qobject_cast<QSGSoftwarePixmapTexture *>(texture)) {
const QPixmap &pm = pt->pixmap();
painter->drawPixmap(m_handle.simpleTextureNode->rect(), pm, m_handle.simpleTextureNode->sourceRect());
- } else if (QSGPlainTexture *pt = dynamic_cast<QSGPlainTexture *>(texture)) {
+ } else if (QSGPlainTexture *pt = qobject_cast<QSGPlainTexture *>(texture)) {
const QImage &im = pt->image();
painter->drawImage(m_handle.simpleTextureNode->rect(), im, m_handle.simpleTextureNode->sourceRect());
}
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp
index cad826fb27..85d04fe136 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp
@@ -90,7 +90,7 @@ void QSGSoftwareRenderer::renderScene(uint)
class B : public QSGBindable
{
public:
- void bind() const { }
+ void bind() const override { }
} bindable;
QSGRenderer::renderScene(bindable);
}
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp
index 19f16a79fb..832b69d0cc 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp
@@ -188,8 +188,8 @@ public:
delete rc;
}
- bool event(QEvent *e);
- void run();
+ bool event(QEvent *e) override;
+ void run() override;
void syncAndRender();
void sync(bool inExpose);
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer.cpp b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
index 0458e2dead..8fbd402a2f 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
@@ -134,6 +134,7 @@ QSGRenderer::QSGRenderer(QSGRenderContext *context)
, m_bindable(0)
, m_changed_emitted(false)
, m_is_rendering(false)
+ , m_is_preprocessing(false)
{
}
@@ -189,7 +190,7 @@ void QSGRenderer::renderScene(uint fboId)
class B : public QSGBindable
{
public:
- void bind() const { QOpenGLFramebufferObject::bindDefault(); }
+ void bind() const override { QOpenGLFramebufferObject::bindDefault(); }
} bindable;
renderScene(bindable);
}
@@ -287,6 +288,8 @@ void QSGRenderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state)
void QSGRenderer::preprocess()
{
+ m_is_preprocessing = true;
+
QSGRootNode *root = rootNode();
Q_ASSERT(root);
@@ -298,6 +301,11 @@ void QSGRenderer::preprocess()
for (QSet<QSGNode *>::const_iterator it = items.constBegin();
it != items.constEnd(); ++it) {
QSGNode *n = *it;
+
+ // If we are currently preprocessing, check this node hasn't been
+ // deleted or something. we don't want a use-after-free!
+ if (m_nodes_dont_preprocess.contains(n)) // skip
+ continue;
if (!nodeUpdater()->isNodeBlocked(n, root)) {
n->preprocess();
}
@@ -315,8 +323,13 @@ void QSGRenderer::preprocess()
updatePassTime = frameTimer.nsecsElapsed();
Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRendererFrame,
QQuickProfiler::SceneGraphRendererUpdate);
+
+ m_is_preprocessing = false;
+ m_nodes_dont_preprocess.clear();
}
+
+
void QSGRenderer::addNodesToPreprocess(QSGNode *node)
{
for (QSGNode *c = node->firstChild(); c; c = c->nextSibling())
@@ -329,8 +342,13 @@ void QSGRenderer::removeNodesToPreprocess(QSGNode *node)
{
for (QSGNode *c = node->firstChild(); c; c = c->nextSibling())
removeNodesToPreprocess(c);
- if (node->flags() & QSGNode::UsePreprocess)
+ if (node->flags() & QSGNode::UsePreprocess) {
m_nodes_to_preprocess.remove(node);
+
+ // If preprocessing *now*, mark the node as gone.
+ if (m_is_preprocessing)
+ m_nodes_dont_preprocess.insert(node);
+ }
}
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer_p.h b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
index 4589685765..1ea2775e6f 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
@@ -118,11 +118,13 @@ private:
QSGNodeUpdater *m_node_updater;
QSet<QSGNode *> m_nodes_to_preprocess;
+ QSet<QSGNode *> m_nodes_dont_preprocess;
const QSGBindable *m_bindable;
uint m_changed_emitted : 1;
uint m_is_rendering : 1;
+ uint m_is_preprocessing : 1;
};
class Q_QUICK_PRIVATE_EXPORT QSGBindable
diff --git a/src/quick/scenegraph/coreapi/qsgrendernode.cpp b/src/quick/scenegraph/coreapi/qsgrendernode.cpp
index 1bc0210b72..a8954848d6 100644
--- a/src/quick/scenegraph/coreapi/qsgrendernode.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrendernode.cpp
@@ -267,6 +267,10 @@ QSGRenderNode::RenderingFlags QSGRenderNode::flags() const
For rendernodes covering the entire area of a corresponding QQuickItem the
return value will be (0, 0, item->width(), item->height()).
+ \note Nodes are also free to render outside the boundaries specified by the
+ item's width and height, since the scenegraph nodes are not bounded by the
+ QQuickItem geometry, as long as this is reported correctly from this function.
+
\sa flags()
*/
QRectF QSGRenderNode::rect() const
@@ -359,7 +363,10 @@ QSGRenderNode::RenderState::~RenderState()
of the render state is not in use. However, the clip region that can be set
on the QPainter still has to be communicated since reconstructing this
manually in render() is not reasonable. It can therefore be queried via
- this function.
+ this function. The region is in world coordinates and can be passed
+ to QPainter::setClipRegion() with Qt::ReplaceClip. This must be done before
+ calling QPainter::setTransform() since the clip region is already mapped to
+ the transform provided in QSGRenderNode::matrix().
*/
/*!
diff --git a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp
index 2b70139b37..1fdc1720f7 100644
--- a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp
+++ b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include <QtCore/QByteArray>
+#include <QtCore/QString>
#include <QtGui/QSurfaceFormat>
// Duct Tape tokenizer for the purpose of parsing and rewriting
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
index 0f7e555aa7..c64360f955 100644
--- a/src/quick/scenegraph/qsgadaptationlayer.cpp
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -40,7 +40,6 @@
#include "qsgadaptationlayer_p.h"
#include <qmath.h>
-#include <QtQuick/private/qsgdistancefieldutil_p.h>
#include <QtQuick/private/qsgdistancefieldglyphnode_p.h>
#include <QtQuick/private/qsgcontext_p.h>
#include <private/qrawfont_p.h>
@@ -57,9 +56,8 @@ static QElapsedTimer qsg_render_timer;
QSGDistanceFieldGlyphCache::Texture QSGDistanceFieldGlyphCache::s_emptyTexture;
-QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font)
- : m_manager(man)
- , m_pendingGlyphs(64)
+QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QOpenGLContext *c, const QRawFont &font)
+ : m_pendingGlyphs(64)
{
Q_ASSERT(font.isValid());
diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h
index 03a1f7f281..ba146b884f 100644
--- a/src/quick/scenegraph/qsgadaptationlayer_p.h
+++ b/src/quick/scenegraph/qsgadaptationlayer_p.h
@@ -73,7 +73,6 @@ QT_BEGIN_NAMESPACE
class QSGNode;
class QImage;
class TextureReference;
-class QSGDistanceFieldGlyphCacheManager;
class QSGDistanceFieldGlyphNode;
class QOpenGLContext;
class QSGInternalImageNode;
@@ -209,6 +208,7 @@ public:
virtual void setDevicePixelRatio(qreal ratio) = 0;
virtual void setMirrorHorizontal(bool mirror) = 0;
virtual void setMirrorVertical(bool mirror) = 0;
+ virtual void setSamples(int samples) = 0;
Q_SLOT virtual void markDirtyTexture() = 0;
Q_SLOT virtual void invalidated() = 0;
@@ -408,7 +408,7 @@ public:
class Q_QUICK_PRIVATE_EXPORT QSGDistanceFieldGlyphCache
{
public:
- QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font);
+ QSGDistanceFieldGlyphCache(QOpenGLContext *c, const QRawFont &font);
virtual ~QSGDistanceFieldGlyphCache();
struct Metrics {
@@ -442,8 +442,6 @@ public:
bool operator == (const Texture &other) const { return textureId == other.textureId; }
};
- const QSGDistanceFieldGlyphCacheManager *manager() const { return m_manager; }
-
const QRawFont &referenceFont() const { return m_referenceFont; }
qreal fontScale(qreal pixelSize) const
@@ -513,8 +511,6 @@ protected:
inline bool isCoreProfile() const { return m_coreProfile; }
private:
- QSGDistanceFieldGlyphCacheManager *m_manager;
-
QRawFont m_referenceFont;
int m_glyphCount;
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index c0a054a539..d460794573 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -228,14 +228,6 @@ public:
int m_good;
};
-class QSGTextureCleanupEvent : public QEvent
-{
-public:
- QSGTextureCleanupEvent(QSGTexture *t) : QEvent(QEvent::User), texture(t) { }
- ~QSGTextureCleanupEvent() { delete texture; }
- QSGTexture *texture;
-};
-
/*!
\class QSGContext
@@ -333,7 +325,6 @@ QSGRendererInterface *QSGContext::rendererInterface(QSGRenderContext *renderCont
QSGRenderContext::QSGRenderContext(QSGContext *context)
: m_sg(context)
- , m_distanceFieldCacheManager(0)
{
}
diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h
index 1c4cd0ce90..84a2523f26 100644
--- a/src/quick/scenegraph/qsgcontext_p.h
+++ b/src/quick/scenegraph/qsgcontext_p.h
@@ -78,7 +78,6 @@ class QSGMaterial;
class QSGRenderLoop;
class QSGLayer;
class QQuickTextureFactory;
-class QSGDistanceFieldGlyphCacheManager;
class QSGContext;
class QQuickPaintedItem;
class QSGRendererInterface;
@@ -195,7 +194,7 @@ protected:
QMutex m_mutex;
QHash<QQuickTextureFactory *, QSGTexture *> m_textures;
QSet<QSGTexture *> m_texturesToDelete;
- QSGDistanceFieldGlyphCacheManager *m_distanceFieldCacheManager;
+ QHash<QString, QSGDistanceFieldGlyphCache *> m_glyphCaches;
QSet<QFontEngine *> m_fontEnginesToClean;
};
diff --git a/src/quick/scenegraph/qsgcontextplugin.cpp b/src/quick/scenegraph/qsgcontextplugin.cpp
index b8b5141957..bd311d3b46 100644
--- a/src/quick/scenegraph/qsgcontextplugin.cpp
+++ b/src/quick/scenegraph/qsgcontextplugin.cpp
@@ -49,6 +49,9 @@
#include <QtQuick/private/qsgdefaultcontext_p.h>
#endif
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/qpa/qplatformintegration.h>
+
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(QSG_LOG_INFO)
@@ -128,12 +131,12 @@ QSGAdaptationBackendData *contextFactory()
if (requestedBackend.isEmpty() && qEnvironmentVariableIsSet("QT_QUICK_BACKEND"))
requestedBackend = QString::fromLocal8Bit(qgetenv("QT_QUICK_BACKEND"));
-#if !QT_CONFIG(opengl)
- // If this is a build without OpenGL, and no backend has been set
+ // If this platform does not support OpenGL, and no backend has been set
// default to the software renderer
- if (requestedBackend.isEmpty())
+ if (requestedBackend.isEmpty()
+ && !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) {
requestedBackend = QString::fromLocal8Bit("software");
-#endif
+ }
if (!requestedBackend.isEmpty()) {
qCDebug(QSG_LOG_INFO) << "Loading backend" << requestedBackend;
diff --git a/src/quick/scenegraph/qsgdefaultcontext.cpp b/src/quick/scenegraph/qsgdefaultcontext.cpp
index 405f1d86a4..be5fec9dab 100644
--- a/src/quick/scenegraph/qsgdefaultcontext.cpp
+++ b/src/quick/scenegraph/qsgdefaultcontext.cpp
@@ -39,7 +39,6 @@
#include "qsgdefaultcontext_p.h"
-#include <QtQuick/private/qsgdistancefieldutil_p.h>
#include <QtQuick/private/qsgdefaultinternalrectanglenode_p.h>
#include <QtQuick/private/qsgdefaultinternalimagenode_p.h>
#include <QtQuick/private/qsgdefaultpainternode_p.h>
@@ -68,13 +67,13 @@ QT_BEGIN_NAMESPACE
namespace QSGMultisampleAntialiasing {
class ImageNode : public QSGDefaultInternalImageNode {
public:
- void setAntialiasing(bool) { }
+ void setAntialiasing(bool) override { }
};
class RectangleNode : public QSGDefaultInternalRectangleNode {
public:
- void setAntialiasing(bool) { }
+ void setAntialiasing(bool) override { }
};
}
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
index f0a336e229..7789ef8fb1 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
@@ -42,7 +42,6 @@
#include <QtGui/private/qdistancefield_p.h>
#include <QtGui/private/qopenglcontext_p.h>
#include <QtQml/private/qqmlglobal_p.h>
-#include <QtQuick/private/qsgdistancefieldutil_p.h>
#include <qopenglfunctions.h>
#include <qopenglframebufferobject.h>
#include <qmath.h>
@@ -60,8 +59,8 @@ DEFINE_BOOL_CONFIG_OPTION(qsgPreferFullSizeGlyphCacheTextures, QSG_PREFER_FULLSI
# define QSG_DEFAULT_DISTANCEFIELD_GLYPH_CACHE_PADDING 2
#endif
-QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font)
- : QSGDistanceFieldGlyphCache(man, c, font)
+QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QOpenGLContext *c, const QRawFont &font)
+ : QSGDistanceFieldGlyphCache(c, font)
, m_maxTextureSize(0)
, m_maxTextureCount(3)
, m_blitProgram(0)
@@ -72,12 +71,15 @@ QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QSGDistance
, m_coreFuncs(0)
#endif
{
- m_blitBuffer.create();
- m_blitBuffer.bind();
- static GLfloat buffer[16] = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
- 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
- m_blitBuffer.allocate(buffer, sizeof(buffer));
- m_blitBuffer.release();
+ if (Q_LIKELY(m_blitBuffer.create())) {
+ m_blitBuffer.bind();
+ static const GLfloat buffer[16] = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
+ m_blitBuffer.allocate(buffer, sizeof(buffer));
+ m_blitBuffer.release();
+ } else {
+ qWarning("Buffer creation failed");
+ }
m_areaAllocator = new QSGAreaAllocator(QSize(maxTextureSize(), m_maxTextureCount * maxTextureSize()));
}
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
index 57dc4a5d07..fe365495c2 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
@@ -69,7 +69,7 @@ class QOpenGLFunctions_3_2_Core;
class Q_QUICK_PRIVATE_EXPORT QSGDefaultDistanceFieldGlyphCache : public QSGDistanceFieldGlyphCache
{
public:
- QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font);
+ QSGDefaultDistanceFieldGlyphCache(QOpenGLContext *c, const QRawFont &font);
virtual ~QSGDefaultDistanceFieldGlyphCache();
void requestGlyphs(const QSet<glyph_t> &glyphs) override;
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
index b001899915..edb6e92a0d 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
@@ -91,11 +91,11 @@ class QSGTextMaskShader : public QSGMaterialShader
public:
QSGTextMaskShader(QFontEngine::GlyphFormat glyphFormat);
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
- virtual char const *const *attributeNames() const;
+ void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
+ char const *const *attributeNames() const override;
protected:
- virtual void initialize();
+ void initialize() override;
int m_matrix_id;
int m_color_id;
@@ -181,7 +181,7 @@ public:
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/8bittextmask.frag"));
}
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+ void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
};
void QSG8BitTextMaskShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
@@ -206,10 +206,10 @@ public:
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/24bittextmask.frag"));
}
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
- virtual void initialize();
- void activate();
- void deactivate();
+ void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
+ void initialize() override;
+ void activate() override;
+ void deactivate() override;
bool useSRGB() const;
uint m_useSRGB : 1;
@@ -326,10 +326,10 @@ public:
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/styledtext.frag"));
}
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+ void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
private:
- virtual void initialize();
+ void initialize() override;
int m_shift_id;
int m_styleColor_id;
diff --git a/src/quick/scenegraph/qsgdefaultinternalimagenode.cpp b/src/quick/scenegraph/qsgdefaultinternalimagenode.cpp
index 1d54628acd..a5a6da06a7 100644
--- a/src/quick/scenegraph/qsgdefaultinternalimagenode.cpp
+++ b/src/quick/scenegraph/qsgdefaultinternalimagenode.cpp
@@ -50,11 +50,11 @@ class SmoothTextureMaterialShader : public QSGTextureMaterialShader
public:
SmoothTextureMaterialShader();
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
- virtual char const *const *attributeNames() const;
+ void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
+ char const *const *attributeNames() const override;
protected:
- virtual void initialize();
+ void initialize() override;
int m_pixelSizeLoc;
};
diff --git a/src/quick/scenegraph/qsgdefaultinternalrectanglenode.cpp b/src/quick/scenegraph/qsgdefaultinternalrectanglenode.cpp
index 94414444ba..e52dcaad52 100644
--- a/src/quick/scenegraph/qsgdefaultinternalrectanglenode.cpp
+++ b/src/quick/scenegraph/qsgdefaultinternalrectanglenode.cpp
@@ -55,11 +55,11 @@ class SmoothColorMaterialShader : public QSGMaterialShader
public:
SmoothColorMaterialShader();
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
- virtual char const *const *attributeNames() const;
+ void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
+ char const *const *attributeNames() const override;
private:
- virtual void initialize();
+ void initialize() override;
int m_matrixLoc;
int m_opacityLoc;
diff --git a/src/quick/scenegraph/qsgdefaultlayer.cpp b/src/quick/scenegraph/qsgdefaultlayer.cpp
index 2897f53e32..86d74acf54 100644
--- a/src/quick/scenegraph/qsgdefaultlayer.cpp
+++ b/src/quick/scenegraph/qsgdefaultlayer.cpp
@@ -100,6 +100,7 @@ QSGDefaultLayer::QSGDefaultLayer(QSGRenderContext *context)
#ifdef QSG_DEBUG_FBO_OVERLAY
, m_debugOverlay(0)
#endif
+ , m_samples(0)
, m_mipmap(false)
, m_live(true)
, m_recursive(false)
@@ -314,11 +315,20 @@ void QSGDefaultLayer::grab()
QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
bool deleteFboLater = false;
- if (!m_fbo || m_fbo->size() != m_size || m_fbo->format().internalTextureFormat() != m_format
- || (!m_fbo->format().mipmap() && m_mipmap))
- {
+
+ int effectiveSamples = m_samples;
+ // By default m_samples is 0. Fall back to the context's setting in this case.
+ if (effectiveSamples == 0)
+ effectiveSamples = m_context->openglContext()->format().samples();
+
+ const bool needsNewFbo = !m_fbo || m_fbo->size() != m_size || m_fbo->format().internalTextureFormat() != m_format;
+ const bool mipmapGotEnabled = m_fbo && !m_fbo->format().mipmap() && m_mipmap;
+ const bool msaaGotEnabled = effectiveSamples > 1 && (!m_secondaryFbo || m_secondaryFbo->format().samples() != effectiveSamples);
+ const bool msaaGotDisabled = effectiveSamples <= 1 && m_secondaryFbo;
+
+ if (needsNewFbo || mipmapGotEnabled || msaaGotEnabled || msaaGotDisabled) {
if (!m_multisamplingChecked) {
- if (m_context->openglContext()->format().samples() <= 1) {
+ if (effectiveSamples <= 1) {
m_multisampling = false;
} else {
QOpenGLExtensions *e = static_cast<QOpenGLExtensions *>(funcs);
@@ -334,7 +344,7 @@ void QSGDefaultLayer::grab()
QOpenGLFramebufferObjectFormat format;
format.setInternalTextureFormat(m_format);
- format.setSamples(m_context->openglContext()->format().samples());
+ format.setSamples(effectiveSamples);
m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_secondaryFbo);
} else {
diff --git a/src/quick/scenegraph/qsgdefaultlayer_p.h b/src/quick/scenegraph/qsgdefaultlayer_p.h
index ae39994096..7b09293095 100644
--- a/src/quick/scenegraph/qsgdefaultlayer_p.h
+++ b/src/quick/scenegraph/qsgdefaultlayer_p.h
@@ -113,6 +113,9 @@ public:
QRectF normalizedTextureSubRect() const Q_DECL_OVERRIDE;
+ int samples() const { return m_samples; }
+ void setSamples(int samples) Q_DECL_OVERRIDE { m_samples = samples; }
+
public Q_SLOTS:
void markDirtyTexture() Q_DECL_OVERRIDE;
void invalidated() Q_DECL_OVERRIDE;
@@ -138,6 +141,7 @@ private:
#endif
QSGDefaultRenderContext *m_context;
+ int m_samples;
uint m_mipmap : 1;
uint m_live : 1;
diff --git a/src/quick/scenegraph/qsgdefaultrendercontext.cpp b/src/quick/scenegraph/qsgdefaultrendercontext.cpp
index b343f89cc0..95f3555994 100644
--- a/src/quick/scenegraph/qsgdefaultrendercontext.cpp
+++ b/src/quick/scenegraph/qsgdefaultrendercontext.cpp
@@ -45,7 +45,6 @@
#include <QtQuick/private/qsgrenderer_p.h>
#include <QtQuick/private/qsgatlastexture_p.h>
#include <QtQuick/private/qsgdefaultdistancefieldglyphcache_p.h>
-#include <QtQuick/private/qsgdistancefieldutil_p.h>
QT_BEGIN_NAMESPACE
@@ -159,8 +158,8 @@ void QSGDefaultRenderContext::invalidate()
delete m_depthStencilManager;
m_depthStencilManager = 0;
- delete m_distanceFieldCacheManager;
- m_distanceFieldCacheManager = 0;
+ qDeleteAll(m_glyphCaches);
+ m_glyphCaches.clear();
if (m_gl->property(QSG_RENDERCONTEXT_PROPERTY) == QVariant::fromValue(this))
m_gl->setProperty(QSG_RENDERCONTEXT_PROPERTY, QVariant());
@@ -260,7 +259,7 @@ void QSGDefaultRenderContext::compileShader(QSGMaterialShader *shader, QSGMateri
if (vertexCode || fragmentCode) {
Q_ASSERT_X((material->flags() & QSGMaterial::CustomCompileStep) == 0,
"QSGRenderContext::compile()",
- "materials with custom compile step cannot have custom vertex/fragment code");
+ "materials with custom compile step cannot have modified vertex or fragment code");
QOpenGLShaderProgram *p = shader->program();
p->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexCode ? vertexCode : shader->vertexShader());
p->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragmentCode ? fragmentCode : shader->fragmentShader());
@@ -272,6 +271,26 @@ void QSGDefaultRenderContext::compileShader(QSGMaterialShader *shader, QSGMateri
}
}
+QString QSGDefaultRenderContext::fontKey(const QRawFont &font)
+{
+ QFontEngine *fe = QRawFontPrivate::get(font)->fontEngine;
+ if (!fe->faceId().filename.isEmpty()) {
+ QByteArray keyName = fe->faceId().filename;
+ if (font.style() != QFont::StyleNormal)
+ keyName += QByteArray(" I");
+ if (font.weight() != QFont::Normal)
+ keyName += ' ' + QByteArray::number(font.weight());
+ keyName += QByteArray(" DF");
+ return QString::fromUtf8(keyName);
+ } else {
+ return QString::fromLatin1("%1_%2_%3_%4")
+ .arg(font.familyName())
+ .arg(font.styleName())
+ .arg(font.weight())
+ .arg(font.style());
+ }
+}
+
void QSGDefaultRenderContext::initializeShader(QSGMaterialShader *shader)
{
shader->program()->bind();
@@ -291,13 +310,11 @@ QSGDefaultRenderContext *QSGDefaultRenderContext::from(QOpenGLContext *context)
QSGDistanceFieldGlyphCache *QSGDefaultRenderContext::distanceFieldGlyphCache(const QRawFont &font)
{
- if (!m_distanceFieldCacheManager)
- m_distanceFieldCacheManager = new QSGDistanceFieldGlyphCacheManager;
-
- QSGDistanceFieldGlyphCache *cache = m_distanceFieldCacheManager->cache(font);
+ QString key = fontKey(font);
+ QSGDistanceFieldGlyphCache *cache = m_glyphCaches.value(key, 0);
if (!cache) {
- cache = new QSGDefaultDistanceFieldGlyphCache(m_distanceFieldCacheManager, openglContext(), font);
- m_distanceFieldCacheManager->insertCache(font, cache);
+ cache = new QSGDefaultDistanceFieldGlyphCache(openglContext(), font);
+ m_glyphCaches.insert(key, cache);
}
return cache;
diff --git a/src/quick/scenegraph/qsgdefaultrendercontext_p.h b/src/quick/scenegraph/qsgdefaultrendercontext_p.h
index 0aed46b658..2537a06988 100644
--- a/src/quick/scenegraph/qsgdefaultrendercontext_p.h
+++ b/src/quick/scenegraph/qsgdefaultrendercontext_p.h
@@ -96,6 +96,8 @@ public:
int maxTextureSize() const override { return m_maxTextureSize; }
protected:
+ static QString fontKey(const QRawFont &font);
+
QOpenGLContext *m_gl;
QSGDepthStencilBufferManager *m_depthStencilManager;
int m_maxTextureSize;
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
index 456a197ba1..32eda2d142 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
@@ -39,7 +39,6 @@
#include "qsgdistancefieldglyphnode_p.h"
#include "qsgdistancefieldglyphnode_p_p.h"
-#include <QtQuick/private/qsgdistancefieldutil_p.h>
#include <QtQuick/private/qsgcontext_p.h>
QT_BEGIN_NAMESPACE
@@ -76,9 +75,6 @@ QSGDistanceFieldGlyphNode::~QSGDistanceFieldGlyphNode()
m_glyph_cache->unregisterGlyphNode(this);
m_glyph_cache->unregisterOwnerElement(ownerElement());
}
-
- while (m_nodesToDelete.count())
- delete m_nodesToDelete.takeLast();
}
void QSGDistanceFieldGlyphNode::setColor(const QColor &color)
@@ -158,9 +154,6 @@ void QSGDistanceFieldGlyphNode::preprocess()
{
Q_ASSERT(m_glyph_cache);
- while (m_nodesToDelete.count())
- delete m_nodesToDelete.takeLast();
-
m_glyph_cache->processPendingGlyphs();
m_glyph_cache->update();
@@ -188,13 +181,12 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
// Remove previously created sub glyph nodes
// We assume all the children are sub glyph nodes
QSGNode *subnode = firstChild();
+ QSGNode *nextNode = 0;
while (subnode) {
- // We can't delete the node now as it might be in the preprocess list
- // It will be deleted in the next preprocess
- m_nodesToDelete.append(subnode);
- subnode = subnode->nextSibling();
+ nextNode = subnode->nextSibling();
+ delete subnode;
+ subnode = nextNode;
}
- removeAllChildNodes();
QSGGeometry *g = geometry();
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
index ca91e5d85f..a67c659c99 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include "qsgdistancefieldglyphnode_p_p.h"
-#include <QtQuick/private/qsgdistancefieldutil_p.h>
#include <QtQuick/private/qsgtexture_p.h>
#include <QtGui/qopenglfunctions.h>
#include <QtGui/qsurface.h>
@@ -52,13 +51,13 @@ class QSGDistanceFieldTextMaterialShader : public QSGMaterialShader
public:
QSGDistanceFieldTextMaterialShader();
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
- virtual char const *const *attributeNames() const;
+ void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
+ char const *const *attributeNames() const override;
protected:
- virtual void initialize();
+ void initialize() override;
- void updateAlphaRange(ThresholdFunc thresholdFunc, AntialiasingSpreadFunc spreadFunc);
+ void updateAlphaRange();
void updateColor(const QVector4D &c);
void updateTextureScale(const QVector2D &ts);
@@ -98,7 +97,31 @@ QSGDistanceFieldTextMaterialShader::QSGDistanceFieldTextMaterialShader()
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/distancefieldtext.frag"));
}
-void QSGDistanceFieldTextMaterialShader::updateAlphaRange(ThresholdFunc thresholdFunc, AntialiasingSpreadFunc spreadFunc)
+static float qt_sg_envFloat(const char *name, float defaultValue)
+{
+ if (Q_LIKELY(!qEnvironmentVariableIsSet(name)))
+ return defaultValue;
+ bool ok = false;
+ const float value = qgetenv(name).toFloat(&ok);
+ return ok ? value : defaultValue;
+}
+
+static float thresholdFunc(float glyphScale)
+{
+ static const float base = qt_sg_envFloat("QT_DF_BASE", 0.5f);
+ static const float baseDev = qt_sg_envFloat("QT_DF_BASEDEVIATION", 0.065f);
+ static const float devScaleMin = qt_sg_envFloat("QT_DF_SCALEFORMAXDEV", 0.15f);
+ static const float devScaleMax = qt_sg_envFloat("QT_DF_SCALEFORNODEV", 0.3f);
+ return base - ((qBound(devScaleMin, glyphScale, devScaleMax) - devScaleMin) / (devScaleMax - devScaleMin) * -baseDev + baseDev);
+}
+
+static float spreadFunc(float glyphScale)
+{
+ static const float range = qt_sg_envFloat("QT_DF_RANGE", 0.06f);
+ return range / glyphScale;
+}
+
+void QSGDistanceFieldTextMaterialShader::updateAlphaRange()
{
float combinedScale = m_fontScale * m_matrixScale;
float base = thresholdFunc(combinedScale);
@@ -169,8 +192,7 @@ void QSGDistanceFieldTextMaterialShader::updateState(const RenderState &state, Q
updateRange = true;
}
if (updateRange) {
- updateAlphaRange(material->glyphCache()->manager()->thresholdFunc(),
- material->glyphCache()->manager()->antialiasingSpreadFunc());
+ updateAlphaRange();
}
Q_ASSERT(material->glyphCache());
@@ -261,10 +283,10 @@ class DistanceFieldStyledTextMaterialShader : public QSGDistanceFieldTextMateria
public:
DistanceFieldStyledTextMaterialShader();
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+ void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
protected:
- virtual void initialize();
+ void initialize() override;
int m_styleColor_id;
};
@@ -329,12 +351,12 @@ class DistanceFieldOutlineTextMaterialShader : public DistanceFieldStyledTextMat
public:
DistanceFieldOutlineTextMaterialShader();
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+ void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
protected:
- virtual void initialize();
+ void initialize() override;
- void updateOutlineAlphaRange(ThresholdFunc thresholdFunc, AntialiasingSpreadFunc spreadFunc, int dfRadius);
+ void updateOutlineAlphaRange(int dfRadius);
int m_outlineAlphaMax0_id;
int m_outlineAlphaMax1_id;
@@ -355,9 +377,7 @@ void DistanceFieldOutlineTextMaterialShader::initialize()
m_outlineAlphaMax1_id = program()->uniformLocation("outlineAlphaMax1");
}
-void DistanceFieldOutlineTextMaterialShader::updateOutlineAlphaRange(ThresholdFunc thresholdFunc,
- AntialiasingSpreadFunc spreadFunc,
- int dfRadius)
+void DistanceFieldOutlineTextMaterialShader::updateOutlineAlphaRange(int dfRadius)
{
float combinedScale = m_fontScale * m_matrixScale;
float base = thresholdFunc(combinedScale);
@@ -381,9 +401,7 @@ void DistanceFieldOutlineTextMaterialShader::updateState(const RenderState &stat
if (oldMaterial == 0
|| material->fontScale() != oldMaterial->fontScale()
|| state.isMatrixDirty())
- updateOutlineAlphaRange(material->glyphCache()->manager()->thresholdFunc(),
- material->glyphCache()->manager()->antialiasingSpreadFunc(),
- material->glyphCache()->distanceFieldRadius());
+ updateOutlineAlphaRange(material->glyphCache()->distanceFieldRadius());
}
@@ -413,10 +431,10 @@ class DistanceFieldShiftedStyleTextMaterialShader : public DistanceFieldStyledTe
public:
DistanceFieldShiftedStyleTextMaterialShader();
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+ void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
protected:
- virtual void initialize();
+ void initialize() override;
void updateShift(qreal fontScale, const QPointF& shift);
@@ -492,10 +510,10 @@ class QSGHiQSubPixelDistanceFieldTextMaterialShader : public QSGDistanceFieldTex
public:
QSGHiQSubPixelDistanceFieldTextMaterialShader();
- virtual void initialize();
- virtual void activate();
- virtual void deactivate();
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+ void initialize() override;
+ void activate() override;
+ void deactivate() override;
+ void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
private:
int m_fontScale_id;
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
index c0c6bda718..7008f20925 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
@@ -59,7 +59,6 @@
QT_BEGIN_NAMESPACE
class QSGRenderContext;
-class QSGDistanceFieldGlyphCacheManager;
class QSGDistanceFieldTextMaterial;
class QSGDistanceFieldGlyphNode: public QSGGlyphNode, public QSGDistanceFieldGlyphConsumer
{
@@ -107,7 +106,6 @@ private:
AntialiasingMode m_antialiasingMode;
QRectF m_boundingRect;
const QSGDistanceFieldGlyphCache::Texture *m_texture;
- QLinkedList<QSGNode *> m_nodesToDelete;
struct GlyphInfo {
QVector<quint32> indexes;
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index bc65dc1bc3..4a69b770ed 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -139,25 +139,25 @@ public:
QSGGuiThreadRenderLoop();
~QSGGuiThreadRenderLoop();
- void show(QQuickWindow *window);
- void hide(QQuickWindow *window);
+ void show(QQuickWindow *window) override;
+ void hide(QQuickWindow *window) override;
- void windowDestroyed(QQuickWindow *window);
+ void windowDestroyed(QQuickWindow *window) override;
void renderWindow(QQuickWindow *window);
- void exposureChanged(QQuickWindow *window);
- QImage grab(QQuickWindow *window);
+ void exposureChanged(QQuickWindow *window) override;
+ QImage grab(QQuickWindow *window) override;
- void maybeUpdate(QQuickWindow *window);
- void update(QQuickWindow *window) { maybeUpdate(window); } // identical for this implementation.
- void handleUpdateRequest(QQuickWindow *);
+ void maybeUpdate(QQuickWindow *window) override;
+ void update(QQuickWindow *window) override { maybeUpdate(window); } // identical for this implementation.
+ void handleUpdateRequest(QQuickWindow *) override;
- void releaseResources(QQuickWindow *) { }
+ void releaseResources(QQuickWindow *) override { }
- QAnimationDriver *animationDriver() const { return 0; }
+ QAnimationDriver *animationDriver() const override { return 0; }
- QSGContext *sceneGraphContext() const;
- QSGRenderContext *createRenderContext(QSGContext *) const { return rc; }
+ QSGContext *sceneGraphContext() const override;
+ QSGRenderContext *createRenderContext(QSGContext *) const override { return rc; }
struct WindowData {
bool updatePending : 1;
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index 3a8e673c0d..1e5e61e43b 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -295,8 +295,8 @@ public:
void invalidateOpenGL(QQuickWindow *window, bool inDestructor, QOffscreenSurface *backupSurface);
void initializeOpenGL();
- bool event(QEvent *);
- void run();
+ bool event(QEvent *) override;
+ void run() override;
void syncAndRender();
void sync(bool inExpose);
diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri
index 38c3b8dd85..c6db3df158 100644
--- a/src/quick/scenegraph/scenegraph.pri
+++ b/src/quick/scenegraph/scenegraph.pri
@@ -45,7 +45,6 @@ HEADERS += \
$$PWD/util/qsgtexture.h \
$$PWD/util/qsgtexture_p.h \
$$PWD/util/qsgtextureprovider.h \
- $$PWD/util/qsgdistancefieldutil_p.h \
$$PWD/util/qsgflatcolormaterial.h \
$$PWD/util/qsgsimplematerial.h \
$$PWD/util/qsgtexturematerial.h \
@@ -62,7 +61,6 @@ SOURCES += \
$$PWD/util/qsgsimpletexturenode.cpp \
$$PWD/util/qsgtexture.cpp \
$$PWD/util/qsgtextureprovider.cpp \
- $$PWD/util/qsgdistancefieldutil.cpp \
$$PWD/util/qsgflatcolormaterial.cpp \
$$PWD/util/qsgsimplematerial.cpp \
$$PWD/util/qsgtexturematerial.cpp \
diff --git a/src/quick/scenegraph/util/qsgdistancefieldutil.cpp b/src/quick/scenegraph/util/qsgdistancefieldutil.cpp
deleted file mode 100644
index 84df7f3393..0000000000
--- a/src/quick/scenegraph/util/qsgdistancefieldutil.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQuick module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsgdistancefieldutil_p.h"
-
-#include <private/qsgadaptationlayer_p.h>
-#if QT_CONFIG(opengl)
-# include <QtGui/private/qopenglengineshadersource_p.h>
-#endif
-#include <QtQuick/private/qsgcontext_p.h>
-
-QT_BEGIN_NAMESPACE
-
-static float qt_sg_envFloat(const char *name, float defaultValue)
-{
- if (Q_LIKELY(!qEnvironmentVariableIsSet(name)))
- return defaultValue;
- bool ok = false;
- const float value = qgetenv(name).toFloat(&ok);
- return ok ? value : defaultValue;
-}
-
-static float defaultThresholdFunc(float glyphScale)
-{
- static const float base = qt_sg_envFloat("QT_DF_BASE", 0.5f);
- static const float baseDev = qt_sg_envFloat("QT_DF_BASEDEVIATION", 0.065f);
- static const float devScaleMin = qt_sg_envFloat("QT_DF_SCALEFORMAXDEV", 0.15f);
- static const float devScaleMax = qt_sg_envFloat("QT_DF_SCALEFORNODEV", 0.3f);
- return base - ((qBound(devScaleMin, glyphScale, devScaleMax) - devScaleMin) / (devScaleMax - devScaleMin) * -baseDev + baseDev);
-}
-
-static float defaultAntialiasingSpreadFunc(float glyphScale)
-{
- static const float range = qt_sg_envFloat("QT_DF_RANGE", 0.06f);
- return range / glyphScale;
-}
-
-QSGDistanceFieldGlyphCacheManager::QSGDistanceFieldGlyphCacheManager()
- : m_threshold_func(defaultThresholdFunc)
- , m_antialiasingSpread_func(defaultAntialiasingSpreadFunc)
-{
-}
-
-QSGDistanceFieldGlyphCacheManager::~QSGDistanceFieldGlyphCacheManager()
-{
- qDeleteAll(m_caches);
-}
-
-QSGDistanceFieldGlyphCache *QSGDistanceFieldGlyphCacheManager::cache(const QRawFont &font)
-{
- return m_caches.value(fontKey(font), 0);
-}
-
-void QSGDistanceFieldGlyphCacheManager::insertCache(const QRawFont &font, QSGDistanceFieldGlyphCache *cache)
-{
- m_caches.insert(fontKey(font), cache);
-}
-
-QString QSGDistanceFieldGlyphCacheManager::fontKey(const QRawFont &font)
-{
- QFontEngine *fe = QRawFontPrivate::get(font)->fontEngine;
- if (!fe->faceId().filename.isEmpty()) {
- QByteArray keyName = fe->faceId().filename;
- if (font.style() != QFont::StyleNormal)
- keyName += QByteArray(" I");
- if (font.weight() != QFont::Normal)
- keyName += ' ' + QByteArray::number(font.weight());
- keyName += QByteArray(" DF");
- return QString::fromUtf8(keyName);
- } else {
- return QString::fromLatin1("%1_%2_%3_%4")
- .arg(font.familyName())
- .arg(font.styleName())
- .arg(font.weight())
- .arg(font.style());
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgflatcolormaterial.cpp b/src/quick/scenegraph/util/qsgflatcolormaterial.cpp
index 8ab7669891..a0c71b5340 100644
--- a/src/quick/scenegraph/util/qsgflatcolormaterial.cpp
+++ b/src/quick/scenegraph/util/qsgflatcolormaterial.cpp
@@ -50,13 +50,13 @@ class FlatColorMaterialShader : public QSGMaterialShader
public:
FlatColorMaterialShader();
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
- virtual char const *const *attributeNames() const;
+ void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
+ char const *const *attributeNames() const override;
static QSGMaterialType type;
private:
- virtual void initialize();
+ void initialize() override;
#if QT_CONFIG(opengl)
int m_matrix_id;
int m_color_id;
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
index 4abee3d568..4f11d95e70 100644
--- a/src/quick/scenegraph/util/qsgtexture.cpp
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -256,11 +256,15 @@ static void qt_debug_remove_texture(QSGTexture* texture)
Specifies how the texture should treat texture coordinates.
- \value Repeat Only the factional part of the texture coordiante is
+ \value Repeat Only the fractional part of the texture coordinate is
used, causing values above 1 and below 0 to repeat.
\value ClampToEdge Values above 1 are clamped to 1 and values
below 0 are clamped to 0.
+
+ \value MirroredRepeat When the texture coordinate is even, only the
+ fractional part is used. When odd, the texture coordinate is set to
+ \c{1 - fractional part}. This value has been introduced in Qt 5.10.
*/
/*!
@@ -605,7 +609,9 @@ void QSGTexture::updateBindOptions(bool force)
if (force || d->wrapChanged) {
#ifndef QT_NO_DEBUG
- if (d->horizontalWrap == Repeat || d->verticalWrap == Repeat) {
+ if (d->horizontalWrap == Repeat || d->verticalWrap == Repeat
+ || d->horizontalWrap == MirroredRepeat || d->verticalWrap == MirroredRepeat)
+ {
bool npotSupported = QOpenGLFunctions(QOpenGLContext::currentContext()).hasOpenGLFeature(QOpenGLFunctions::NPOTTextures);
QSize size = textureSize();
bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height());
@@ -613,8 +619,18 @@ void QSGTexture::updateBindOptions(bool force)
qWarning("Scene Graph: This system does not support the REPEAT wrap mode for non-power-of-two textures.");
}
#endif
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, d->horizontalWrap == Repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, d->verticalWrap == Repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
+ GLenum wrapS = GL_CLAMP_TO_EDGE;
+ if (d->horizontalWrap == Repeat)
+ wrapS = GL_REPEAT;
+ else if (d->horizontalWrap == MirroredRepeat)
+ wrapS = GL_MIRRORED_REPEAT;
+ GLenum wrapT = GL_CLAMP_TO_EDGE;
+ if (d->verticalWrap == Repeat)
+ wrapT = GL_REPEAT;
+ else if (d->verticalWrap == MirroredRepeat)
+ wrapT = GL_MIRRORED_REPEAT;
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
d->wrapChanged = false;
}
#else
diff --git a/src/quick/scenegraph/util/qsgtexture.h b/src/quick/scenegraph/util/qsgtexture.h
index 035acc02b1..032129434e 100644
--- a/src/quick/scenegraph/util/qsgtexture.h
+++ b/src/quick/scenegraph/util/qsgtexture.h
@@ -58,7 +58,8 @@ public:
enum WrapMode {
Repeat,
- ClampToEdge
+ ClampToEdge,
+ MirroredRepeat
};
enum Filtering {
diff --git a/src/quick/scenegraph/util/qsgtexture_p.h b/src/quick/scenegraph/util/qsgtexture_p.h
index 36f9b802ba..52dc6db2d0 100644
--- a/src/quick/scenegraph/util/qsgtexture_p.h
+++ b/src/quick/scenegraph/util/qsgtexture_p.h
@@ -71,8 +71,8 @@ public:
uint filteringChanged : 1;
uint anisotropyChanged : 1;
- uint horizontalWrap : 1;
- uint verticalWrap : 1;
+ uint horizontalWrap : 2;
+ uint verticalWrap : 2;
uint mipmapMode : 2;
uint filterMode : 2;
uint anisotropyLevel: 3;
diff --git a/src/quick/scenegraph/util/qsgtexturematerial.cpp b/src/quick/scenegraph/util/qsgtexturematerial.cpp
index c536445e82..fbc8f27a63 100644
--- a/src/quick/scenegraph/util/qsgtexturematerial.cpp
+++ b/src/quick/scenegraph/util/qsgtexturematerial.cpp
@@ -280,7 +280,7 @@ void QSGOpaqueTextureMaterial::setTexture(QSGTexture *texture)
Returns this material's horizontal wrap mode.
- The default horizontal wrap mode is \c QSGTexutre::ClampToEdge.
+ The default horizontal wrap mode is \c QSGTexture::ClampToEdge.
*/
@@ -301,7 +301,7 @@ void QSGOpaqueTextureMaterial::setTexture(QSGTexture *texture)
Returns this material's vertical wrap mode.
- The default vertical wrap mode is \c QSGTexutre::ClampToEdge.
+ The default vertical wrap mode is \c QSGTexture::ClampToEdge.
*/
diff --git a/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp b/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp
index 8c305d7fd4..42c589b14a 100644
--- a/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp
+++ b/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp
@@ -48,13 +48,13 @@ class QSGVertexColorMaterialShader : public QSGMaterialShader
public:
QSGVertexColorMaterialShader();
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
- virtual char const *const *attributeNames() const;
+ void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
+ char const *const *attributeNames() const override;
static QSGMaterialType type;
private:
- virtual void initialize();
+ void initialize() override;
#if QT_CONFIG(opengl)
int m_matrix_id;
int m_opacity_id;
diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp
index 3ac02cd259..a7950e2b33 100644
--- a/src/quick/util/qquickanimatorjob.cpp
+++ b/src/quick/util/qquickanimatorjob.cpp
@@ -321,8 +321,10 @@ void QQuickTransformAnimatorJob::preSync()
m_helper = nullptr;
}
- if (!m_target)
+ if (!m_target) {
+ invalidate();
return;
+ }
if (!m_helper) {
m_helper = qquick_transform_animatorjob_helper_store()->acquire(m_target);
@@ -342,27 +344,6 @@ void QQuickTransformAnimatorJob::preSync()
m_helper->sync();
}
-void QQuickTransformAnimatorJob::postSync()
-{
- Q_ASSERT((m_helper != nullptr) == (m_target != nullptr)); // If there is a target, there should also be a helper, ref: preSync
- Q_ASSERT(!m_helper || m_helper->item == m_target); // If there is a helper, it should point to our target
-
- if (!m_target || !m_helper) {
- invalidate();
- return;
- }
-
- QQuickItemPrivate *d = QQuickItemPrivate::get(m_target);
-#if QT_CONFIG(quick_shadereffect)
- if (d->extra.isAllocated()
- && d->extra->layer
- && d->extra->layer->enabled()) {
- d = QQuickItemPrivate::get(d->extra->layer->m_effectSource);
- }
-#endif
- m_helper->node = d->itemNode();
-}
-
void QQuickTransformAnimatorJob::invalidate()
{
if (m_helper)
diff --git a/src/quick/util/qquickanimatorjob_p.h b/src/quick/util/qquickanimatorjob_p.h
index a3ced4c21b..777da2ee6c 100644
--- a/src/quick/util/qquickanimatorjob_p.h
+++ b/src/quick/util/qquickanimatorjob_p.h
@@ -235,7 +235,6 @@ public:
protected:
QQuickTransformAnimatorJob();
- void postSync() override;
void invalidate() override;
Helper *m_helper;
diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp
index 5ba849c57f..6df23cdff5 100644
--- a/src/quick/util/qquickglobal.cpp
+++ b/src/quick/util/qquickglobal.cpp
@@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE
class QQuickColorProvider : public QQmlColorProvider
{
public:
- QVariant colorFromString(const QString &s, bool *ok)
+ QVariant colorFromString(const QString &s, bool *ok) override
{
QColor c(s);
if (c.isValid()) {
@@ -73,7 +73,7 @@ public:
return QVariant();
}
- unsigned rgbaFromString(const QString &s, bool *ok)
+ unsigned rgbaFromString(const QString &s, bool *ok) override
{
QColor c(s);
if (c.isValid()) {
@@ -95,36 +95,36 @@ public:
return QString();
}
- QVariant fromRgbF(double r, double g, double b, double a)
+ QVariant fromRgbF(double r, double g, double b, double a) override
{
return QVariant(QColor::fromRgbF(r, g, b, a));
}
- QVariant fromHslF(double h, double s, double l, double a)
+ QVariant fromHslF(double h, double s, double l, double a) override
{
return QVariant(QColor::fromHslF(h, s, l, a));
}
- QVariant fromHsvF(double h, double s, double v, double a)
+ QVariant fromHsvF(double h, double s, double v, double a) override
{
return QVariant(QColor::fromHsvF(h, s, v, a));
}
- QVariant lighter(const QVariant &var, qreal factor)
+ QVariant lighter(const QVariant &var, qreal factor) override
{
QColor color = var.value<QColor>();
color = color.lighter(int(qRound(factor*100.)));
return QVariant::fromValue(color);
}
- QVariant darker(const QVariant &var, qreal factor)
+ QVariant darker(const QVariant &var, qreal factor) override
{
QColor color = var.value<QColor>();
color = color.darker(int(qRound(factor*100.)));
return QVariant::fromValue(color);
}
- QVariant tint(const QVariant &baseVar, const QVariant &tintVar)
+ QVariant tint(const QVariant &baseVar, const QVariant &tintVar) override
{
QColor tintColor = tintVar.value<QColor>();
@@ -302,6 +302,7 @@ public:
QV4::ScopedValue vweight(scope, obj->get((s = v4->newString(QStringLiteral("weight")))));
QV4::ScopedValue vwspac(scope, obj->get((s = v4->newString(QStringLiteral("wordSpacing")))));
QV4::ScopedValue vhint(scope, obj->get((s = v4->newString(QStringLiteral("hintingPreference")))));
+ QV4::ScopedValue vkerning(scope, obj->get((s = v4->newString(QStringLiteral("kerning")))));
// pull out the values, set ok to true if at least one valid field is given.
if (vbold->isBoolean()) {
@@ -356,6 +357,10 @@ public:
retn.setHintingPreference(static_cast<QFont::HintingPreference>(vhint->integerValue()));
if (ok) *ok = true;
}
+ if (vkerning->isBoolean()) {
+ retn.setKerning(vkerning->booleanValue());
+ if (ok) *ok = true;
+ }
return retn;
}
@@ -778,13 +783,13 @@ public:
class QQuickGuiProvider : public QQmlGuiProvider
{
public:
- QQuickApplication *application(QObject *parent)
+ QQuickApplication *application(QObject *parent) override
{
return new QQuickApplication(parent);
}
#if QT_CONFIG(im)
- QInputMethod *inputMethod()
+ QInputMethod *inputMethod() override
{
QInputMethod *im = qGuiApp->inputMethod();
QQmlEngine::setObjectOwnership(im, QQmlEngine::CppOwnership);
@@ -792,20 +797,20 @@ public:
}
#endif
- QStyleHints *styleHints()
+ QStyleHints *styleHints() override
{
QStyleHints *sh = qGuiApp->styleHints();
QQmlEngine::setObjectOwnership(sh, QQmlEngine::CppOwnership);
return sh;
}
- QStringList fontFamilies()
+ QStringList fontFamilies() override
{
QFontDatabase database;
return database.families();
}
- bool openUrlExternally(QUrl &url)
+ bool openUrlExternally(QUrl &url) override
{
#ifndef QT_NO_DESKTOPSERVICES
return QDesktopServices::openUrl(url);
@@ -814,6 +819,11 @@ public:
return false;
#endif
}
+
+ QString pluginName() const override
+ {
+ return QGuiApplication::platformName();
+ }
};
diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp
index c80025f968..b4a6b9e1f6 100644
--- a/src/quick/util/qquickimageprovider.cpp
+++ b/src/quick/util/qquickimageprovider.cpp
@@ -183,7 +183,12 @@ QString QQuickImageResponse::errorString() const
It may be reimplemented to cancel a request in the provider side, however, it is not mandatory.
- A cancelled QQuickImageResponse still needs to emit finished().
+ A cancelled QQuickImageResponse still needs to emit finished() so that the
+ engine may clean up the QQuickImageResponse.
+
+ \note finished() should not be emitted until the response is complete,
+ regardless of whether or not cancel() was called. If it is called prematurely,
+ the engine may destroy the response while it is still active, leading to a crash.
*/
void QQuickImageResponse::cancel()
{
@@ -192,7 +197,12 @@ void QQuickImageResponse::cancel()
/*!
\fn void QQuickImageResponse::finished()
- Signals that the job execution has finished (be it successfully, because an error happened or because it was cancelled).
+ Signals that the job execution has finished (be it successfully, because an
+ error happened or because it was cancelled).
+
+ \note Emission of this signal must be the final action the response performs:
+ once the signal is received, the response will subsequently be destroyed by
+ the engine.
*/
/*!
diff --git a/src/quick/util/qquickpath.cpp b/src/quick/util/qquickpath.cpp
index 8abb9377a6..15defdc01b 100644
--- a/src/quick/util/qquickpath.cpp
+++ b/src/quick/util/qquickpath.cpp
@@ -68,7 +68,7 @@ QT_BEGIN_NAMESPACE
\instantiates QQuickPath
\inqmlmodule QtQuick
\ingroup qtquick-animation-paths
- \brief Defines a path for use by \l PathView
+ \brief Defines a path for use by \l PathView and \l Shape
A Path is composed of one or more path segments - PathLine, PathQuad,
PathCubic, PathArc, PathCurve, PathSvg.
@@ -79,13 +79,85 @@ QT_BEGIN_NAMESPACE
PathAttribute allows named attributes with values to be defined
along the path.
- \sa PathView, PathAttribute, PathPercent, PathLine, PathQuad, PathCubic, PathArc, PathCurve, PathSvg
+ Path and the other types for specifying path elements are shared between
+ \l PathView and \l Shape. The following table provides an overview of the
+ applicability of the various path elements:
+
+ \table
+ \header
+ \li Element
+ \li PathView
+ \li Shape
+ \li Shape, GL_NV_path_rendering
+ \li Shape, software
+ \row
+ \li PathMove
+ \li N/A
+ \li Yes
+ \li Yes
+ \li Yes
+ \row
+ \li PathLine
+ \li Yes
+ \li Yes
+ \li Yes
+ \li Yes
+ \row
+ \li PathQuad
+ \li Yes
+ \li Yes
+ \li Yes
+ \li Yes
+ \row
+ \li PathCubic
+ \li Yes
+ \li Yes
+ \li Yes
+ \li Yes
+ \row
+ \li PathArc
+ \li Yes
+ \li Yes
+ \li Yes
+ \li Yes
+ \row
+ \li PathSvg
+ \li Yes
+ \li Yes
+ \li Yes
+ \li Yes
+ \row
+ \li PathAttribute
+ \li Yes
+ \li N/A
+ \li N/A
+ \li N/A
+ \row
+ \li PathPercent
+ \li Yes
+ \li N/A
+ \li N/A
+ \li N/A
+ \row
+ \li PathCurve
+ \li Yes
+ \li No
+ \li No
+ \li No
+ \endtable
+
+ \sa PathView, Shape, PathAttribute, PathPercent, PathLine, PathMove, PathQuad, PathCubic, PathArc, PathCurve, PathSvg
*/
QQuickPath::QQuickPath(QObject *parent)
: QObject(*(new QQuickPathPrivate), parent)
{
}
+QQuickPath::QQuickPath(QQuickPathPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
QQuickPath::~QQuickPath()
{
}
@@ -1003,7 +1075,7 @@ void QQuickPathAttribute::setValue(qreal value)
}
\endqml
- \sa Path, PathQuad, PathCubic, PathArc, PathCurve, PathSvg
+ \sa Path, PathQuad, PathCubic, PathArc, PathCurve, PathSvg, PathMove
*/
/*!
@@ -1046,6 +1118,64 @@ void QQuickPathLine::addToPath(QPainterPath &path, const QQuickPathData &data)
/****************************************************************************/
/*!
+ \qmltype PathMove
+ \instantiates QQuickPathMove
+ \inqmlmodule QtQuick
+ \ingroup qtquick-animation-paths
+ \brief Moves the Path's position
+
+ The example below creates a path consisting of two horizontal lines with
+ some empty space between them. All three segments have a width of 100:
+
+ \qml
+ Path {
+ startX: 0; startY: 100
+ PathLine { relativeX: 100; y: 100 }
+ PathMove { relativeX: 100; y: 100 }
+ PathLine { relativeX: 100; y: 100 }
+ }
+ \endqml
+
+ \note PathMove should not be used in a Path associated with a PathView. Use
+ PathLine instead. For ShapePath however it is important to distinguish
+ between the operations of drawing a straight line and moving the path
+ position without drawing anything.
+
+ \sa Path, PathQuad, PathCubic, PathArc, PathCurve, PathSvg, PathLine
+*/
+
+/*!
+ \qmlproperty real QtQuick::PathMove::x
+ \qmlproperty real QtQuick::PathMove::y
+
+ Defines the position to move to.
+
+ \sa relativeX, relativeY
+*/
+
+/*!
+ \qmlproperty real QtQuick::PathMove::relativeX
+ \qmlproperty real QtQuick::PathMove::relativeY
+
+ Defines the position to move to relative to its start.
+
+ If both a relative and absolute end position are specified for a single axis, the relative
+ position will be used.
+
+ Relative and absolute positions can be mixed, for example it is valid to set a relative x
+ and an absolute y.
+
+ \sa x, y
+*/
+
+void QQuickPathMove::addToPath(QPainterPath &path, const QQuickPathData &data)
+{
+ path.moveTo(positionForCurve(data, path.currentPosition()));
+}
+
+/****************************************************************************/
+
+/*!
\qmltype PathQuad
\instantiates QQuickPathQuad
\inqmlmodule QtQuick
@@ -1641,6 +1771,7 @@ void QQuickPathArc::setRadiusX(qreal radius)
_radiusX = radius;
emit radiusXChanged();
+ emit changed();
}
qreal QQuickPathArc::radiusY() const
@@ -1655,6 +1786,7 @@ void QQuickPathArc::setRadiusY(qreal radius)
_radiusY = radius;
emit radiusYChanged();
+ emit changed();
}
/*!
@@ -1688,6 +1820,7 @@ void QQuickPathArc::setUseLargeArc(bool largeArc)
_useLargeArc = largeArc;
emit useLargeArcChanged();
+ emit changed();
}
/*!
@@ -1719,6 +1852,43 @@ void QQuickPathArc::setDirection(ArcDirection direction)
_direction = direction;
emit directionChanged();
+ emit changed();
+}
+
+/*!
+ \qmlproperty real QtQuick::PathArc::xAxisRotation
+
+ Defines the rotation of the arc, in degrees. The default value is 0.
+
+ An arc is a section of circles or ellipses. Given the radius and the start
+ and end points, there are two ellipses that connect the points. This
+ property defines the rotation of the X axis of these ellipses.
+
+ \note The value is only useful when the x and y radius differ, meaning the
+ arc is a section of ellipses.
+
+ The following QML demonstrates how different radius values can be used to change
+ the shape of the arc:
+ \table
+ \row
+ \li \image declarative-arcrotation.png
+ \li \snippet qml/path/arcrotation.qml 0
+ \endtable
+*/
+
+qreal QQuickPathArc::xAxisRotation() const
+{
+ return _xAxisRotation;
+}
+
+void QQuickPathArc::setXAxisRotation(qreal rotation)
+{
+ if (_xAxisRotation == rotation)
+ return;
+
+ _xAxisRotation = rotation;
+ emit xAxisRotationChanged();
+ emit changed();
}
void QQuickPathArc::addToPath(QPainterPath &path, const QQuickPathData &data)
@@ -1728,7 +1898,7 @@ void QQuickPathArc::addToPath(QPainterPath &path, const QQuickPathData &data)
QQuickSvgParser::pathArc(path,
_radiusX,
_radiusY,
- 0, //xAxisRotation
+ _xAxisRotation,
_useLargeArc,
_direction == Clockwise ? 1 : 0,
endPoint.x(),
@@ -1758,6 +1928,11 @@ void QQuickPathArc::addToPath(QPainterPath &path, const QQuickPathData &data)
\endqml
\endtable
+ \note Mixing PathSvg with other type of elements is not always supported.
+ For example, when \l Shape is backed by \c{GL_NV_path_rendering}, a
+ ShapePath can contain one or more PathSvg elements, or one or more other
+ type of elements, but not both.
+
\sa Path, PathLine, PathQuad, PathCubic, PathArc, PathCurve
*/
@@ -1782,6 +1957,7 @@ void QQuickPathSvg::setPath(const QString &path)
_path = path;
emit pathChanged();
+ emit changed();
}
void QQuickPathSvg::addToPath(QPainterPath &path, const QQuickPathData &)
diff --git a/src/quick/util/qquickpath_p.h b/src/quick/util/qquickpath_p.h
index c0a96cad4f..b7fde5c272 100644
--- a/src/quick/util/qquickpath_p.h
+++ b/src/quick/util/qquickpath_p.h
@@ -159,6 +159,15 @@ public:
void addToPath(QPainterPath &path, const QQuickPathData &) override;
};
+class Q_QUICK_PRIVATE_EXPORT QQuickPathMove : public QQuickCurve
+{
+ Q_OBJECT
+public:
+ QQuickPathMove(QObject *parent=0) : QQuickCurve(parent) {}
+
+ void addToPath(QPainterPath &path, const QQuickPathData &) override;
+};
+
class Q_QUICK_PRIVATE_EXPORT QQuickPathQuad : public QQuickCurve
{
Q_OBJECT
@@ -281,10 +290,11 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathArc : public QQuickCurve
Q_PROPERTY(qreal radiusY READ radiusY WRITE setRadiusY NOTIFY radiusYChanged)
Q_PROPERTY(bool useLargeArc READ useLargeArc WRITE setUseLargeArc NOTIFY useLargeArcChanged)
Q_PROPERTY(ArcDirection direction READ direction WRITE setDirection NOTIFY directionChanged)
+ Q_PROPERTY(qreal xAxisRotation READ xAxisRotation WRITE setXAxisRotation NOTIFY xAxisRotationChanged REVISION 2)
public:
QQuickPathArc(QObject *parent=0)
- : QQuickCurve(parent), _radiusX(0), _radiusY(0), _useLargeArc(false), _direction(Clockwise) {}
+ : QQuickCurve(parent), _radiusX(0), _radiusY(0), _useLargeArc(false), _direction(Clockwise), _xAxisRotation(0) {}
enum ArcDirection { Clockwise, Counterclockwise };
Q_ENUM(ArcDirection)
@@ -301,6 +311,9 @@ public:
ArcDirection direction() const;
void setDirection(ArcDirection direction);
+ qreal xAxisRotation() const;
+ void setXAxisRotation(qreal rotation);
+
void addToPath(QPainterPath &path, const QQuickPathData &) override;
Q_SIGNALS:
@@ -308,12 +321,14 @@ Q_SIGNALS:
void radiusYChanged();
void useLargeArcChanged();
void directionChanged();
+ Q_REVISION(2) void xAxisRotationChanged();
private:
qreal _radiusX;
qreal _radiusY;
bool _useLargeArc;
ArcDirection _direction;
+ qreal _xAxisRotation;
};
class Q_QUICK_PRIVATE_EXPORT QQuickPathSvg : public QQuickCurve
@@ -404,6 +419,7 @@ Q_SIGNALS:
void startYChanged();
protected:
+ QQuickPath(QQuickPathPrivate &dd, QObject *parent = nullptr);
void componentComplete() override;
void classBegin() override;
void disconnectPathElements();
@@ -458,6 +474,7 @@ QML_DECLARE_TYPE(QQuickPathElement)
QML_DECLARE_TYPE(QQuickPathAttribute)
QML_DECLARE_TYPE(QQuickCurve)
QML_DECLARE_TYPE(QQuickPathLine)
+QML_DECLARE_TYPE(QQuickPathMove)
QML_DECLARE_TYPE(QQuickPathQuad)
QML_DECLARE_TYPE(QQuickPathCubic)
QML_DECLARE_TYPE(QQuickPathCatmullRomCurve)
diff --git a/src/quick/util/qquickpath_p_p.h b/src/quick/util/qquickpath_p_p.h
index 1dc3c1c47a..8ce85dbf0f 100644
--- a/src/quick/util/qquickpath_p_p.h
+++ b/src/quick/util/qquickpath_p_p.h
@@ -64,7 +64,7 @@ QT_REQUIRE_CONFIG(quick_path);
QT_BEGIN_NAMESPACE
-class QQuickPathPrivate : public QObjectPrivate
+class Q_QUICK_PRIVATE_EXPORT QQuickPathPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QQuickPath)
diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp
index 882482ad31..e026608150 100644
--- a/src/quick/util/qquickpixmapcache.cpp
+++ b/src/quick/util/qquickpixmapcache.cpp
@@ -162,7 +162,7 @@ Q_SIGNALS:
void downloadProgress(qint64, qint64);
protected:
- bool event(QEvent *event);
+ bool event(QEvent *event) override;
private:
Q_DISABLE_COPY(QQuickPixmapReply)
@@ -200,7 +200,7 @@ public:
static QQuickPixmapReader *existingInstance(QQmlEngine *engine);
protected:
- void run();
+ void run() override;
private:
friend class QQuickPixmapReaderThreadObject;
diff --git a/src/quick/util/qquicksvgparser.cpp b/src/quick/util/qquicksvgparser.cpp
index 310b600965..086c6d0b28 100644
--- a/src/quick/util/qquicksvgparser.cpp
+++ b/src/quick/util/qquicksvgparser.cpp
@@ -45,8 +45,6 @@
QT_BEGIN_NAMESPACE
-static const double Q_PI = 3.14159265358979323846; // pi
-
//copied from Qt SVG (qsvghandler.cpp).
Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
// '0' is 0x30 and '9' is 0x39
@@ -253,11 +251,11 @@ void QQuickSvgParser::pathArc(QPainterPath &path,
th_arc = th1 - th0;
if (th_arc < 0 && sweep_flag)
- th_arc += 2 * Q_PI;
+ th_arc += 2 * M_PI;
else if (th_arc > 0 && !sweep_flag)
- th_arc -= 2 * Q_PI;
+ th_arc -= 2 * M_PI;
- n_segs = qCeil(qAbs(th_arc / (Q_PI * 0.5 + 0.001)));
+ n_segs = qCeil(qAbs(th_arc / (M_PI * 0.5 + 0.001)));
for (i = 0; i < n_segs; i++) {
pathArcSegment(path, xc, yc,
diff --git a/src/quick/util/qquicksvgparser_p.h b/src/quick/util/qquicksvgparser_p.h
index 44b0d1b6dd..1777b99bf4 100644
--- a/src/quick/util/qquicksvgparser_p.h
+++ b/src/quick/util/qquicksvgparser_p.h
@@ -51,6 +51,7 @@
// We mean it.
//
+#include <private/qtquickglobal_p.h>
#include <QtCore/qstring.h>
#include <QtGui/qpainterpath.h>
@@ -59,9 +60,9 @@ QT_BEGIN_NAMESPACE
namespace QQuickSvgParser
{
bool parsePathDataFast(const QString &dataStr, QPainterPath &path);
- void pathArc(QPainterPath &path, qreal rx, qreal ry, qreal x_axis_rotation,
- int large_arc_flag, int sweep_flag, qreal x, qreal y, qreal curx,
- qreal cury);
+ Q_QUICK_PRIVATE_EXPORT void pathArc(QPainterPath &path, qreal rx, qreal ry, qreal x_axis_rotation,
+ int large_arc_flag, int sweep_flag, qreal x, qreal y, qreal curx,
+ qreal cury);
}
QT_END_NAMESPACE
diff --git a/src/quick/util/qquickvaluetypes.cpp b/src/quick/util/qquickvaluetypes.cpp
index 4d34c6d661..bc4a72b6ea 100644
--- a/src/quick/util/qquickvaluetypes.cpp
+++ b/src/quick/util/qquickvaluetypes.cpp
@@ -757,6 +757,16 @@ void QQuickFontValueType::setHintingPreference(QQuickFontValueType::HintingPrefe
v.setHintingPreference(QFont::HintingPreference(hintingPreference));
}
+bool QQuickFontValueType::kerning() const
+{
+ return v.kerning();
+}
+
+void QQuickFontValueType::setKerning(bool b)
+{
+ v.setKerning(b);
+}
+
QT_END_NAMESPACE
#include "moc_qquickvaluetypes_p.cpp"
diff --git a/src/quick/util/qquickvaluetypes_p.h b/src/quick/util/qquickvaluetypes_p.h
index 4a1598ec5c..a3f35a84ec 100644
--- a/src/quick/util/qquickvaluetypes_p.h
+++ b/src/quick/util/qquickvaluetypes_p.h
@@ -323,6 +323,7 @@ class QQuickFontValueType
Q_PROPERTY(qreal letterSpacing READ letterSpacing WRITE setLetterSpacing FINAL)
Q_PROPERTY(qreal wordSpacing READ wordSpacing WRITE setWordSpacing FINAL)
Q_PROPERTY(HintingPreference hintingPreference READ hintingPreference WRITE setHintingPreference FINAL)
+ Q_PROPERTY(bool kerning READ kerning WRITE setKerning FINAL)
public:
enum FontWeight { Thin = QFont::Thin,
@@ -393,6 +394,9 @@ public:
HintingPreference hintingPreference() const;
void setHintingPreference(HintingPreference);
+
+ bool kerning() const;
+ void setKerning(bool b);
};
QT_END_NAMESPACE
diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations
index 49f107452a..27498de473 100644
--- a/tests/auto/qml/ecmascripttests/TestExpectations
+++ b/tests/auto/qml/ecmascripttests/TestExpectations
@@ -29,3 +29,150 @@ Sbp_12.5_A9_T3 failing
Sbp_12.6.1_A13_T3 failing
Sbp_12.6.2_A13_T3 failing
Sbp_12.6.4_A13_T3 failing
+
+# es6: function length attributes are configurable, wasn't in es5
+S15.1.2.2_A9.2 failing
+S15.1.3.1_A5.2 failing
+S15.1.3.2_A5.2 failing
+S15.1.3.3_A5.2 failing
+S15.1.2.3_A7.2 failing
+S15.1.2.4_A2.2 failing
+S15.1.2.5_A2.2 failing
+S15.1.3.4_A5.2 failing
+15.2.3.3-4-186 failing
+S15.2.4.2_A9 failing
+S15.2.4.3_A9 failing
+S15.2.4.4_A9 failing
+S15.2.4.5_A9 failing
+S15.2.4.6_A9 failing
+S15.2.4.7_A9 failing
+15.3.3.2-1 failing
+15.4.4.2_A4.2
+S15.3.4.2_A9 failing
+S15.3.4.3_A9 failing
+S15.3.4.4_A9 failing
+15.3.4.5-15-2 failing
+S15.4.4.2_A4.2 failing
+S15.4.4.3_A4.2 failing
+S15.4.4.4_A4.2 failing
+S15.4.4.5_A6.2 failing
+S15.4.4.6_A5.2 failing
+S15.4.4.7_A6.2 failing
+S15.4.4.8_A5.2 failing
+S15.4.4.9_A5.2 failing
+S15.4.4.10_A5.2 failing
+S15.4.4.11_A7.2 failing
+S15.4.4.12_A5.2 failing
+S15.4.4.13_A5.2 failing
+S15.5.4.10_A9 failing
+S15.5.4.11_A9 failing
+S15.5.4.12_A9 failing
+S15.5.4.13_A9 failing
+S15.5.4.14_A9 failing
+S15.5.4.15_A9 failing
+S15.5.4.16_A9 failing
+S15.5.4.17_A9 failing
+S15.5.4.18_A9 failing
+S15.5.4.19_A9 failing
+S15.5.4.4_A9 failing
+S15.5.4.5_A9 failing
+S15.5.4.6_A9 failing
+S15.5.4.7_A9 failing
+S15.5.4.8_A9 failing
+S15.5.4.9_A9 failing
+S15.9.4.2_A3_T2 failing
+S15.9.4.3_A3_T2 failing
+S15.9.5.2_A3_T2 failing
+S15.9.5.3_A3_T2 failing
+S15.9.5.4_A3_T2 failing
+S15.9.5.5_A3_T2 failing
+S15.9.5.1_A3_T2 failing
+S15.9.5.10_A3_T2 failing
+S15.9.5.11_A3_T2 failing
+S15.9.5.12_A3_T2 failing
+S15.9.5.13_A3_T2 failing
+S15.9.5.14_A3_T2 failing
+S15.9.5.15_A3_T2 failing
+S15.9.5.16_A3_T2 failing
+S15.9.5.17_A3_T2 failing
+S15.9.5.18_A3_T2 failing
+S15.9.5.19_A3_T2 failing
+S15.9.5.20_A3_T2 failing
+S15.9.5.21_A3_T2 failing
+S15.9.5.22_A3_T2 failing
+S15.9.5.23_A3_T2 failing
+S15.9.5.24_A3_T2 failing
+S15.9.5.25_A3_T2 failing
+S15.9.5.26_A3_T2 failing
+S15.9.5.27_A3_T2 failing
+S15.9.5.28_A3_T2 failing
+S15.9.5.29_A3_T2 failing
+S15.9.5.30_A3_T2 failing
+S15.9.5.31_A3_T2 failing
+S15.9.5.32_A3_T2 failing
+S15.9.5.33_A3_T2 failing
+S15.9.5.34_A3_T2 failing
+S15.9.5.35_A3_T2 failing
+S15.9.5.36_A3_T2 failing
+S15.9.5.37_A3_T2 failing
+S15.9.5.38_A3_T2 failing
+S15.9.5.39_A3_T2 failing
+S15.9.5.40_A3_T2 failing
+S15.9.5.41_A3_T2 failing
+S15.9.5.42_A3_T2 failing
+S15.9.5.6_A3_T2 failing
+S15.9.5.7_A3_T2 failing
+S15.9.5.8_A3_T2 failing
+S15.9.5.9_A3_T2 failing
+S15.10.6.2_A9 failing
+S15.10.6.3_A9 failing
+S15.10.6.4_A9 failing
+
+# es6: Object.freeze(v) on a non-object returns v, no longer TypeError
+15.2.3.9-1 failing
+15.2.3.9-1-1 failing
+15.2.3.9-1-2 failing
+15.2.3.9-1-3 failing
+15.2.3.9-1-4 failing
+# es6: Object.preventExtensions(O) on a non-object, no longer TypeError
+15.2.3.10-1 failing
+15.2.3.10-1-3 failing
+15.2.3.10-1-4 failing
+# es6: Object.isSealed(O) on a non-object, no longer TypeError
+15.2.3.11-1
+# es6: Object.isFrozen(O) on a non-object, no longer TypeError
+15.2.3.12-1
+15.2.3.12-1-3
+15.2.3.12-1-4
+# es6: Object.isExtensible(O) on a non-object, no longer TypeError
+15.2.3.13-1
+15.2.3.13-1-3
+15.2.3.13-1-4
+# es6: Object.keys(O) on a non-object, no longer TypeError
+15.2.3.14-1-1
+15.2.3.14-1-2
+15.2.3.14-1-3
+15.2.3.14-1
+15.2.3.14-2
+15.2.3.14-3
+# es6: Object.getOwnPropertyDescriptor(O) on a non-object, no longer TypeError
+15.2.3.3-1
+15.2.3.3-1-3
+15.2.3.3-1-4
+# es6: Object.getPrototypeOf(O) on a non-object, no longer TypeError
+15.2.3.2-1
+15.2.3.2-1-3
+15.2.3.2-1-4
+# es6: Object.getOwnPropertyNames(O) on a non-object, no longer TypeError
+15.2.3.4-1
+15.2.3.4-1-4
+15.2.3.4-1-5
+# es6: Object.seal(O) on a non-object, no longer TypeError
+15.2.3.8-1
+15.2.3.8-1-1
+15.2.3.8-1-2
+15.2.3.8-1-3
+15.2.3.8-1-4
+
+# es6: Date.prototype is no longer a DateObject
+15.9.5.40_1 failing
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index 2642d10545..a3a2efd565 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -568,10 +568,6 @@ void tst_QJSEngine::newDate()
QCOMPARE(date.isDate(), true);
QCOMPARE(date.isObject(), true);
QVERIFY(!date.isCallable());
- // prototype should be Date.prototype
- QVERIFY(!date.prototype().isUndefined());
- QCOMPARE(date.prototype().isDate(), true);
- QCOMPARE(date.prototype().strictlyEquals(eng.evaluate("Date.prototype")), true);
}
{
@@ -580,10 +576,6 @@ void tst_QJSEngine::newDate()
QVERIFY(!date.isUndefined());
QCOMPARE(date.isDate(), true);
QCOMPARE(date.isObject(), true);
- // prototype should be Date.prototype
- QVERIFY(!date.prototype().isUndefined());
- QCOMPARE(date.prototype().isDate(), true);
- QCOMPARE(date.prototype().strictlyEquals(eng.evaluate("Date.prototype")), true);
QCOMPARE(date.toDateTime(), dt);
}
@@ -1114,7 +1106,7 @@ void tst_QJSEngine::builtinFunctionNames_data()
QTest::newRow("Date.prototype.setFullYear") << QString("Date.prototype.setFullYear") << QString("setFullYear");
QTest::newRow("Date.prototype.setUTCFullYear") << QString("Date.prototype.setUTCFullYear") << QString("setUTCFullYear");
QTest::newRow("Date.prototype.toUTCString") << QString("Date.prototype.toUTCString") << QString("toUTCString");
- QTest::newRow("Date.prototype.toGMTString") << QString("Date.prototype.toGMTString") << QString("toGMTString");
+ QTest::newRow("Date.prototype.toGMTString") << QString("Date.prototype.toGMTString") << QString("toUTCString"); // yes, this is per spec
QTest::newRow("Error") << QString("Error") << QString("Error");
// QTest::newRow("Error.prototype.backtrace") << QString("Error.prototype.backtrace") << QString("backtrace");
@@ -1192,6 +1184,7 @@ void tst_QJSEngine::builtinFunctionNames_data()
QTest::newRow("String.prototype.lastIndexOf") << QString("String.prototype.lastIndexOf") << QString("lastIndexOf");
QTest::newRow("String.prototype.localeCompare") << QString("String.prototype.localeCompare") << QString("localeCompare");
QTest::newRow("String.prototype.match") << QString("String.prototype.match") << QString("match");
+ QTest::newRow("String.prototype.repeat") << QString("String.prototype.repeat") << QString("repeat");
QTest::newRow("String.prototype.replace") << QString("String.prototype.replace") << QString("replace");
QTest::newRow("String.prototype.search") << QString("String.prototype.search") << QString("search");
QTest::newRow("String.prototype.slice") << QString("String.prototype.slice") << QString("slice");
diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
index b7e616a050..1f80ff46d0 100644
--- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
+++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
@@ -43,6 +43,7 @@ private slots:
void loadGeneratedFile();
void translationExpressionSupport();
+ void signalHandlerParameters();
};
// A wrapper around QQmlComponent to ensure the temporary reference counts
@@ -158,6 +159,41 @@ void tst_qmlcachegen::translationExpressionSupport()
QCOMPARE(obj->property("text").toString(), QString("All Ok"));
}
+void tst_qmlcachegen::signalHandlerParameters()
+{
+ QTemporaryDir tempDir;
+ QVERIFY(tempDir.isValid());
+
+ const auto writeTempFile = [&tempDir](const QString &fileName, const char *contents) {
+ QFile f(tempDir.path() + '/' + fileName);
+ const bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate);
+ Q_ASSERT(ok);
+ f.write(contents);
+ return f.fileName();
+ };
+
+ const QString testFilePath = writeTempFile("test.qml", "import QtQml 2.0\n"
+ "QtObject {\n"
+ " property real result: 0\n"
+ " signal testMe(real value);\n"
+ " onTestMe: result = value;\n"
+ " function runTest() { testMe(42); }\n"
+ "}");
+
+ QVERIFY(generateCache(testFilePath));
+
+ const QString cacheFilePath = testFilePath + QLatin1Char('c');
+ QVERIFY(QFile::exists(cacheFilePath));
+ QVERIFY(QFile::remove(testFilePath));
+
+ QQmlEngine engine;
+ CleanlyLoadingComponent component(&engine, QUrl::fromLocalFile(testFilePath));
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ QMetaObject::invokeMethod(obj.data(), "runTest");
+ QCOMPARE(obj->property("result").toInt(), 42);
+}
+
QTEST_GUILESS_MAIN(tst_qmlcachegen)
#include "tst_qmlcachegen.moc"
diff --git a/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp b/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp
index 838966e2a0..68e11e3551 100644
--- a/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp
+++ b/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp
@@ -105,12 +105,12 @@ void tst_qmlplugindump::singleton()
args << QLatin1String("tests.dumper.CompositeSingleton") << QLatin1String("1.0")
<< QLatin1String(".");
dumper.start(qmlplugindumpPath, args);
- dumper.waitForFinished();
+ QVERIFY2(dumper.waitForStarted(), qPrintable(dumper.errorString()));
+ QVERIFY2(dumper.waitForFinished(), qPrintable(dumper.errorString()));
const QString &result = dumper.readAllStandardOutput();
- qDebug() << "result: " << result;
- QVERIFY(result.contains(QLatin1String("exports: [\"Singleton 1.0\"]")));
- QVERIFY(result.contains(QLatin1String("exportMetaObjectRevisions: [0]")));
+ QVERIFY2(result.contains(QLatin1String("exports: [\"Singleton 1.0\"]")), qPrintable(result));
+ QVERIFY2(result.contains(QLatin1String("exportMetaObjectRevisions: [0]")), qPrintable(result));
}
QTEST_MAIN(tst_qmlplugindump)
diff --git a/tests/auto/qml/qqmlbinding/data/bindingOverwriting.qml b/tests/auto/qml/qqmlbinding/data/bindingOverwriting.qml
new file mode 100644
index 0000000000..767ca0c719
--- /dev/null
+++ b/tests/auto/qml/qqmlbinding/data/bindingOverwriting.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.9
+
+Text {
+ visible: text && enabled
+ enabled: font.pixelSize === 25
+ font: enabled ? Qt.font({ "pixelSize": 25 }) : Qt.font({ "pixelSize": 50 })
+
+ Component.onCompleted: {
+ enabled = Qt.binding(function() { return visible; }); // replacement binding, not breaking
+ visible = true; // breaks visible binding
+ font.bold = true; // breaks font binding
+ }
+}
diff --git a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
index 6f1d82eca5..4b485d2ce8 100644
--- a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
+++ b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
@@ -50,6 +50,7 @@ private slots:
void disabledOnUnknownProperty();
void disabledOnReadonlyProperty();
void delayed();
+ void bindingOverwriting();
private:
QQmlEngine engine;
@@ -303,6 +304,21 @@ void tst_qqmlbinding::delayed()
delete item;
}
+void tst_qqmlbinding::bindingOverwriting()
+{
+ QQmlTestMessageHandler messageHandler;
+ QLoggingCategory::setFilterRules(QStringLiteral("qt.qml.binding.removal.info=true"));
+
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("bindingOverwriting.qml"));
+ QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ QVERIFY(item);
+ delete item;
+
+ QLoggingCategory::setFilterRules(QString());
+ QCOMPARE(messageHandler.messages().count(), 2);
+}
+
QTEST_MAIN(tst_qqmlbinding)
#include "tst_qqmlbinding.moc"
diff --git a/tests/auto/qml/qqmlconnections/data/connection-no-signal-name.qml b/tests/auto/qml/qqmlconnections/data/connection-no-signal-name.qml
new file mode 100644
index 0000000000..462a9577ff
--- /dev/null
+++ b/tests/auto/qml/qqmlconnections/data/connection-no-signal-name.qml
@@ -0,0 +1,15 @@
+import QtQuick 2.4
+
+Item {
+ id: blaBlaBla
+ function hint() {
+ }
+
+ Connections {
+ //target: blaBlaBla
+ //onHint: hint();
+ on: true
+ }
+}
+
+
diff --git a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp
index fe45495f74..22e9724c61 100644
--- a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp
+++ b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp
@@ -54,6 +54,7 @@ private slots:
void enableDisable_QTBUG_36350();
void disabledAtStart();
void clearImplicitTarget();
+ void onWithoutASignal();
private:
QQmlEngine engine;
@@ -397,6 +398,15 @@ void tst_qqmlconnections::clearImplicitTarget()
delete item;
}
+void tst_qqmlconnections::onWithoutASignal()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("connection-no-signal-name.qml"));
+ QVERIFY(c.isError()); // Cannot assign to non-existent property "on" expected
+ QScopedPointer<QQuickItem> item(qobject_cast<QQuickItem*>(c.create()));
+ QVERIFY(item == nullptr); // should parse error, and not give us an item (or crash).
+}
+
QTEST_MAIN(tst_qqmlconnections)
#include "tst_qqmlconnections.moc"
diff --git a/tests/auto/qml/qqmlecmascript/data/dynamicString.qml b/tests/auto/qml/qqmlecmascript/data/dynamicString.qml
index 5693794c71..c704161eb5 100644
--- a/tests/auto/qml/qqmlecmascript/data/dynamicString.qml
+++ b/tests/auto/qml/qqmlecmascript/data/dynamicString.qml
@@ -11,6 +11,6 @@ MyTypeObject {
date.setHours(5);
date.setMinutes(30);
date.setSeconds(50);
- stringProperty = stringProperty.arg("Hello World").arg(false).arg(true).arg(100).arg(-100).arg(3.1415926).arg(Qt.formatDateTime(date, "yyyy-MM-dd hh::mm:ss"));
+ stringProperty = stringProperty.arg("Hello World").arg(false).arg(true).arg(100).arg(-100).arg(Math.PI).arg(Qt.formatDateTime(date, "yyyy-MM-dd hh::mm:ss"));
}
}
diff --git a/tests/auto/qml/qqmlecmascript/data/sequenceSort.qml b/tests/auto/qml/qqmlecmascript/data/sequenceSort.qml
index 74c7cda9a3..c6732efc05 100644
--- a/tests/auto/qml/qqmlecmascript/data/sequenceSort.qml
+++ b/tests/auto/qml/qqmlecmascript/data/sequenceSort.qml
@@ -52,7 +52,11 @@ Item {
function doStringTest(stringList, fn) {
var expected = createExpected(stringList, fn);
var actual = msc.strings(stringList);
- return checkResults(expected, actual, fn);
+ var actual2 = msc.stringsVector(stringList);
+ var actual3 = msc.stringsStdVector(stringList);
+ return checkResults(expected, actual, fn)
+ && checkResults(expected, actual2, fn)
+ && checkResults(expected, actual3, fn)
}
function doIntTest(intList, fn) {
var expected = createExpected(intList, fn);
@@ -67,12 +71,16 @@ Item {
function doIntVectorTest(intList, fn) {
var expected = createExpected(intList, fn);
var actual = msc.integerVector(intList);
- return checkResults(expected, actual, fn);
+ var actual2 = msc.integerStdVector(intList);
+ return checkResults(expected, actual, fn)
+ && checkResults(expected, actual2, fn)
}
function doRealVectorTest(realList, fn) {
var expected = createExpected(realList, fn);
var actual = msc.realVector(realList);
- return checkResults(expected, actual, fn);
+ var actual2 = msc.realStdVector(realList);
+ return checkResults(expected, actual, fn)
+ && checkResults(expected, actual2, fn)
}
function test_qtbug_25269(useCustomCompare) {
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.cpp b/tests/auto/qml/qqmlecmascript/testtypes.cpp
index 63c2918325..c4692fdf31 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.cpp
+++ b/tests/auto/qml/qqmlecmascript/testtypes.cpp
@@ -283,6 +283,15 @@ public:
{
return stringList;
}
+ Q_INVOKABLE QVector<QString> stringsVector(const QStringList& stringList) const
+ {
+ return stringList.toVector();
+ }
+ Q_INVOKABLE
+ std::vector<QString> stringsStdVector(const QStringList& stringList) const
+ {
+ return std::vector<QString>(stringList.begin(), stringList.end());
+ }
Q_INVOKABLE QList<int> integers(QList<int> v) const
{
return v;
@@ -299,14 +308,29 @@ public:
{
return v;
}
+ Q_INVOKABLE
+ std::vector<int> integerStdVector(std::vector<int> v) const
+ {
+ return v;
+ }
Q_INVOKABLE QVector<qreal> realVector(QVector<qreal> v) const
{
return v;
}
+ Q_INVOKABLE
+ std::vector<qreal> realStdVector(std::vector<qreal> v) const
+ {
+ return v;
+ }
Q_INVOKABLE QVector<bool> boolVector(QVector<bool> v) const
{
return v;
}
+ Q_INVOKABLE
+ std::vector<bool> boolStdVector(std::vector<bool> v) const
+ {
+ return v;
+ }
};
static MyInheritedQmlObject *theSingletonObject = 0;
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 7b9a43dc38..45f312e934 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2017 Crimson AS <info@crimson.no>
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
@@ -335,6 +336,9 @@ private slots:
void stringify_qtbug_50592();
void instanceof_data();
void instanceof();
+ void constkw_data();
+ void constkw();
+ void redefineGlobalProp();
void freeze_empty_object();
void singleBlockLoops();
void qtbug_60547();
@@ -4031,7 +4035,7 @@ void tst_qqmlecmascript::verifyContextLifetime(QQmlContextData *ctxt) {
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Scope scope(v4);
QV4::ScopedArrayObject scripts(scope, ctxt->importedScripts.value());
- QV4::Scoped<QV4::QmlContextWrapper> qml(scope);
+ QV4::Scoped<QV4::QQmlContextWrapper> qml(scope);
for (quint32 i = 0; i < scripts->getLength(); ++i) {
QQmlContextData *scriptContext, *newContext;
qml = scripts->getIndexed(i);
@@ -8168,6 +8172,8 @@ void tst_qqmlecmascript::stringify_qtbug_50592()
QCOMPARE(obj->property("source").toString(), QString::fromLatin1("http://example.org/some_nonexistant_image.png"));
}
+// Tests for the JS-only instanceof. Tests for the QML extensions for
+// instanceof belong in tst_qqmllanguage!
void tst_qqmlecmascript::instanceof_data()
{
QTest::addColumn<QString>("setupCode");
@@ -8230,6 +8236,108 @@ void tst_qqmlecmascript::instanceof()
}
}
+void tst_qqmlecmascript::constkw_data()
+{
+ QTest::addColumn<QString>("sourceCode");
+ QTest::addColumn<bool>("exceptionExpected");
+ QTest::addColumn<QVariant>("expectedValue");
+
+ QTest::newRow("simpleconst")
+ << "const v = 5\n"
+ "v\n"
+ << false
+ << QVariant(5);
+ QTest::newRow("twoconst")
+ << "const v = 5, i = 10\n"
+ "v + i\n"
+ << false
+ << QVariant(15);
+ QTest::newRow("constandvar")
+ << "const v = 5\n"
+ "var i = 20\n"
+ "v + i\n"
+ << false
+ << QVariant(25);
+ QTest::newRow("const-multiple-scopes-same-var")
+ << "const v = 3\n"
+ "function f() { const v = 1; return v; }\n"
+ "v + f()\n"
+ << false
+ << QVariant(4);
+
+ // error cases
+ QTest::newRow("const-no-initializer")
+ << "const v\n"
+ << true
+ << QVariant("SyntaxError: Missing initializer in const declaration");
+ QTest::newRow("const-no-initializer-comma")
+ << "const v = 1, i\n"
+ << true
+ << QVariant("SyntaxError: Missing initializer in const declaration");
+ QTest::newRow("const-no-duplicate")
+ << "const v = 1, v = 2\n"
+ << true
+ << QVariant("SyntaxError: Identifier v has already been declared");
+ QTest::newRow("const-no-duplicate-2")
+ << "const v = 1\n"
+ "const v = 2\n"
+ << true
+ << QVariant("SyntaxError: Identifier v has already been declared");
+ QTest::newRow("const-no-duplicate-var")
+ << "const v = 1\n"
+ "var v = 1\n"
+ << true
+ << QVariant("SyntaxError: Identifier v has already been declared");
+ QTest::newRow("var-no-duplicate-const")
+ << "var v = 1\n"
+ "const v = 1\n"
+ << true
+ << QVariant("SyntaxError: Identifier v has already been declared");
+ QTest::newRow("const-no-duplicate-let")
+ << "const v = 1\n"
+ "let v = 1\n"
+ << true
+ << QVariant("SyntaxError: Identifier v has already been declared");
+ QTest::newRow("let-no-duplicate-const")
+ << "let v = 1\n"
+ "const v = 1\n"
+ << true
+ << QVariant("SyntaxError: Identifier v has already been declared");
+}
+
+void tst_qqmlecmascript::constkw()
+{
+ QFETCH(QString, sourceCode);
+ QFETCH(bool, exceptionExpected);
+ QFETCH(QVariant, expectedValue);
+
+ QJSEngine engine;
+ QJSValue ret = engine.evaluate(sourceCode);
+
+ if (!exceptionExpected) {
+ QVERIFY2(!ret.isError(), qPrintable(ret.toString()));
+ QCOMPARE(ret.toVariant(), expectedValue);
+ } else {
+ QVERIFY2(ret.isError(), qPrintable(ret.toString()));
+ QCOMPARE(ret.toString(), expectedValue.toString());
+ }
+}
+
+// Redefine a property found on the global object. It shouldn't throw.
+void tst_qqmlecmascript::redefineGlobalProp()
+{
+ {
+ QJSEngine engine;
+ QJSValue ret = engine.evaluate("\"use strict\"\n var toString = 1;");
+ QVERIFY2(!ret.isError(), qPrintable(ret.toString()));
+ }
+ {
+ QJSEngine engine;
+ QJSValue ret = engine.evaluate("var toString = 1;");
+ QVERIFY2(!ret.isError(), qPrintable(ret.toString()));
+ }
+}
+
void tst_qqmlecmascript::freeze_empty_object()
{
// this shouldn't crash
diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
index dac6ddaebd..7aca830297 100644
--- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
+++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
@@ -741,6 +741,9 @@ public:
if (url.path().endsWith("Test.2/qmldir"))//Special case
return QUrl::fromLocalFile(m_base.path() + "interception/module/intercepted/qmldir");
+ // Special case: with 5.10 we always add the implicit import, so we need to explicitly handle this case now
+ if (url.path().endsWith("intercepted/qmldir"))
+ return url;
QString alteredPath = url.path();
int a = alteredPath.lastIndexOf('/');
diff --git a/tests/auto/qml/qqmllanguage/data/TypeWithEnum.qml b/tests/auto/qml/qqmllanguage/data/TypeWithEnum.qml
new file mode 100644
index 0000000000..c89a228bef
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/TypeWithEnum.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.0
+
+QtObject {
+ enum MyEnum {
+ EnumValue1,
+ EnumValue2,
+ EnumValue3
+ }
+
+ property int enumValue: TypeWithEnum.EnumValue2
+ property int enumValue2
+ property int scopedEnumValue: TypeWithEnum.MyEnum.EnumValue2
+ Component.onCompleted: enumValue2 = TypeWithEnum.EnumValue3
+}
diff --git a/tests/auto/qml/qqmllanguage/data/cppnamespace.qml b/tests/auto/qml/qqmllanguage/data/cppnamespace.qml
index efedf2b14a..48f7eb6715 100644
--- a/tests/auto/qml/qqmllanguage/data/cppnamespace.qml
+++ b/tests/auto/qml/qqmllanguage/data/cppnamespace.qml
@@ -2,4 +2,5 @@ import Test 1.0
MyNamespacedType {
myEnum: MyNamespace.Key5
+ property int intProperty: MyNamespace.MyOtherNSEnum.OtherKey2
}
diff --git a/tests/auto/qml/qqmllanguage/data/instanceOf/CustomMouseArea.qml b/tests/auto/qml/qqmllanguage/data/instanceOf/CustomMouseArea.qml
new file mode 100644
index 0000000000..f6ec5848c1
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/instanceOf/CustomMouseArea.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.6
+
+MouseArea {
+
+}
+
diff --git a/tests/auto/qml/qqmllanguage/data/instanceOf/CustomRectangle.qml b/tests/auto/qml/qqmllanguage/data/instanceOf/CustomRectangle.qml
new file mode 100644
index 0000000000..b3fa43a671
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/instanceOf/CustomRectangle.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.6
+
+Rectangle {
+}
diff --git a/tests/auto/qml/qqmllanguage/data/instanceOf/CustomRectangleWithProp.qml b/tests/auto/qml/qqmllanguage/data/instanceOf/CustomRectangleWithProp.qml
new file mode 100644
index 0000000000..cf566b9315
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/instanceOf/CustomRectangleWithProp.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.6
+
+Rectangle {
+ property int somethingCustom: 0
+}
+
diff --git a/tests/auto/qml/qqmllanguage/data/instanceOf/qmldir b/tests/auto/qml/qqmllanguage/data/instanceOf/qmldir
new file mode 100644
index 0000000000..144c93d8e3
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/instanceOf/qmldir
@@ -0,0 +1,2 @@
+CustomRectangle 1.0 CustomRectangle.qml
+CustomMouseArea 1.0 CustomMouseArea.qml
diff --git a/tests/auto/qml/qqmllanguage/data/instanceof_qtqml.qml b/tests/auto/qml/qqmllanguage/data/instanceof_qtqml.qml
new file mode 100644
index 0000000000..d74b172cf8
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/instanceof_qtqml.qml
@@ -0,0 +1,13 @@
+import QtQml 2.0
+
+QtObject {
+ id: qtobjectInstance
+
+ property Timer aTimer: Timer {
+ id: timerInstance
+ }
+
+ property Connections aConnections: Connections {
+ id: connectionsInstance
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/instanceof_qtqml_qualified.qml b/tests/auto/qml/qqmllanguage/data/instanceof_qtqml_qualified.qml
new file mode 100644
index 0000000000..a8e303363e
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/instanceof_qtqml_qualified.qml
@@ -0,0 +1,13 @@
+import QtQml 2.0 as QmlImport
+
+QmlImport.QtObject {
+ id: qtobjectInstance
+
+ property QmlImport.Timer aTimer: QmlImport.Timer {
+ id: timerInstance
+ }
+
+ property QmlImport.Connections aConnections: QmlImport.Connections {
+ id: connectionsInstance
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/instanceof_qtquick.qml b/tests/auto/qml/qqmllanguage/data/instanceof_qtquick.qml
new file mode 100644
index 0000000000..9c1808d515
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/instanceof_qtquick.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.0
+
+Item {
+ id: itemInstance
+
+ Rectangle {
+ id: rectangleInstance
+ }
+
+ MouseArea {
+ id: mouseAreaInstance
+ }
+}
+
diff --git a/tests/auto/qml/qqmllanguage/data/instanceof_qtquick_composite.qml b/tests/auto/qml/qqmllanguage/data/instanceof_qtquick_composite.qml
new file mode 100644
index 0000000000..78fc112805
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/instanceof_qtquick_composite.qml
@@ -0,0 +1,26 @@
+import QtQuick 2.0
+import "instanceOf"
+
+Item {
+ id: itemInstance
+
+ Rectangle {
+ id: rectangleInstance
+ }
+
+ MouseArea {
+ id: mouseAreaInstance
+ }
+
+ CustomRectangle {
+ id: customRectangleInstance
+ }
+ CustomRectangleWithProp {
+ id: customRectangleWithPropInstance
+ }
+ CustomMouseArea {
+ id: customMouseAreaInstance
+ }
+}
+
+
diff --git a/tests/auto/qml/qqmllanguage/data/instanceof_qtquick_composite_qualified.qml b/tests/auto/qml/qqmllanguage/data/instanceof_qtquick_composite_qualified.qml
new file mode 100644
index 0000000000..97361b7334
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/instanceof_qtquick_composite_qualified.qml
@@ -0,0 +1,27 @@
+import QtQuick 2.0 as QuickImport
+import "instanceOf" as CustomImport
+
+QuickImport.Item {
+ id: itemInstance
+
+ QuickImport.Rectangle {
+ id: rectangleInstance
+ }
+
+ QuickImport.MouseArea {
+ id: mouseAreaInstance
+ }
+
+ CustomImport.CustomRectangle {
+ id: customRectangleInstance
+ }
+ CustomImport.CustomRectangleWithProp {
+ id: customRectangleWithPropInstance
+ }
+ CustomImport.CustomMouseArea {
+ id: customMouseAreaInstance
+ }
+}
+
+
+
diff --git a/tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/NonSingletonType.qml b/tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/NonSingletonType.qml
new file mode 100644
index 0000000000..ec7c76c055
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/NonSingletonType.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+import org.qtproject.MixedModule 1.0
+
+Item {
+}
diff --git a/tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/SingletonType.qml b/tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/SingletonType.qml
new file mode 100644
index 0000000000..7763c783f1
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/SingletonType.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+pragma Singleton
+
+Item {
+}
diff --git a/tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/qmldir b/tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/qmldir
new file mode 100644
index 0000000000..cd03a5f941
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/qmldir
@@ -0,0 +1,4 @@
+module org.qtproject.MixedModule
+singleton SingletonType 1.0 SingletonType.qml
+NonSingletonType 1.0 NonSingletonType.qml
+Test 1.0 test.js
diff --git a/tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/test.js b/tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/test.js
new file mode 100644
index 0000000000..6a53b53b02
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/test.js
@@ -0,0 +1 @@
+var foo = 1
diff --git a/tests/auto/qml/qqmllanguage/data/lowercaseQmlEnum.1.errors.txt b/tests/auto/qml/qqmllanguage/data/lowercaseQmlEnum.1.errors.txt
new file mode 100644
index 0000000000..d1bd2bcff4
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/lowercaseQmlEnum.1.errors.txt
@@ -0,0 +1 @@
+6:9:Enum names must begin with an upper case letter
diff --git a/tests/auto/qml/qqmllanguage/data/lowercaseQmlEnum.1.qml b/tests/auto/qml/qqmllanguage/data/lowercaseQmlEnum.1.qml
new file mode 100644
index 0000000000..0b50820128
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/lowercaseQmlEnum.1.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.0
+
+QtObject {
+ enum MyEnum {
+ EnumValue1,
+ enumValue2,
+ EnumValue3
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/lowercaseQmlEnum.2.errors.txt b/tests/auto/qml/qqmllanguage/data/lowercaseQmlEnum.2.errors.txt
new file mode 100644
index 0000000000..3e051c416e
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/lowercaseQmlEnum.2.errors.txt
@@ -0,0 +1 @@
+4:5:Scoped enum names must begin with an upper case letter
diff --git a/tests/auto/qml/qqmllanguage/data/lowercaseQmlEnum.2.qml b/tests/auto/qml/qqmllanguage/data/lowercaseQmlEnum.2.qml
new file mode 100644
index 0000000000..bb7aea6aa4
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/lowercaseQmlEnum.2.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.0
+
+QtObject {
+ enum myEnum {
+ EnumValue1,
+ EnumValue2,
+ EnumValue3
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/mixedModuleWithSelfImport.qml b/tests/auto/qml/qqmllanguage/data/mixedModuleWithSelfImport.qml
new file mode 100644
index 0000000000..7768a6aedf
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/mixedModuleWithSelfImport.qml
@@ -0,0 +1,3 @@
+import org.qtproject.MixedModule 1.0
+
+NonSingletonType {}
diff --git a/tests/auto/qml/qqmllanguage/data/registeredCompositeTypeWithEnum.qml b/tests/auto/qml/qqmllanguage/data/registeredCompositeTypeWithEnum.qml
index 5f8c11e5f6..b6a07693f2 100644
--- a/tests/auto/qml/qqmllanguage/data/registeredCompositeTypeWithEnum.qml
+++ b/tests/auto/qml/qqmllanguage/data/registeredCompositeTypeWithEnum.qml
@@ -3,4 +3,5 @@ import Test 1.0
RegisteredCompositeTypeWithEnum {
property int enumValue0: RegisteredCompositeTypeWithEnum.EnumValue0
property int enumValue42: RegisteredCompositeTypeWithEnum.EnumValue42
+ property int enumValue15: RegisteredCompositeTypeWithEnum.ScopedCompositeEnum.EnumValue15
}
diff --git a/tests/auto/qml/qqmllanguage/data/scopedEnum.qml b/tests/auto/qml/qqmllanguage/data/scopedEnum.qml
new file mode 100644
index 0000000000..7f4177af76
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/scopedEnum.qml
@@ -0,0 +1,21 @@
+import QtQuick 2.0
+import Test 1.0
+
+MyTypeObject {
+ id: obj
+ scopedEnum: MyTypeObject.MyScopedEnum.ScopedVal1
+ intProperty: MyTypeObject.MyScopedEnum.ScopedVal2
+ property int listValue: myModel.get(0).myData
+ property int noScope: MyTypeObject.ScopedVal1
+
+ function assignNewValue() {
+ scopedEnum = MyTypeObject.MyScopedEnum.ScopedVal2
+ noScope = MyTypeObject.ScopedVal2
+ }
+
+ property ListModel myModel: ListModel {
+ ListElement {
+ myData: MyTypeObject.MyScopedEnum.ScopedVal3
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/scopedEnumList.errors.txt b/tests/auto/qml/qqmllanguage/data/scopedEnumList.errors.txt
new file mode 100644
index 0000000000..67576dfd8d
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/scopedEnumList.errors.txt
@@ -0,0 +1 @@
+7:13:ListElement: cannot use script for property value
diff --git a/tests/auto/qml/qqmllanguage/data/scopedEnumList.qml b/tests/auto/qml/qqmllanguage/data/scopedEnumList.qml
new file mode 100644
index 0000000000..8655139683
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/scopedEnumList.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.0
+import Test 1.0
+
+MyTypeObject {
+ property ListModel myModel: ListModel {
+ ListElement {
+ myData: MyTypeObject.MyScopedEnum
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/usingTypeWithEnum.qml b/tests/auto/qml/qqmllanguage/data/usingTypeWithEnum.qml
new file mode 100644
index 0000000000..2509fc0df1
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/usingTypeWithEnum.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+
+QtObject {
+ property int enumValue: TypeWithEnum.EnumValue2
+ property int enumValue2: -1
+ property int scopedEnumValue: TypeWithEnum.MyEnum.EnumValue3
+ Component.onCompleted: enumValue2 = TypeWithEnum.EnumValue1
+}
diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h
index 7d7a8ac6d3..e4a76b4324 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.h
+++ b/tests/auto/qml/qqmllanguage/testtypes.h
@@ -223,6 +223,7 @@ class MyTypeObject : public QObject
Q_PROPERTY(Qt::TextFormat qtEnumProperty READ qtEnumProperty WRITE setQtEnumProperty NOTIFY qtEnumPropertyChanged)
Q_PROPERTY(MyMirroredEnum mirroredEnumProperty READ mirroredEnumProperty WRITE setMirroredEnumProperty NOTIFY mirroredEnumPropertyChanged)
Q_PROPERTY(MyEnumContainer::RelatedEnum relatedEnumProperty READ relatedEnumProperty WRITE setRelatedEnumProperty)
+ Q_PROPERTY(MyScopedEnum scopedEnum READ scopedEnum WRITE setScopedEnum)
Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty NOTIFY stringPropertyChanged)
Q_PROPERTY(QByteArray byteArrayProperty READ byteArrayProperty WRITE setByteArrayProperty NOTIFY byteArrayPropertyChanged)
Q_PROPERTY(uint uintProperty READ uintProperty WRITE setUintProperty NOTIFY uintPropertyChanged)
@@ -339,6 +340,14 @@ public:
relatedEnumPropertyValue = v;
}
+ enum class MyScopedEnum : int { ScopedVal1, ScopedVal2, ScopedVal3 };
+ Q_ENUM(MyScopedEnum)
+ MyScopedEnum scopedEnumPropertyValue;
+ MyScopedEnum scopedEnum() const { return scopedEnumPropertyValue; }
+ void setScopedEnum(MyScopedEnum v) {
+ scopedEnumPropertyValue = v;
+ }
+
QString stringPropertyValue;
QString stringProperty() const {
return stringPropertyValue;
@@ -738,6 +747,13 @@ namespace MyNamespace {
};
Q_ENUM_NS(MyNSEnum);
+ enum class MyOtherNSEnum {
+ OtherKey1 = 1,
+ OtherKey2
+ };
+ Q_ENUM_NS(MyOtherNSEnum);
+
+
class MyNamespacedType : public QObject
{
Q_OBJECT
@@ -1171,9 +1187,11 @@ class MyCompositeBaseType : public QObject
{
Q_OBJECT
Q_ENUMS(CompositeEnum)
+ Q_ENUMS(ScopedCompositeEnum)
public:
enum CompositeEnum { EnumValue0, EnumValue42 = 42 };
+ enum class ScopedCompositeEnum : int { EnumValue15 = 15 };
static QObject *qmlAttachedProperties(QObject *parent) { return new QObject(parent); }
};
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 39f5082c70..c145c6d737 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -178,6 +178,7 @@ private slots:
void importIncorrectCase();
void importJs_data();
void importJs();
+ void explicitSelfImport();
void qmlAttachedPropertiesObjectMethod();
void customOnProperty();
@@ -208,6 +209,8 @@ private slots:
void lowercaseEnumRuntime();
void lowercaseEnumCompileTime_data();
void lowercaseEnumCompileTime();
+ void scopedEnum();
+ void qmlEnums();
void literals_data();
void literals();
@@ -263,6 +266,9 @@ private slots:
void qmlTypeCanBeResolvedByName_data();
void qmlTypeCanBeResolvedByName();
+ void instanceof_data();
+ void instanceof();
+
void concurrentLoadQmlDir();
private:
@@ -311,7 +317,7 @@ private:
if (!errorfile) { \
if (qgetenv("DEBUG") != "" && !component.errors().isEmpty()) \
qWarning() << "Unexpected Errors:" << component.errors(); \
- QVERIFY(!component.isError()); \
+ QVERIFY2(!component.isError(), qPrintable(component.errorString())); \
QVERIFY(component.errors().isEmpty()); \
} else { \
DETERMINE_ERRORS(errorfile,expected,actual);\
@@ -540,6 +546,10 @@ void tst_qqmllanguage::errors_data()
QTest::newRow("singularProperty") << "singularProperty.qml" << "singularProperty.errors.txt" << false;
QTest::newRow("singularProperty.2") << "singularProperty.2.qml" << "singularProperty.2.errors.txt" << false;
+ QTest::newRow("scopedEnumList") << "scopedEnumList.qml" << "scopedEnumList.errors.txt" << false;
+ QTest::newRow("lowercase enum value") << "lowercaseQmlEnum.1.qml" << "lowercaseQmlEnum.1.errors.txt" << false;
+ QTest::newRow("lowercase enum type") << "lowercaseQmlEnum.2.qml" << "lowercaseQmlEnum.2.errors.txt" << false;
+
const QString expectedError = isCaseSensitiveFileSystem(dataDirectory()) ?
QStringLiteral("incorrectCase.errors.sensitive.txt") :
QStringLiteral("incorrectCase.errors.insensitive.txt");
@@ -1600,6 +1610,9 @@ void tst_qqmllanguage::cppnamespace()
VERIFY_ERRORS(0);
QObject *object = component.create();
QVERIFY(object != 0);
+
+ QCOMPARE(object->property("intProperty").toInt(), (int)MyNamespace::MyOtherNSEnum::OtherKey2);
+
delete object;
}
@@ -3058,12 +3071,22 @@ void tst_qqmllanguage::importJs()
engine.setImportPathList(defaultImportPathList);
}
+void tst_qqmllanguage::explicitSelfImport()
+{
+ engine.setImportPathList(QStringList(defaultImportPathList) << testFile("lib"));
+
+ QQmlComponent component(&engine, testFileUrl("mixedModuleWithSelfImport.qml"));
+ QVERIFY(component.errors().count() == 0);
+
+ engine.setImportPathList(defaultImportPathList);
+}
+
void tst_qqmllanguage::qmlAttachedPropertiesObjectMethod()
{
QObject object;
QCOMPARE(qmlAttachedPropertiesObject<MyQmlObject>(&object, false), (QObject *)0);
- QCOMPARE(qmlAttachedPropertiesObject<MyQmlObject>(&object, true), (QObject *)0);
+ QVERIFY(qmlAttachedPropertiesObject<MyQmlObject>(&object, true));
{
QQmlComponent component(&engine, testFileUrl("qmlAttachedPropertiesObjectMethod.1.qml"));
@@ -3500,6 +3523,7 @@ void tst_qqmllanguage::registeredCompositeTypeWithEnum()
QCOMPARE(o->property("enumValue0").toInt(), static_cast<int>(MyCompositeBaseType::EnumValue0));
QCOMPARE(o->property("enumValue42").toInt(), static_cast<int>(MyCompositeBaseType::EnumValue42));
+ QCOMPARE(o->property("enumValue15").toInt(), static_cast<int>(MyCompositeBaseType::ScopedCompositeEnum::EnumValue15));
delete o;
}
@@ -3680,6 +3704,44 @@ void tst_qqmllanguage::lowercaseEnumCompileTime()
VERIFY_ERRORS(qPrintable(errorFile));
}
+void tst_qqmllanguage::scopedEnum()
+{
+ QQmlComponent component(&engine, testFileUrl("scopedEnum.qml"));
+
+ MyTypeObject *o = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(o != 0);
+
+ QCOMPARE(o->scopedEnum(), MyTypeObject::MyScopedEnum::ScopedVal1);
+ QCOMPARE(o->intProperty(), (int)MyTypeObject::MyScopedEnum::ScopedVal2);
+ QCOMPARE(o->property("listValue").toInt(), (int)MyTypeObject::MyScopedEnum::ScopedVal3);
+ QCOMPARE(o->property("noScope").toInt(), (int)MyTypeObject::MyScopedEnum::ScopedVal1);
+
+ QMetaObject::invokeMethod(o, "assignNewValue");
+ QCOMPARE(o->scopedEnum(), MyTypeObject::MyScopedEnum::ScopedVal2);
+ QCOMPARE(o->property("noScope").toInt(), (int)MyTypeObject::MyScopedEnum::ScopedVal2);
+}
+
+void tst_qqmllanguage::qmlEnums()
+{
+ {
+ QQmlComponent component(&engine, testFileUrl("TypeWithEnum.qml"));
+ QObject *o = component.create();
+ QVERIFY(o);
+ QCOMPARE(o->property("enumValue").toInt(), 1);
+ QCOMPARE(o->property("enumValue2").toInt(), 2);
+ QCOMPARE(o->property("scopedEnumValue").toInt(), 1);
+ }
+
+ {
+ QQmlComponent component(&engine, testFileUrl("usingTypeWithEnum.qml"));
+ QObject *o = component.create();
+ QVERIFY(o);
+ QCOMPARE(o->property("enumValue").toInt(), 1);
+ QCOMPARE(o->property("enumValue2").toInt(), 0);
+ QCOMPARE(o->property("scopedEnumValue").toInt(), 2);
+ }
+}
+
void tst_qqmllanguage::literals_data()
{
QTest::addColumn<QString>("property");
@@ -4340,6 +4402,200 @@ void tst_qqmllanguage::qmlTypeCanBeResolvedByName()
QVERIFY(!o.isNull());
}
+// Tests for the QML-only extensions of instanceof. Tests for the regular JS
+// instanceof belong in tst_qqmlecmascript!
+void tst_qqmllanguage::instanceof_data()
+{
+ QTest::addColumn<QUrl>("documentToTestIn");
+ QTest::addColumn<QVariant>("expectedValue");
+
+ // so the way this works is that the name of the test tag defines the test
+ // to run.
+ //
+ // the expectedValue is either a boolean true or false for whether the two
+ // operands are indeed an instanceof each other, or a string for the
+ // expected error message.
+
+ // assert that basic types don't convert to QObject
+ QTest::newRow("1 instanceof QtObject")
+ << testFileUrl("instanceof_qtqml.qml")
+ << QVariant("TypeError: Type error");
+ QTest::newRow("true instanceof QtObject")
+ << testFileUrl("instanceof_qtqml.qml")
+ << QVariant("TypeError: Type error");
+ QTest::newRow("\"foobar\" instanceof QtObject")
+ << testFileUrl("instanceof_qtqml.qml")
+ << QVariant("TypeError: Type error");
+
+ // assert that Managed don't either
+ QTest::newRow("new String(\"foobar\") instanceof QtObject")
+ << testFileUrl("instanceof_qtqml.qml")
+ << QVariant("TypeError: Type error");
+ QTest::newRow("new Object() instanceof QtObject")
+ << testFileUrl("instanceof_qtqml.qml")
+ << QVariant("TypeError: Type error");
+ QTest::newRow("new Date() instanceof QtObject")
+ << testFileUrl("instanceof_qtqml.qml")
+ << QVariant("TypeError: Type error");
+
+ // test that simple QtQml comparisons work
+ QTest::newRow("qtobjectInstance instanceof QtObject")
+ << testFileUrl("instanceof_qtqml.qml")
+ << QVariant(true);
+ QTest::newRow("qtobjectInstance instanceof Timer")
+ << testFileUrl("instanceof_qtqml.qml")
+ << QVariant(false);
+ QTest::newRow("timerInstance instanceof QtObject")
+ << testFileUrl("instanceof_qtqml.qml")
+ << QVariant(true);
+ QTest::newRow("timerInstance instanceof Timer")
+ << testFileUrl("instanceof_qtqml.qml")
+ << QVariant(true);
+ QTest::newRow("connectionsInstance instanceof QtObject")
+ << testFileUrl("instanceof_qtqml.qml")
+ << QVariant(true);
+ QTest::newRow("connectionsInstance instanceof Timer")
+ << testFileUrl("instanceof_qtqml.qml")
+ << QVariant(false);
+ QTest::newRow("connectionsInstance instanceof Connections")
+ << testFileUrl("instanceof_qtqml.qml")
+ << QVariant(true);
+
+ // make sure they still work when imported with a qualifier
+ QTest::newRow("qtobjectInstance instanceof QmlImport.QtObject")
+ << testFileUrl("instanceof_qtqml_qualified.qml")
+ << QVariant(true);
+ QTest::newRow("qtobjectInstance instanceof QmlImport.Timer")
+ << testFileUrl("instanceof_qtqml_qualified.qml")
+ << QVariant(false);
+ QTest::newRow("timerInstance instanceof QmlImport.QtObject")
+ << testFileUrl("instanceof_qtqml_qualified.qml")
+ << QVariant(true);
+ QTest::newRow("timerInstance instanceof QmlImport.Timer")
+ << testFileUrl("instanceof_qtqml_qualified.qml")
+ << QVariant(true);
+ QTest::newRow("connectionsInstance instanceof QmlImport.QtObject")
+ << testFileUrl("instanceof_qtqml_qualified.qml")
+ << QVariant(true);
+ QTest::newRow("connectionsInstance instanceof QmlImport.Timer")
+ << testFileUrl("instanceof_qtqml_qualified.qml")
+ << QVariant(false);
+ QTest::newRow("connectionsInstance instanceof QmlImport.Connections")
+ << testFileUrl("instanceof_qtqml_qualified.qml")
+ << QVariant(true);
+
+ // test that Quick C++ types work ok
+ QTest::newRow("itemInstance instanceof QtObject")
+ << testFileUrl("instanceof_qtquick.qml")
+ << QVariant(true);
+ QTest::newRow("itemInstance instanceof Timer")
+ << testFileUrl("instanceof_qtquick.qml")
+ << QVariant(false);
+ QTest::newRow("itemInstance instanceof Rectangle")
+ << testFileUrl("instanceof_qtquick.qml")
+ << QVariant(false);
+ QTest::newRow("rectangleInstance instanceof Item")
+ << testFileUrl("instanceof_qtquick.qml")
+ << QVariant(true);
+ QTest::newRow("rectangleInstance instanceof Rectangle")
+ << testFileUrl("instanceof_qtquick.qml")
+ << QVariant(true);
+ QTest::newRow("rectangleInstance instanceof MouseArea")
+ << testFileUrl("instanceof_qtquick.qml")
+ << QVariant(false);
+ QTest::newRow("mouseAreaInstance instanceof Item")
+ << testFileUrl("instanceof_qtquick.qml")
+ << QVariant(true);
+ QTest::newRow("mouseAreaInstance instanceof Rectangle")
+ << testFileUrl("instanceof_qtquick.qml")
+ << QVariant(false);
+ QTest::newRow("mouseAreaInstance instanceof MouseArea")
+ << testFileUrl("instanceof_qtquick.qml")
+ << QVariant(true);
+
+ // test that unqualified quick composite types work ok
+ QTest::newRow("rectangleInstance instanceof CustomRectangle")
+ << testFileUrl("instanceof_qtquick_composite.qml")
+ << QVariant(false);
+ QTest::newRow("customRectangleInstance instanceof Rectangle")
+ << testFileUrl("instanceof_qtquick_composite.qml")
+ << QVariant(true);
+ QTest::newRow("customRectangleInstance instanceof Item")
+ << testFileUrl("instanceof_qtquick_composite.qml")
+ << QVariant(true);
+ QTest::newRow("customRectangleWithPropInstance instanceof CustomRectangleWithProp")
+ << testFileUrl("instanceof_qtquick_composite.qml")
+ << QVariant(true);
+ QTest::newRow("customRectangleWithPropInstance instanceof CustomRectangle")
+ << testFileUrl("instanceof_qtquick_composite.qml")
+ << QVariant(false); // ### XXX: QTBUG-58477
+ QTest::newRow("customRectangleWithPropInstance instanceof Rectangle")
+ << testFileUrl("instanceof_qtquick_composite.qml")
+ << QVariant(true);
+ QTest::newRow("customRectangleInstance instanceof MouseArea")
+ << testFileUrl("instanceof_qtquick_composite.qml")
+ << QVariant(false);
+ QTest::newRow("customMouseAreaInstance instanceof MouseArea")
+ << testFileUrl("instanceof_qtquick_composite.qml")
+ << QVariant(true);
+
+ // test that they still work when qualified
+ QTest::newRow("rectangleInstance instanceof CustomImport.CustomRectangle")
+ << testFileUrl("instanceof_qtquick_composite_qualified.qml")
+ << QVariant(false);
+ QTest::newRow("customRectangleInstance instanceof QuickImport.Rectangle")
+ << testFileUrl("instanceof_qtquick_composite_qualified.qml")
+ << QVariant(true);
+ QTest::newRow("customRectangleInstance instanceof QuickImport.Item")
+ << testFileUrl("instanceof_qtquick_composite_qualified.qml")
+ << QVariant(true);
+ QTest::newRow("customRectangleWithPropInstance instanceof CustomImport.CustomRectangleWithProp")
+ << testFileUrl("instanceof_qtquick_composite_qualified.qml")
+ << QVariant(true);
+ QTest::newRow("customRectangleWithPropInstance instanceof CustomImport.CustomRectangle")
+ << testFileUrl("instanceof_qtquick_composite_qualified.qml")
+ << QVariant(false); // ### XXX: QTBUG-58477
+ QTest::newRow("customRectangleWithPropInstance instanceof QuickImport.Rectangle")
+ << testFileUrl("instanceof_qtquick_composite_qualified.qml")
+ << QVariant(true);
+ QTest::newRow("customRectangleInstance instanceof QuickImport.MouseArea")
+ << testFileUrl("instanceof_qtquick_composite_qualified.qml")
+ << QVariant(false);
+ QTest::newRow("customMouseAreaInstance instanceof QuickImport.MouseArea")
+ << testFileUrl("instanceof_qtquick_composite_qualified.qml")
+ << QVariant(true);
+}
+
+void tst_qqmllanguage::instanceof()
+{
+ QFETCH(QUrl, documentToTestIn);
+ QFETCH(QVariant, expectedValue);
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine, documentToTestIn);
+ VERIFY_ERRORS(0);
+
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(o != 0);
+
+ QQmlExpression expr(engine.contextForObject(o.data()), 0, QString::fromLatin1(QTest::currentDataTag()));
+ QVariant ret = expr.evaluate();
+
+ if (expectedValue.type() == QVariant::Bool) {
+ // no error expected
+ QVERIFY2(!expr.hasError(), qPrintable(expr.error().description()));
+ bool returnValue = ret.toBool();
+
+ if (QTest::currentDataTag() == QLatin1String("customRectangleWithPropInstance instanceof CustomRectangle") ||
+ QTest::currentDataTag() == QLatin1String("customRectangleWithPropInstance instanceof CustomImport.CustomRectangle"))
+ QEXPECT_FAIL("", "QTBUG-58477: QML type rules are a little lax", Continue);
+ QCOMPARE(returnValue, expectedValue.toBool());
+ } else {
+ QVERIFY(expr.hasError());
+ QCOMPARE(expr.error().description(), expectedValue.toString());
+ }
+}
+
void tst_qqmllanguage::concurrentLoadQmlDir()
{
ThreadedTestHTTPServer server(dataDirectory());
diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
index 555ca5713e..e442dd1421 100644
--- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
+++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
@@ -1204,8 +1204,8 @@ void tst_qqmllistmodel::role_mode_data()
QTest::newRow("default1") << "{append({'a':1});dynamicRoles}" << 0 << "";
QTest::newRow("enableDynamic0") << "{dynamicRoles=true;dynamicRoles}" << 1 << "";
- QTest::newRow("enableDynamic1") << "{append({'a':1});dynamicRoles=true;dynamicRoles}" << 0 << "<Unknown File>: QML ListModel: unable to enable dynamic roles as this model is not empty!";
- QTest::newRow("enableDynamic2") << "{dynamicRoles=true;append({'a':1});dynamicRoles=false;dynamicRoles}" << 1 << "<Unknown File>: QML ListModel: unable to enable static roles as this model is not empty!";
+ QTest::newRow("enableDynamic1") << "{append({'a':1});dynamicRoles=true;dynamicRoles}" << 0 << "<Unknown File>: QML ListModel: unable to enable dynamic roles as this model is not empty";
+ QTest::newRow("enableDynamic2") << "{dynamicRoles=true;append({'a':1});dynamicRoles=false;dynamicRoles}" << 1 << "<Unknown File>: QML ListModel: unable to enable static roles as this model is not empty";
}
void tst_qqmllistmodel::role_mode()
diff --git a/tests/auto/qml/qqmltranslation/data/TranslationChangeBase.qml b/tests/auto/qml/qqmltranslation/data/TranslationChangeBase.qml
new file mode 100644
index 0000000000..c447c84987
--- /dev/null
+++ b/tests/auto/qml/qqmltranslation/data/TranslationChangeBase.qml
@@ -0,0 +1,5 @@
+import QtQml 2.0
+
+QtObject {
+ property string baseProperty: qsTr("translate me");
+}
diff --git a/tests/auto/qml/qqmltranslation/data/translationChange.qml b/tests/auto/qml/qqmltranslation/data/translationChange.qml
new file mode 100644
index 0000000000..23b87c2493
--- /dev/null
+++ b/tests/auto/qml/qqmltranslation/data/translationChange.qml
@@ -0,0 +1,10 @@
+import QtQml 2.0
+
+TranslationChangeBase {
+ baseProperty: "do not translate"
+ property string text1: qsTr("translate me")
+ function weDoTranslations() {
+ return qsTr("translate me")
+ }
+ property string text2: weDoTranslations()
+}
diff --git a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
index 1fc803a395..1c9523fc38 100644
--- a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
+++ b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
@@ -44,6 +44,7 @@ private slots:
void translation_data();
void translation();
void idTranslation();
+ void translationChange();
};
void tst_qqmltranslation::translation_data()
@@ -162,6 +163,51 @@ void tst_qqmltranslation::idTranslation()
delete object;
}
+class DummyTranslator : public QTranslator
+{
+ Q_OBJECT
+
+ QString translate(const char *context, const char *sourceText, const char *disambiguation, int n) const override
+ {
+ Q_UNUSED(context);
+ Q_UNUSED(disambiguation);
+ Q_UNUSED(n);
+ if (!qstrcmp(sourceText, "translate me"))
+ return QString::fromUtf8("xxx");
+ return QString();
+ }
+
+ bool isEmpty() const override
+ {
+ return false;
+ }
+};
+
+void tst_qqmltranslation::translationChange()
+{
+ QQmlEngine engine;
+
+ QQmlComponent component(&engine, testFileUrl("translationChange.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QCOMPARE(object->property("baseProperty").toString(), QString::fromUtf8("do not translate"));
+ QCOMPARE(object->property("text1").toString(), QString::fromUtf8("translate me"));
+ QCOMPARE(object->property("text2").toString(), QString::fromUtf8("translate me"));
+
+ DummyTranslator translator;
+ QCoreApplication::installTranslator(&translator);
+
+ QEvent ev(QEvent::LanguageChange);
+ QCoreApplication::sendEvent(&engine, &ev);
+
+ QCOMPARE(object->property("baseProperty").toString(), QString::fromUtf8("do not translate"));
+ QCOMPARE(object->property("text1").toString(), QString::fromUtf8("xxx"));
+ QCOMPARE(object->property("text2").toString(), QString::fromUtf8("xxx"));
+
+ QCoreApplication::removeTranslator(&translator);
+}
+
QTEST_MAIN(tst_qqmltranslation)
#include "tst_qqmltranslation.moc"
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.expect
new file mode 100644
index 0000000000..6d34e1d2bb
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.expect
Binary files differ
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.qml
new file mode 100644
index 0000000000..ba9761201e
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.qml
@@ -0,0 +1,23 @@
+import QtQuick 2.0
+
+QtObject {
+ property string url
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+ x.open("POST", url);
+ x.setRequestHeader("Accept-Language","en-US");
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+
+ var data = new Uint8Array([1, 2, 3, 0, 3, 2, 1])
+ x.send(data.buffer);
+ }
+}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
index 1ce07ecdab..a8a6456dff 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
+++ b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
@@ -597,6 +597,7 @@ void tst_qqmlxmlhttprequest::send_withdata_data()
QTest::newRow("Incorrect content-type - out of order") << "send_data.4.expect" << "send_data.5.qml";
QTest::newRow("PUT") << "send_data.6.expect" << "send_data.6.qml";
QTest::newRow("Correct content-type - no charset") << "send_data.1.expect" << "send_data.7.qml";
+ QTest::newRow("ArrayBuffer") << "send_data.11.expect" << "send_data.11.qml";
}
void tst_qqmlxmlhttprequest::send_options()
diff --git a/tests/auto/qmltest/BLACKLIST b/tests/auto/qmltest/BLACKLIST
deleted file mode 100644
index 9b39f87219..0000000000
--- a/tests/auto/qmltest/BLACKLIST
+++ /dev/null
@@ -1,16 +0,0 @@
-# Blacklist for testing
-[SelfTests::test_blacklisted_fail]
-*
-[SelfTests::test_blacklistWithData:test2]
-*
-[shadersource-dynamic-sourceobject::test_endresult]
-linux
-[tst_grabImage::test_equals]
-linux
-[ListView::test_listInteractiveCurrentIndexEnforce]
-linux
-osx-10.12
-[TextEdit::test_textentry]
-osx-10.12
-[TextEdit::test_textentry_char]
-osx-10.12
diff --git a/tests/auto/qmltest/animatedimage/animatedimage.pro b/tests/auto/qmltest/animatedimage/animatedimage.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/animatedimage/animatedimage.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/animations/animations.pro b/tests/auto/qmltest/animations/animations.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/animations/animations.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/borderimage/borderimage.pro b/tests/auto/qmltest/borderimage/borderimage.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/borderimage/borderimage.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/buttonclick/buttonclick.pro b/tests/auto/qmltest/buttonclick/buttonclick.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/buttonclick/buttonclick.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/createbenchmark/createbenchmark.pro b/tests/auto/qmltest/createbenchmark/createbenchmark.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/createbenchmark/createbenchmark.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/events/events.pro b/tests/auto/qmltest/events/events.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/events/events.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/fontloader/fontloader.pro b/tests/auto/qmltest/fontloader/fontloader.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/fontloader/fontloader.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/gradient/gradient.pro b/tests/auto/qmltest/gradient/gradient.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/gradient/gradient.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/image/image.pro b/tests/auto/qmltest/image/image.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/image/image.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/itemgrabber/itemgrabber.pro b/tests/auto/qmltest/itemgrabber/itemgrabber.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/itemgrabber/itemgrabber.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml b/tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml
index a80814d6de..53ed3658c2 100644
--- a/tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml
+++ b/tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml
@@ -135,7 +135,7 @@ Item {
property int callCount: 0;
property bool ready: false;
function handleGrab(result) {
- if (!result.saveToFile("itemgrabber/image.png"))
+ if (!result.saveToFile("image.png"))
print("Error: Failed to save image to disk...");
source = "image.png";
ready = true;
@@ -149,7 +149,7 @@ Item {
y: 0
property bool ready: false;
function handleGrab(result) {
- if (!result.saveToFile("itemgrabber/image_small.png"))
+ if (!result.saveToFile("image_small.png"))
print("Error: Failed to save image to disk...");
source = "image_small.png";
ready = true;
diff --git a/tests/auto/qmltest/layout/layout.pro b/tests/auto/qmltest/layout/layout.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/layout/layout.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/listmodel/listmodel.pro b/tests/auto/qmltest/listmodel/listmodel.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/listmodel/listmodel.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/listview/BLACKLIST b/tests/auto/qmltest/listview/BLACKLIST
new file mode 100644
index 0000000000..ffb4f94e2c
--- /dev/null
+++ b/tests/auto/qmltest/listview/BLACKLIST
@@ -0,0 +1,4 @@
+# Blacklist for testing
+[ListView::test_listInteractiveCurrentIndexEnforce]
+linux
+osx-10.12
diff --git a/tests/auto/qmltest/listview/listview.pro b/tests/auto/qmltest/listview/listview.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/listview/listview.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/objectmodel/objectmodel.pro b/tests/auto/qmltest/objectmodel/objectmodel.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/objectmodel/objectmodel.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/pathview/pathview.pro b/tests/auto/qmltest/pathview/pathview.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/pathview/pathview.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/pixel/pixel.pro b/tests/auto/qmltest/pixel/pixel.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/pixel/pixel.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/positioners/positioners.pro b/tests/auto/qmltest/positioners/positioners.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/positioners/positioners.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/qmltest.pro b/tests/auto/qmltest/qmltest.pro
index 52fd6bf9de..8ad1541cbc 100644
--- a/tests/auto/qmltest/qmltest.pro
+++ b/tests/auto/qmltest/qmltest.pro
@@ -1,14 +1,30 @@
-TEMPLATE=app
-TARGET=tst_qmltest
-CONFIG += qmltestcase
-CONFIG += console
-SOURCES += tst_qmltest.cpp
-
-
-importFiles.files = borderimage buttonclick createbenchmark events qqmlbinding selftests
-
-importFiles.path = .
-DEPLOYMENT += importFiles
-
-# Please do not make this test insignificant again, thanks.
-# Just skip those unstable ones. See also QTBUG-33723.
+TEMPLATE = subdirs
+SUBDIRS += \
+ animatedimage \
+ animations \
+ borderimage \
+ buttonclick \
+ createbenchmark \
+ events \
+ fontloader \
+ gradient \
+ image \
+ itemgrabber \
+ layout \
+ listmodel \
+ listview \
+ objectmodel \
+ pathview \
+ pixel \
+ positioners \
+ qqmlbinding \
+ qtbug46798 \
+ rectangle \
+ selftests \
+ shadersource \
+ stability \
+ statemachine \
+ text \
+ textedit \
+ textinput \
+ window
diff --git a/tests/auto/qmltest/qqmlbinding/qqmlbinding.pro b/tests/auto/qmltest/qqmlbinding/qqmlbinding.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/qqmlbinding/qqmlbinding.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/qtbug46798/qtbug46798.pro b/tests/auto/qmltest/qtbug46798/qtbug46798.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/qtbug46798/qtbug46798.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/rectangle/rectangle.pro b/tests/auto/qmltest/rectangle/rectangle.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/rectangle/rectangle.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/selftests/BLACKLIST b/tests/auto/qmltest/selftests/BLACKLIST
new file mode 100644
index 0000000000..ffce42e4c0
--- /dev/null
+++ b/tests/auto/qmltest/selftests/BLACKLIST
@@ -0,0 +1,13 @@
+# Blacklist for testing
+[SelfTests::test_blacklisted_fail]
+*
+[SelfTests::test_blacklistWithData:test2]
+*
+# QTBUG-53793: seems to be failing on Linux a little too often...
+[tst_grabImage::test_equals]
+linux
+[tst_grabImage::test_sizeProps]
+linux
+[tst_grabImage::test_save]
+linux
+
diff --git a/tests/auto/qmltest/selftests/selftests.pro b/tests/auto/qmltest/selftests/selftests.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/selftests/selftests.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/selftests/tst_grabImage.qml b/tests/auto/qmltest/selftests/tst_grabImage.qml
index 1748030f14..7ce7e93a07 100644
--- a/tests/auto/qmltest/selftests/tst_grabImage.qml
+++ b/tests/auto/qmltest/selftests/tst_grabImage.qml
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2017 Crimson AS <info@crimson.no>
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
@@ -35,7 +36,7 @@ TestCase {
when: windowShown
function test_equals() {
- var rect = Qt.createQmlObject("import QtQuick 2.0; Rectangle { color: 'red'; width: 10; height: 10; }", testCase);
+ var rect = createTemporaryQmlObject("import QtQuick 2.0; Rectangle { color: 'red'; width: 10; height: 10; }", testCase);
verify(rect);
var oldImage = grabImage(rect);
rect.width += 10;
@@ -45,9 +46,66 @@ TestCase {
oldImage = grabImage(rect);
// Don't change anything...
newImage = grabImage(rect);
- verify(newImage.equals(oldImage));
+ try {
+ compare(newImage.size, oldImage.size);
+ verify(newImage.equals(oldImage));
+ } catch (ex) {
+ oldImage.save("tst_grabImage_test_equals_oldImage.png")
+ newImage.save("tst_grabImage_test_equals_newImage.png")
+ throw ex;
+ }
verify(!newImage.equals(null));
verify(!newImage.equals(undefined));
}
+
+ function test_sizeProps() {
+ var rect = createTemporaryQmlObject("import QtQuick 2.0; Rectangle { color: 'red'; width: 10; height: 20; }", testCase);
+ var image = grabImage(rect);
+
+ try {
+ compare(image.width, 10)
+ compare(image.height, 20)
+ compare(image.size, Qt.size(10, 20))
+ } catch (ex) {
+ image.save("tst_grabImage_test_sizeProps.png")
+ throw ex;
+ }
+ }
+
+ function test_save() {
+ var rect = createTemporaryQmlObject("import QtQuick 2.0; Rectangle { color: 'red'; width: 10; height: 20; }", testCase);
+ var grabbedImage = grabImage(rect);
+ grabbedImage.save("tst_grabImage_test_save.png")
+
+ // Now try to load it
+ var url = Qt.resolvedUrl("tst_grabImage_test_save.png")
+ var image = createTemporaryQmlObject("import QtQuick 2.0; Image { source: \"" + url + "\" }", testCase);
+ tryCompare(image, "status", Image.Ready)
+ var grabbedImage2 = grabImage(image);
+
+ try {
+ verify(grabbedImage2.equals(grabbedImage))
+ } catch (ex) {
+ grabbedImage2.save("tst_grabImage_test_save2.png")
+ throw ex;
+ }
+ }
+
+ function test_saveThrowsWhenFailing() {
+ var rect = createTemporaryQmlObject("import QtQuick 2.0; Rectangle { color: 'red'; width: 10; height: 20; }", testCase);
+ var grabbedImage = grabImage(rect);
+ var didThrow = false;
+
+ try {
+ // Format doesn't exist, so this will throw
+ grabbedImage.save("tst_grabImage_test_saveThrowsWhenFailing.never-gonna-give-you-up");
+ } catch (ex) {
+ didThrow = true;
+ }
+
+ if (!didThrow) {
+ fail("save() should have thrown, but didn't!")
+ }
+ }
}
diff --git a/tests/auto/qmltest/selftests/tst_selftests.qml b/tests/auto/qmltest/selftests/tst_selftests.qml
index 439ea7a70d..5555876014 100644
--- a/tests/auto/qmltest/selftests/tst_selftests.qml
+++ b/tests/auto/qmltest/selftests/tst_selftests.qml
@@ -167,6 +167,16 @@ TestCase {
caught = true
}
verify(caught)
+
+ caught = false;
+ try {
+ testCase.verify(true, "foo", "bar")
+ } catch (e) {
+ compare(e.message, "QtQuickTest::fail")
+ compare(functions.failmsg, "More than two arguments given to verify(). Did you mean tryVerify() or tryCompare()?")
+ caught = true
+ }
+ verify(caught)
}
function test_compare() {
diff --git a/tests/auto/qmltest/shadersource/BLACKLIST b/tests/auto/qmltest/shadersource/BLACKLIST
new file mode 100644
index 0000000000..cc1e110153
--- /dev/null
+++ b/tests/auto/qmltest/shadersource/BLACKLIST
@@ -0,0 +1,3 @@
+# Blacklist for testing
+[shadersource-dynamic-sourceobject::test_endresult]
+linux
diff --git a/tests/auto/qmltest/shadersource/shadersource.pro b/tests/auto/qmltest/shadersource/shadersource.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/shadersource/shadersource.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/stability/stability.pro b/tests/auto/qmltest/stability/stability.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/stability/stability.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/statemachine/statemachine.pro b/tests/auto/qmltest/statemachine/statemachine.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/statemachine/statemachine.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/text/text.pro b/tests/auto/qmltest/text/text.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/text/text.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/textedit/BLACKLIST b/tests/auto/qmltest/textedit/BLACKLIST
new file mode 100644
index 0000000000..e06cba3e8f
--- /dev/null
+++ b/tests/auto/qmltest/textedit/BLACKLIST
@@ -0,0 +1,6 @@
+# Blacklist for testing
+[TextEdit::test_textentry]
+osx-10.12
+[TextEdit::test_textentry_char]
+osx-10.12
+
diff --git a/tests/auto/qmltest/textedit/textedit.pro b/tests/auto/qmltest/textedit/textedit.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/textedit/textedit.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/textinput/textinput.pro b/tests/auto/qmltest/textinput/textinput.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/textinput/textinput.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/qmltest/tst_qmltest.cpp b/tests/auto/qmltest/tst_qmltest.cpp
deleted file mode 100644
index 3387ce8ee9..0000000000
--- a/tests/auto/qmltest/tst_qmltest.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtQuickTest/quicktest.h>
-QUICK_TEST_MAIN(qmltest) \ No newline at end of file
diff --git a/tests/auto/qmltest/window/window.pro b/tests/auto/qmltest/window/window.pro
new file mode 100644
index 0000000000..a7938e7003
--- /dev/null
+++ b/tests/auto/qmltest/window/window.pro
@@ -0,0 +1 @@
+CONFIG += qmltestcase
diff --git a/tests/auto/quick/examples/tst_examples.cpp b/tests/auto/quick/examples/tst_examples.cpp
index b6742b9efe..d35a2e971a 100644
--- a/tests/auto/quick/examples/tst_examples.cpp
+++ b/tests/auto/quick/examples/tst_examples.cpp
@@ -86,6 +86,8 @@ tst_examples::tst_examples()
excludedDirs << "snippets/qml/visualdatamodel_rootindex";
excludedDirs << "snippets/qml/qtbinding";
excludedDirs << "snippets/qml/imports";
+ excludedFiles << "examples/quick/shapes/content/pathitem.qml"; // relies on resources
+ excludedFiles << "examples/quick/shapes/content/pathiteminteract.qml"; // relies on resources
#ifdef QT_NO_XMLPATTERNS
excludedDirs << "demos/twitter";
diff --git a/tests/auto/quick/nokeywords/tst_nokeywords.cpp b/tests/auto/quick/nokeywords/tst_nokeywords.cpp
index ad77743ddd..e6655589a3 100644
--- a/tests/auto/quick/nokeywords/tst_nokeywords.cpp
+++ b/tests/auto/quick/nokeywords/tst_nokeywords.cpp
@@ -55,7 +55,6 @@
#include <QtQuick/private/qsgdefaultinternalrectanglenode_p.h>
#include <QtQuick/private/qsgdepthstencilbuffer_p.h>
#include <QtQuick/private/qsgdistancefieldglyphnode_p.h>
-#include <QtQuick/private/qsgdistancefieldutil_p.h>
#endif
#include <QtQuick/private/qsggeometry_p.h>
#include <QtQuick/private/qsgnode_p.h>
diff --git a/tests/auto/quick/qquickapplication/data/tst_platformname.qml b/tests/auto/quick/qquickapplication/data/tst_platformname.qml
new file mode 100644
index 0000000000..1bcd66ac8d
--- /dev/null
+++ b/tests/auto/quick/qquickapplication/data/tst_platformname.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.0;
+
+Item {
+ id: root;
+ property string platformName: Qt.platform.pluginName
+}
diff --git a/tests/auto/quick/qquickapplication/qquickapplication.pro b/tests/auto/quick/qquickapplication/qquickapplication.pro
index c47f5472b7..00b5bb3a18 100644
--- a/tests/auto/quick/qquickapplication/qquickapplication.pro
+++ b/tests/auto/quick/qquickapplication/qquickapplication.pro
@@ -3,7 +3,8 @@ TARGET = tst_qquickapplication
macx:CONFIG -= app_bundle
SOURCES += tst_qquickapplication.cpp
-OTHER_FILES += data/tst_displayname.qml
+OTHER_FILES += data/tst_displayname.qml \
+ data/tst_platformname.qml
include (../../shared/util.pri)
diff --git a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
index d780b91260..e428a1fc6e 100644
--- a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
+++ b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
@@ -53,6 +53,7 @@ private slots:
void styleHints();
void cleanup();
void displayName();
+ void platformName();
private:
QQmlEngine engine;
@@ -264,6 +265,24 @@ void tst_qquickapplication::displayName()
QCOMPARE(QGuiApplication::applicationDisplayName(), name[2]);
}
+void tst_qquickapplication::platformName()
+{
+ // Set up QML component
+ QQmlComponent component(&engine, testFileUrl("tst_platformname.qml"));
+ QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
+ QVERIFY(item);
+ QQuickView view;
+ item->setParentItem(view.rootObject());
+
+ // Get native platform name
+ QString guiApplicationPlatformName = QGuiApplication::platformName();
+ QVERIFY(!guiApplicationPlatformName.isEmpty());
+
+ // Get platform name from QML component and verify it's same
+ QString qmlPlatformName = qvariant_cast<QString>(item->property("platformName"));
+ QCOMPARE(qmlPlatformName, guiApplicationPlatformName);
+}
+
QTEST_MAIN(tst_qquickapplication)
#include "tst_qquickapplication.moc"
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index f8277c6895..ef6e444580 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -2216,6 +2216,7 @@ Q_DECLARE_METATYPE(QQuickFlickable::BoundsBehavior)
void tst_qquickflickable::overshoot()
{
QFETCH(QQuickFlickable::BoundsBehavior, boundsBehavior);
+ QFETCH(int, boundsMovement);
QScopedPointer<QQuickView> window(new QQuickView);
window->setSource(testFileUrl("overshoot.qml"));
@@ -2232,6 +2233,7 @@ void tst_qquickflickable::overshoot()
QCOMPARE(flickable->contentHeight(), 400.0);
flickable->setBoundsBehavior(boundsBehavior);
+ flickable->setBoundsMovement(QQuickFlickable::BoundsMovement(boundsMovement));
// drag past the beginning
QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(10, 10));
@@ -2240,23 +2242,30 @@ void tst_qquickflickable::overshoot()
QTest::mouseMove(window.data(), QPoint(40, 40));
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(50, 50));
+ if ((boundsMovement == QQuickFlickable::FollowBoundsBehavior) && (boundsBehavior & QQuickFlickable::DragOverBounds)) {
+ QVERIFY(flickable->property("minContentX").toReal() < 0.0);
+ QVERIFY(flickable->property("minContentY").toReal() < 0.0);
+ } else {
+ QCOMPARE(flickable->property("minContentX").toReal(), 0.0);
+ QCOMPARE(flickable->property("minContentY").toReal(), 0.0);
+ }
if (boundsBehavior & QQuickFlickable::DragOverBounds) {
- QVERIFY(flickable->property("minVerticalOvershoot").toReal() < 0.0);
QVERIFY(flickable->property("minHorizontalOvershoot").toReal() < 0.0);
- QCOMPARE(flickable->property("minContentY").toReal(),
- flickable->property("minVerticalOvershoot").toReal());
- QCOMPARE(flickable->property("minContentX").toReal(),
- flickable->property("minHorizontalOvershoot").toReal());
+ QVERIFY(flickable->property("minVerticalOvershoot").toReal() < 0.0);
} else {
- QCOMPARE(flickable->property("minContentY").toReal(), 0.0);
- QCOMPARE(flickable->property("minContentX").toReal(), 0.0);
- QCOMPARE(flickable->property("minVerticalOvershoot").toReal(), 0.0);
QCOMPARE(flickable->property("minHorizontalOvershoot").toReal(), 0.0);
+ QCOMPARE(flickable->property("minVerticalOvershoot").toReal(), 0.0);
+ }
+ if (bool(boundsMovement == QQuickFlickable::FollowBoundsBehavior) == bool(boundsBehavior & QQuickFlickable::DragOverBounds)) {
+ QCOMPARE(flickable->property("minContentX").toReal(),
+ flickable->property("minHorizontalOvershoot").toReal());
+ QCOMPARE(flickable->property("minContentY").toReal(),
+ flickable->property("minVerticalOvershoot").toReal());
}
- QCOMPARE(flickable->property("maxContentY").toReal(), 0.0);
QCOMPARE(flickable->property("maxContentX").toReal(), 0.0);
- QCOMPARE(flickable->property("maxVerticalOvershoot").toReal(), 0.0);
+ QCOMPARE(flickable->property("maxContentY").toReal(), 0.0);
QCOMPARE(flickable->property("maxHorizontalOvershoot").toReal(), 0.0);
+ QCOMPARE(flickable->property("maxVerticalOvershoot").toReal(), 0.0);
flickable->setContentX(20.0);
flickable->setContentY(20.0);
@@ -2266,23 +2275,30 @@ void tst_qquickflickable::overshoot()
flick(window.data(), QPoint(10, 10), QPoint(50, 50), 100);
QTRY_VERIFY(!flickable->property("flicking").toBool());
+ if ((boundsMovement == QQuickFlickable::FollowBoundsBehavior) && (boundsBehavior & QQuickFlickable::OvershootBounds)) {
+ QVERIFY(flickable->property("minContentX").toReal() < 0.0);
+ QVERIFY(flickable->property("minContentY").toReal() < 0.0);
+ } else {
+ QCOMPARE(flickable->property("minContentX").toReal(), 0.0);
+ QCOMPARE(flickable->property("minContentY").toReal(), 0.0);
+ }
if (boundsBehavior & QQuickFlickable::OvershootBounds) {
- QVERIFY(flickable->property("minVerticalOvershoot").toReal() < 0.0);
QVERIFY(flickable->property("minHorizontalOvershoot").toReal() < 0.0);
- QCOMPARE(flickable->property("minContentY").toReal(),
- flickable->property("minVerticalOvershoot").toReal());
- QCOMPARE(flickable->property("minContentX").toReal(),
- flickable->property("minHorizontalOvershoot").toReal());
+ QVERIFY(flickable->property("minVerticalOvershoot").toReal() < 0.0);
} else {
- QCOMPARE(flickable->property("minContentY").toReal(), 0.0);
- QCOMPARE(flickable->property("minContentX").toReal(), 0.0);
- QCOMPARE(flickable->property("minVerticalOvershoot").toReal(), 0.0);
QCOMPARE(flickable->property("minHorizontalOvershoot").toReal(), 0.0);
+ QCOMPARE(flickable->property("minVerticalOvershoot").toReal(), 0.0);
+ }
+ if ((boundsMovement == QQuickFlickable::FollowBoundsBehavior) == (boundsBehavior & QQuickFlickable::OvershootBounds)) {
+ QCOMPARE(flickable->property("minContentX").toReal(),
+ flickable->property("minHorizontalOvershoot").toReal());
+ QCOMPARE(flickable->property("minContentY").toReal(),
+ flickable->property("minVerticalOvershoot").toReal());
}
- QCOMPARE(flickable->property("maxContentY").toReal(), 20.0);
QCOMPARE(flickable->property("maxContentX").toReal(), 20.0);
- QCOMPARE(flickable->property("maxVerticalOvershoot").toReal(), 0.0);
+ QCOMPARE(flickable->property("maxContentY").toReal(), 20.0);
QCOMPARE(flickable->property("maxHorizontalOvershoot").toReal(), 0.0);
+ QCOMPARE(flickable->property("maxVerticalOvershoot").toReal(), 0.0);
flickable->setContentX(200.0);
flickable->setContentY(200.0);
@@ -2295,23 +2311,30 @@ void tst_qquickflickable::overshoot()
QTest::mouseMove(window.data(), QPoint(20, 20));
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(10, 10));
+ if ((boundsMovement == QQuickFlickable::FollowBoundsBehavior) && (boundsBehavior & QQuickFlickable::DragOverBounds)) {
+ QVERIFY(flickable->property("maxContentX").toReal() > 200.0);
+ QVERIFY(flickable->property("maxContentX").toReal() > 200.0);
+ } else {
+ QCOMPARE(flickable->property("maxContentX").toReal(), 200.0);
+ QCOMPARE(flickable->property("maxContentY").toReal(), 200.0);
+ }
if (boundsBehavior & QQuickFlickable::DragOverBounds) {
- QVERIFY(flickable->property("maxVerticalOvershoot").toReal() > 0.0);
QVERIFY(flickable->property("maxHorizontalOvershoot").toReal() > 0.0);
- QCOMPARE(flickable->property("maxContentY").toReal() - 200.0,
- flickable->property("maxVerticalOvershoot").toReal());
- QCOMPARE(flickable->property("maxContentX").toReal() - 200.0,
- flickable->property("maxHorizontalOvershoot").toReal());
+ QVERIFY(flickable->property("maxVerticalOvershoot").toReal() > 0.0);
} else {
- QCOMPARE(flickable->property("maxContentY").toReal(), 200.0);
- QCOMPARE(flickable->property("maxContentX").toReal(), 200.0);
- QCOMPARE(flickable->property("maxVerticalOvershoot").toReal(), 0.0);
QCOMPARE(flickable->property("maxHorizontalOvershoot").toReal(), 0.0);
+ QCOMPARE(flickable->property("maxVerticalOvershoot").toReal(), 0.0);
+ }
+ if ((boundsMovement == QQuickFlickable::FollowBoundsBehavior) == (boundsBehavior & QQuickFlickable::DragOverBounds)) {
+ QCOMPARE(flickable->property("maxContentX").toReal() - 200.0,
+ flickable->property("maxHorizontalOvershoot").toReal());
+ QCOMPARE(flickable->property("maxContentY").toReal() - 200.0,
+ flickable->property("maxVerticalOvershoot").toReal());
}
- QCOMPARE(flickable->property("minContentY").toReal(), 200.0);
QCOMPARE(flickable->property("minContentX").toReal(), 200.0);
- QCOMPARE(flickable->property("minVerticalOvershoot").toReal(), 0.0);
+ QCOMPARE(flickable->property("minContentY").toReal(), 200.0);
QCOMPARE(flickable->property("minHorizontalOvershoot").toReal(), 0.0);
+ QCOMPARE(flickable->property("minVerticalOvershoot").toReal(), 0.0);
flickable->setContentX(180.0);
flickable->setContentY(180.0);
@@ -2321,37 +2344,59 @@ void tst_qquickflickable::overshoot()
flick(window.data(), QPoint(50, 50), QPoint(10, 10), 100);
QTRY_VERIFY(!flickable->property("flicking").toBool());
+ if ((boundsMovement == QQuickFlickable::FollowBoundsBehavior) && (boundsBehavior & QQuickFlickable::OvershootBounds)) {
+ QVERIFY(flickable->property("maxContentX").toReal() > 200.0);
+ QVERIFY(flickable->property("maxContentY").toReal() > 200.0);
+ } else {
+ QCOMPARE(flickable->property("maxContentX").toReal(), 200.0);
+ QCOMPARE(flickable->property("maxContentY").toReal(), 200.0);
+ }
if (boundsBehavior & QQuickFlickable::OvershootBounds) {
- QVERIFY(flickable->property("maxVerticalOvershoot").toReal() > 0.0);
QVERIFY(flickable->property("maxHorizontalOvershoot").toReal() > 0.0);
- QCOMPARE(flickable->property("maxContentY").toReal() - 200.0,
- flickable->property("maxVerticalOvershoot").toReal());
- QCOMPARE(flickable->property("maxContentX").toReal() - 200.0,
- flickable->property("maxHorizontalOvershoot").toReal());
+ QVERIFY(flickable->property("maxVerticalOvershoot").toReal() > 0.0);
} else {
- QCOMPARE(flickable->property("maxContentY").toReal(), 200.0);
- QCOMPARE(flickable->property("maxContentX").toReal(), 200.0);
- QCOMPARE(flickable->property("maxVerticalOvershoot").toReal(), 0.0);
QCOMPARE(flickable->property("maxHorizontalOvershoot").toReal(), 0.0);
+ QCOMPARE(flickable->property("maxVerticalOvershoot").toReal(), 0.0);
+ }
+ if ((boundsMovement == QQuickFlickable::FollowBoundsBehavior) == (boundsBehavior & QQuickFlickable::OvershootBounds)) {
+ QCOMPARE(flickable->property("maxContentX").toReal() - 200.0,
+ flickable->property("maxHorizontalOvershoot").toReal());
+ QCOMPARE(flickable->property("maxContentY").toReal() - 200.0,
+ flickable->property("maxVerticalOvershoot").toReal());
}
- QCOMPARE(flickable->property("minContentY").toReal(), 180.0);
QCOMPARE(flickable->property("minContentX").toReal(), 180.0);
- QCOMPARE(flickable->property("minVerticalOvershoot").toReal(), 0.0);
+ QCOMPARE(flickable->property("minContentY").toReal(), 180.0);
QCOMPARE(flickable->property("minHorizontalOvershoot").toReal(), 0.0);
+ QCOMPARE(flickable->property("minVerticalOvershoot").toReal(), 0.0);
}
void tst_qquickflickable::overshoot_data()
{
QTest::addColumn<QQuickFlickable::BoundsBehavior>("boundsBehavior");
-
- QTest::newRow("StopAtBounds")
- << QQuickFlickable::BoundsBehavior(QQuickFlickable::StopAtBounds);
- QTest::newRow("DragOverBounds")
- << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragOverBounds);
- QTest::newRow("OvershootBounds")
- << QQuickFlickable::BoundsBehavior(QQuickFlickable::OvershootBounds);
- QTest::newRow("DragAndOvershootBounds")
- << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragAndOvershootBounds);
+ QTest::addColumn<int>("boundsMovement");
+
+ QTest::newRow("StopAtBounds,FollowBoundsBehavior")
+ << QQuickFlickable::BoundsBehavior(QQuickFlickable::StopAtBounds)
+ << int(QQuickFlickable::FollowBoundsBehavior);
+ QTest::newRow("DragOverBounds,FollowBoundsBehavior")
+ << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragOverBounds)
+ << int(QQuickFlickable::FollowBoundsBehavior);
+ QTest::newRow("OvershootBounds,FollowBoundsBehavior")
+ << QQuickFlickable::BoundsBehavior(QQuickFlickable::OvershootBounds)
+ << int(QQuickFlickable::FollowBoundsBehavior);
+ QTest::newRow("DragAndOvershootBounds,FollowBoundsBehavior")
+ << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragAndOvershootBounds)
+ << int(QQuickFlickable::FollowBoundsBehavior);
+
+ QTest::newRow("DragOverBounds,StopAtBounds")
+ << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragOverBounds)
+ << int(QQuickFlickable::StopAtBounds);
+ QTest::newRow("OvershootBounds,StopAtBounds")
+ << QQuickFlickable::BoundsBehavior(QQuickFlickable::OvershootBounds)
+ << int(QQuickFlickable::StopAtBounds);
+ QTest::newRow("DragAndOvershootBounds,StopAtBounds")
+ << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragAndOvershootBounds)
+ << int(QQuickFlickable::StopAtBounds);
}
void tst_qquickflickable::overshoot_reentrant()
diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
index 115fe53430..a2a65aa803 100644
--- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp
+++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
@@ -91,6 +91,8 @@ private slots:
void sourceSizeChanges();
void correctStatus();
void highdpi();
+ void highDpiFillModesAndSizes_data();
+ void highDpiFillModesAndSizes();
void hugeImages();
private:
@@ -971,6 +973,65 @@ void tst_qquickimage::highdpi()
delete obj;
}
+void tst_qquickimage::highDpiFillModesAndSizes_data()
+{
+ QTest::addColumn<QQuickImage::FillMode>("fillMode");
+ QTest::addColumn<qreal>("expectedHeightAfterSettingWidthTo100");
+ QTest::addColumn<qreal>("expectedImplicitHeightAfterSettingWidthTo100");
+ QTest::addColumn<qreal>("expectedPaintedWidthAfterSettingWidthTo100");
+ QTest::addColumn<qreal>("expectedPaintedHeightAfterSettingWidthTo100");
+
+ QTest::addRow("Stretch") << QQuickImage::Stretch << 150.0 << 150.0 << 100.0 << 150.0;
+ QTest::addRow("PreserveAspectFit") << QQuickImage::PreserveAspectFit << 100.0 << 100.0 << 100.0 << 100.0;
+ QTest::addRow("PreserveAspectCrop") << QQuickImage::PreserveAspectCrop << 150.0 << 150.0 << 150.0 << 150.0;
+ QTest::addRow("Tile") << QQuickImage::Tile << 150.0 << 150.0 << 100.0 << 150.0;
+ QTest::addRow("TileVertically") << QQuickImage::TileVertically << 150.0 << 150.0 << 100.0 << 150.0;
+ QTest::addRow("TileHorizontally") << QQuickImage::TileHorizontally << 150.0 << 150.0 << 100.0 << 150.0;
+ QTest::addRow("Pad") << QQuickImage::Pad << 150.0 << 150.0 << 150.0 << 150.0;
+}
+
+void tst_qquickimage::highDpiFillModesAndSizes()
+{
+ QFETCH(QQuickImage::FillMode, fillMode);
+ QFETCH(qreal, expectedHeightAfterSettingWidthTo100);
+ QFETCH(qreal, expectedImplicitHeightAfterSettingWidthTo100);
+ QFETCH(qreal, expectedPaintedWidthAfterSettingWidthTo100);
+ QFETCH(qreal, expectedPaintedHeightAfterSettingWidthTo100);
+
+ QString componentStr = "import QtQuick 2.0\nImage { source: srcImage; }";
+ QQmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+
+ engine.rootContext()->setContextProperty("srcImage", testFileUrl("heart-highdpi@2x.png"));
+
+ QScopedPointer<QQuickImage> image(qobject_cast<QQuickImage*>(component.create()));
+ QVERIFY(image);
+ QCOMPARE(image->width(), 150.0);
+ QCOMPARE(image->height(), 150.0);
+ QCOMPARE(image->paintedWidth(), 150.0);
+ QCOMPARE(image->paintedHeight(), 150.0);
+ QCOMPARE(image->implicitWidth(), 150.0);
+ QCOMPARE(image->implicitHeight(), 150.0);
+ QCOMPARE(image->paintedWidth(), 150.0);
+ QCOMPARE(image->paintedHeight(), 150.0);
+
+ // The implicit size should not change when setting any fillMode here.
+ image->setFillMode(fillMode);
+ QCOMPARE(image->fillMode(), fillMode);
+ QCOMPARE(image->implicitWidth(), 150.0);
+ QCOMPARE(image->implicitHeight(), 150.0);
+ QCOMPARE(image->paintedWidth(), 150.0);
+ QCOMPARE(image->paintedHeight(), 150.0);
+
+ image->setWidth(100.0);
+ QCOMPARE(image->width(), 100.0);
+ QCOMPARE(image->height(), expectedHeightAfterSettingWidthTo100);
+ QCOMPARE(image->implicitWidth(), 150.0);
+ QCOMPARE(image->implicitHeight(), expectedImplicitHeightAfterSettingWidthTo100);
+ QCOMPARE(image->paintedWidth(), expectedPaintedWidthAfterSettingWidthTo100);
+ QCOMPARE(image->paintedHeight(), expectedPaintedHeightAfterSettingWidthTo100);
+}
+
void tst_qquickimage::hugeImages()
{
QQuickView view;
diff --git a/tests/auto/quick/qquickrectangle/data/gradient-multiple.qml b/tests/auto/quick/qquickrectangle/data/gradient-multiple.qml
new file mode 100644
index 0000000000..d58c857008
--- /dev/null
+++ b/tests/auto/quick/qquickrectangle/data/gradient-multiple.qml
@@ -0,0 +1,30 @@
+import QtQuick 2.0
+
+Item {
+ property alias firstRectangle: r1
+ property alias secondRectangle: r2
+ Rectangle {
+ id: r1
+ gradient: someObject.someGradient
+ anchors.fill: parent
+ }
+ Rectangle {
+ id: r2
+ gradient: someObject.someGradient
+ anchors.fill: parent
+ }
+
+ function changeGradient() {
+ firstStop.color = "red"
+ secondStop.color = "blue"
+ }
+
+ QtObject {
+ id: someObject
+ property Gradient someGradient: Gradient {
+ GradientStop { id: firstStop; position: 0.0; color: "gray" }
+ GradientStop { id: secondStop; position: 1.0; color: "white" }
+ }
+ }
+}
+
diff --git a/tests/auto/quick/qquickrectangle/data/gradient-separate.qml b/tests/auto/quick/qquickrectangle/data/gradient-separate.qml
new file mode 100644
index 0000000000..8ae3f3296b
--- /dev/null
+++ b/tests/auto/quick/qquickrectangle/data/gradient-separate.qml
@@ -0,0 +1,20 @@
+import QtQuick 2.0
+
+Rectangle {
+
+ function changeGradient() {
+ firstStop.color = "red"
+ secondStop.color = "blue"
+ }
+
+ QtObject {
+ id: someObject
+ property Gradient someGradient: Gradient {
+ GradientStop { id: firstStop; position: 0.0; color: "gray" }
+ GradientStop { id: secondStop; position: 1.0; color: "white" }
+ }
+ }
+
+ gradient: someObject.someGradient
+}
+
diff --git a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
index 65c7e387a0..0d79592e37 100644
--- a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
+++ b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
@@ -32,6 +32,7 @@
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQuick/qquickview.h>
+#include <private/qquickitem_p.h>
#include <private/qquickrectangle_p.h>
#include "../../shared/util.h"
@@ -46,6 +47,8 @@ private slots:
void color();
void gradient();
void gradient_border();
+ void gradient_separate();
+ void gradient_multiple();
void antialiasing();
private:
@@ -111,6 +114,62 @@ void tst_qquickrectangle::gradient_border()
QVERIFY(QTest::qWaitForWindowExposed(&view));
}
+// A gradient not defined inline with the Rectangle using it should still change
+// that Rectangle.
+void tst_qquickrectangle::gradient_separate()
+{
+ QQuickView view;
+ view.setSource(testFileUrl("gradient-separate.qml"));
+ view.show();
+
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(view.rootObject());
+ QVERIFY(rect);
+
+ // Start off clean
+ QQuickItemPrivate *rectPriv = QQuickItemPrivate::get(rect);
+ bool isDirty = rectPriv->dirtyAttributes & QQuickItemPrivate::Content;
+ QVERIFY(!isDirty);
+
+ QMetaObject::invokeMethod(rect, "changeGradient");
+
+ // Changing the gradient should have scheduled an update of the item.
+ isDirty = rectPriv->dirtyAttributes & QQuickItemPrivate::Content;
+ QVERIFY(isDirty);
+}
+
+// When a gradient is changed, every Rectangle connected to it must update.
+void tst_qquickrectangle::gradient_multiple()
+{
+ QQuickView view;
+ view.setSource(testFileUrl("gradient-multiple.qml"));
+ view.show();
+
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+ QQuickRectangle *firstRect = qobject_cast<QQuickRectangle*>(view.rootObject()->property("firstRectangle").value<QObject*>());
+ QQuickRectangle *secondRect = qobject_cast<QQuickRectangle*>(view.rootObject()->property("secondRectangle").value<QObject*>());
+ QVERIFY(firstRect);
+ QVERIFY(secondRect);
+
+ // Start off clean
+ QQuickItemPrivate *firstRectPriv = QQuickItemPrivate::get(firstRect);
+ QQuickItemPrivate *secondRectPriv = QQuickItemPrivate::get(secondRect);
+ bool firstIsDirty = firstRectPriv->dirtyAttributes & QQuickItemPrivate::Content;
+ bool secondIsDirty = secondRectPriv->dirtyAttributes & QQuickItemPrivate::Content;
+ QVERIFY(!firstIsDirty);
+ QVERIFY(!secondIsDirty);
+
+ QMetaObject::invokeMethod(view.rootObject(), "changeGradient");
+
+ // Changing the gradient should have scheduled an update of both items
+ firstIsDirty = firstRectPriv->dirtyAttributes & QQuickItemPrivate::Content;
+ secondIsDirty = secondRectPriv->dirtyAttributes & QQuickItemPrivate::Content;
+ QVERIFY(firstIsDirty);
+ QVERIFY(secondIsDirty);
+}
+
void tst_qquickrectangle::antialiasing()
{
QQmlComponent component(&engine);
diff --git a/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp b/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp
index 26b687a4a6..0a3796402a 100644
--- a/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp
+++ b/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp
@@ -113,6 +113,9 @@ void tst_qquickscreen::fullScreenList()
QQuickScreenInfo *info = qobject_cast<QQuickScreenInfo *>(screensArray.property(i).toQObject());
QVERIFY(info != nullptr);
QCOMPARE(screenList[i]->name(), info->name());
+ QCOMPARE(screenList[i]->manufacturer(), info->manufacturer());
+ QCOMPARE(screenList[i]->model(), info->model());
+ QCOMPARE(screenList[i]->serialNumber(), info->serialNumber());
QCOMPARE(screenList[i]->size().width(), info->width());
QCOMPARE(screenList[i]->size().height(), info->height());
QCOMPARE(screenList[i]->availableVirtualGeometry().width(), info->desktopAvailableWidth());
diff --git a/tests/auto/quick/qquickshape/data/pathitem1.qml b/tests/auto/quick/qquickshape/data/pathitem1.qml
new file mode 100644
index 0000000000..29ca67b0bb
--- /dev/null
+++ b/tests/auto/quick/qquickshape/data/pathitem1.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.9
+import tst_qquickpathitem 1.0
+
+Shape {
+}
diff --git a/tests/auto/quick/qquickshape/data/pathitem2.qml b/tests/auto/quick/qquickshape/data/pathitem2.qml
new file mode 100644
index 0000000000..a255a37af6
--- /dev/null
+++ b/tests/auto/quick/qquickshape/data/pathitem2.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.9
+import tst_qquickpathitem 1.0
+
+Shape {
+ ShapePath { }
+ ShapePath { }
+}
diff --git a/tests/auto/quick/qquickshape/data/pathitem3.png b/tests/auto/quick/qquickshape/data/pathitem3.png
new file mode 100644
index 0000000000..a8b4483c96
--- /dev/null
+++ b/tests/auto/quick/qquickshape/data/pathitem3.png
Binary files differ
diff --git a/tests/auto/quick/qquickshape/data/pathitem3.qml b/tests/auto/quick/qquickshape/data/pathitem3.qml
new file mode 100644
index 0000000000..8328f2fc33
--- /dev/null
+++ b/tests/auto/quick/qquickshape/data/pathitem3.qml
@@ -0,0 +1,33 @@
+import QtQuick 2.9
+import tst_qquickpathitem 1.0
+
+Item {
+ width: 200
+ height: 150
+
+ Shape {
+ vendorExtensionsEnabled: false
+ objectName: "pathItem"
+ anchors.fill: parent
+
+ ShapePath {
+ strokeWidth: 4
+ strokeColor: "red"
+ fillGradient: LinearGradient {
+ x1: 20; y1: 20
+ x2: 180; y2: 130
+ GradientStop { position: 0; color: "blue" }
+ GradientStop { position: 0.2; color: "green" }
+ GradientStop { position: 0.4; color: "red" }
+ GradientStop { position: 0.6; color: "yellow" }
+ GradientStop { position: 1; color: "cyan" }
+ }
+ strokeStyle: ShapePath.DashLine
+ dashPattern: [ 1, 4 ]
+ startX: 20; startY: 20
+ PathLine { x: 180; y: 130 }
+ PathLine { x: 20; y: 130 }
+ PathLine { x: 20; y: 20 }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickshape/data/pathitem4.png b/tests/auto/quick/qquickshape/data/pathitem4.png
new file mode 100644
index 0000000000..3a988ba249
--- /dev/null
+++ b/tests/auto/quick/qquickshape/data/pathitem4.png
Binary files differ
diff --git a/tests/auto/quick/qquickshape/data/pathitem4.qml b/tests/auto/quick/qquickshape/data/pathitem4.qml
new file mode 100644
index 0000000000..635113416f
--- /dev/null
+++ b/tests/auto/quick/qquickshape/data/pathitem4.qml
@@ -0,0 +1,56 @@
+import QtQuick 2.9
+import tst_qquickpathitem 1.0
+
+Item {
+ width: 200
+ height: 150
+
+ Shape {
+ vendorExtensionsEnabled: false
+ objectName: "pathItem"
+ anchors.fill: parent
+
+ ShapePath {
+ strokeColor: "red"
+ fillColor: "green"
+ startX: 40; startY: 30
+ PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 }
+ PathLine { x: 150; y: 80 }
+ PathQuad { x: 160; y: 30; controlX: 200; controlY: 80 }
+ }
+
+ ShapePath {
+ strokeWidth: 10
+ fillColor: "transparent"
+ strokeColor: "blue"
+ startX: 40; startY: 30
+ PathCubic { x: 50; y: 80; control1X: 0; control1Y: 80; control2X: 100; control2Y: 100 }
+ }
+
+ ShapePath {
+ fillGradient: LinearGradient {
+ y2: 150
+ GradientStop { position: 0; color: "yellow" }
+ GradientStop { position: 1; color: "green" }
+ }
+
+ startX: 10; startY: 100
+ PathArc {
+ relativeX: 50; y: 100
+ radiusX: 25; radiusY: 25
+ }
+ PathArc {
+ relativeX: 50; y: 100
+ radiusX: 25; radiusY: 35
+ }
+ PathArc {
+ relativeX: 50; y: 100
+ radiusX: 25; radiusY: 60
+ }
+ PathArc {
+ relativeX: 50; y: 100
+ radiusX: 50; radiusY: 120
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickshape/qquickshape.pro b/tests/auto/quick/qquickshape/qquickshape.pro
new file mode 100644
index 0000000000..29c3502b86
--- /dev/null
+++ b/tests/auto/quick/qquickshape/qquickshape.pro
@@ -0,0 +1,35 @@
+CONFIG += testcase
+TARGET = tst_qquickshape
+macos:CONFIG -= app_bundle
+
+SOURCES += tst_qquickshape.cpp
+
+include (../../shared/util.pri)
+include (../shared/util.pri)
+
+TESTDATA = data/*
+
+HEADERS += \
+ ../../../../src/imports/shapes/qquickshape_p.h \
+ ../../../../src/imports/shapes/qquickshape_p_p.h \
+ ../../../../src/imports/shapes/qquickshapegenericrenderer_p.h \
+ ../../../../src/imports/shapes/qquickshapesoftwarerenderer_p.h
+
+SOURCES += \
+ ../../../../src/imports/shapes/qquickshape.cpp \
+ ../../../../src/imports/shapes/qquickshapegenericrenderer.cpp \
+ ../../../../src/imports/shapes/qquickshapesoftwarerenderer.cpp
+
+qtConfig(opengl) {
+ HEADERS += \
+ ../../../../src/imports/shapes/qquicknvprfunctions_p.h \
+ ../../../../src/imports/shapes/qquicknvprfunctions_p_p.h \
+ ../../../../src/imports/shapes/qquickshapenvprrenderer_p.h
+
+ SOURCES += \
+ ../../../../src/imports/shapes/qquicknvprfunctions.cpp \
+ ../../../../src/imports/shapes/qquickshapenvprrenderer.cpp
+}
+
+QT += core-private gui-private qml-private quick-private testlib
+qtHaveModule(widgets): QT += widgets
diff --git a/tests/auto/quick/qquickshape/tst_qquickshape.cpp b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
new file mode 100644
index 0000000000..dcc79e6599
--- /dev/null
+++ b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
@@ -0,0 +1,250 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtQuick/qquickview.h>
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlexpression.h>
+#include <QtQml/qqmlincubator.h>
+#include "../../../../src/imports/shapes/qquickshape_p.h"
+
+#include "../../shared/util.h"
+#include "../shared/viewtestutil.h"
+#include "../shared/visualtestutil.h"
+
+using namespace QQuickViewTestUtil;
+using namespace QQuickVisualTestUtil;
+
+class tst_QQuickShape : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_QQuickShape();
+
+private slots:
+ void initValues();
+ void vpInitValues();
+ void basicShape();
+ void changeSignals();
+ void render();
+ void renderWithMultipleSp();
+};
+
+tst_QQuickShape::tst_QQuickShape()
+{
+ // Force the software backend to get reliable rendering results regardless of the hw and drivers.
+ QQuickWindow::setSceneGraphBackend(QSGRendererInterface::Software);
+
+ const char *uri = "tst_qquickpathitem";
+ qmlRegisterType<QQuickShape>(uri, 1, 0, "Shape");
+ qmlRegisterType<QQuickShapePath>(uri, 1, 0, "ShapePath");
+ qmlRegisterUncreatableType<QQuickShapeGradient>(uri, 1, 0, "ShapeGradient", QQuickShapeGradient::tr("ShapeGradient is an abstract base class"));
+ qmlRegisterType<QQuickShapeLinearGradient>(uri, 1, 0, "LinearGradient");
+}
+
+void tst_QQuickShape::initValues()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("pathitem1.qml"));
+ QQuickShape *obj = qobject_cast<QQuickShape *>(c.create());
+
+ QVERIFY(obj != nullptr);
+ QVERIFY(obj->rendererType() == QQuickShape::UnknownRenderer);
+ QVERIFY(!obj->asynchronous());
+ QVERIFY(obj->vendorExtensionsEnabled());
+ QVERIFY(obj->status() == QQuickShape::Null);
+ auto vps = obj->data();
+ QVERIFY(vps.count(&vps) == 0);
+
+ delete obj;
+}
+
+void tst_QQuickShape::vpInitValues()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("pathitem2.qml"));
+ QQuickShape *obj = qobject_cast<QQuickShape *>(c.create());
+
+ QVERIFY(obj != nullptr);
+ QVERIFY(obj->rendererType() == QQuickShape::UnknownRenderer);
+ QVERIFY(!obj->asynchronous());
+ QVERIFY(obj->vendorExtensionsEnabled());
+ QVERIFY(obj->status() == QQuickShape::Null);
+ auto vps = obj->data();
+ QVERIFY(vps.count(&vps) == 2);
+
+ QQuickShapePath *vp = qobject_cast<QQuickShapePath *>(vps.at(&vps, 0));
+ QVERIFY(vp != nullptr);
+ QQmlListReference pathList(vp, "pathElements");
+ QCOMPARE(pathList.count(), 0);
+ QCOMPARE(vp->strokeColor(), QColor(Qt::white));
+ QCOMPARE(vp->strokeWidth(), 1.0f);
+ QCOMPARE(vp->fillColor(), QColor(Qt::white));
+ QCOMPARE(vp->fillRule(), QQuickShapePath::OddEvenFill);
+ QCOMPARE(vp->joinStyle(), QQuickShapePath::BevelJoin);
+ QCOMPARE(vp->miterLimit(), 2);
+ QCOMPARE(vp->capStyle(), QQuickShapePath::SquareCap);
+ QCOMPARE(vp->strokeStyle(), QQuickShapePath::SolidLine);
+ QCOMPARE(vp->dashOffset(), 0.0f);
+ QCOMPARE(vp->dashPattern(), QVector<qreal>() << 4 << 2);
+ QVERIFY(!vp->fillGradient());
+
+ delete obj;
+}
+
+void tst_QQuickShape::basicShape()
+{
+ QScopedPointer<QQuickView> window(createView());
+
+ window->setSource(testFileUrl("pathitem3.qml"));
+ qApp->processEvents();
+
+ QQuickShape *obj = findItem<QQuickShape>(window->rootObject(), "pathItem");
+ QVERIFY(obj != nullptr);
+ QQmlListReference list(obj, "data");
+ QCOMPARE(list.count(), 1);
+ QQuickShapePath *vp = qobject_cast<QQuickShapePath *>(list.at(0));
+ QVERIFY(vp != nullptr);
+ QCOMPARE(vp->strokeWidth(), 4.0f);
+ QVERIFY(vp->fillGradient() != nullptr);
+ QCOMPARE(vp->strokeStyle(), QQuickShapePath::DashLine);
+
+ vp->setStrokeWidth(5.0f);
+ QCOMPARE(vp->strokeWidth(), 5.0f);
+
+ QQuickShapeLinearGradient *lgrad = qobject_cast<QQuickShapeLinearGradient *>(vp->fillGradient());
+ QVERIFY(lgrad != nullptr);
+ QCOMPARE(lgrad->spread(), QQuickShapeGradient::PadSpread);
+ QCOMPARE(lgrad->x1(), 20.0f);
+ QQmlListReference stopList(lgrad, "stops");
+ QCOMPARE(stopList.count(), 5);
+ QVERIFY(stopList.at(2) != nullptr);
+
+ QQuickPath *path = vp;
+ QCOMPARE(path->startX(), 20.0f);
+ QQmlListReference pathList(path, "pathElements");
+ QCOMPARE(pathList.count(), 3);
+}
+
+void tst_QQuickShape::changeSignals()
+{
+ QScopedPointer<QQuickView> window(createView());
+
+ window->setSource(testFileUrl("pathitem3.qml"));
+ qApp->processEvents();
+
+ QQuickShape *obj = findItem<QQuickShape>(window->rootObject(), "pathItem");
+ QVERIFY(obj != nullptr);
+
+ QSignalSpy asyncPropSpy(obj, SIGNAL(asynchronousChanged()));
+ obj->setAsynchronous(true);
+ obj->setAsynchronous(false);
+ QCOMPARE(asyncPropSpy.count(), 2);
+
+ QQmlListReference list(obj, "data");
+ QQuickShapePath *vp = qobject_cast<QQuickShapePath *>(list.at(0));
+ QVERIFY(vp != nullptr);
+
+ // Verify that VisualPath property changes emit shapePathChanged().
+ QSignalSpy vpChangeSpy(vp, SIGNAL(shapePathChanged()));
+ QSignalSpy strokeColorPropSpy(vp, SIGNAL(strokeColorChanged()));
+ vp->setStrokeColor(Qt::blue);
+ vp->setStrokeWidth(1.0f);
+ QQuickShapeGradient *g = vp->fillGradient();
+ vp->setFillGradient(nullptr);
+ vp->setFillColor(Qt::yellow);
+ vp->setFillRule(QQuickShapePath::WindingFill);
+ vp->setJoinStyle(QQuickShapePath::MiterJoin);
+ vp->setMiterLimit(5);
+ vp->setCapStyle(QQuickShapePath::RoundCap);
+ vp->setDashOffset(10);
+ vp->setDashPattern(QVector<qreal>() << 1 << 2 << 3 << 4);
+ QCOMPARE(strokeColorPropSpy.count(), 1);
+ QCOMPARE(vpChangeSpy.count(), 10);
+
+ // Verify that property changes from Path and its elements bubble up and result in shapePathChanged().
+ QQuickPath *path = vp;
+ path->setStartX(30);
+ QCOMPARE(vpChangeSpy.count(), 11);
+ QQmlListReference pathList(path, "pathElements");
+ qobject_cast<QQuickPathLine *>(pathList.at(1))->setY(200);
+ QCOMPARE(vpChangeSpy.count(), 12);
+
+ // Verify that property changes from the gradient bubble up and result in shapePathChanged().
+ vp->setFillGradient(g);
+ QCOMPARE(vpChangeSpy.count(), 13);
+ QQuickShapeLinearGradient *lgrad = qobject_cast<QQuickShapeLinearGradient *>(g);
+ lgrad->setX2(200);
+ QCOMPARE(vpChangeSpy.count(), 14);
+ QQmlListReference stopList(lgrad, "stops");
+ QCOMPARE(stopList.count(), 5);
+ qobject_cast<QQuickGradientStop *>(stopList.at(1))->setPosition(0.3);
+ QCOMPARE(vpChangeSpy.count(), 15);
+ qobject_cast<QQuickGradientStop *>(stopList.at(1))->setColor(Qt::black);
+ QCOMPARE(vpChangeSpy.count(), 16);
+}
+
+void tst_QQuickShape::render()
+{
+ QScopedPointer<QQuickView> window(createView());
+
+ window->setSource(testFileUrl("pathitem3.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QImage img = window->grabWindow();
+ QVERIFY(!img.isNull());
+
+ QImage refImg(testFileUrl("pathitem3.png").toLocalFile());
+ QVERIFY(!refImg.isNull());
+
+ QVERIFY(QQuickVisualTestUtil::compareImages(img.convertToFormat(refImg.format()), refImg));
+}
+
+void tst_QQuickShape::renderWithMultipleSp()
+{
+ QScopedPointer<QQuickView> window(createView());
+
+ window->setSource(testFileUrl("pathitem4.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QImage img = window->grabWindow();
+ QVERIFY(!img.isNull());
+
+ QImage refImg(testFileUrl("pathitem4.png").toLocalFile());
+ QVERIFY(!refImg.isNull());
+
+ QVERIFY(QQuickVisualTestUtil::compareImages(img.convertToFormat(refImg.format()), refImg));
+}
+
+QTEST_MAIN(tst_QQuickShape)
+
+#include "tst_qquickshape.moc"
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index c5fa0e19fa..4e643bb9d9 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -723,6 +723,61 @@ void tst_qquicktext::textFormat()
QCOMPARE(text->textFormat(), QQuickText::AutoText);
QCOMPARE(spy.count(), 2);
}
+
+ {
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0\n Text { text: \"<b>Hello</b>\" }", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickText *text = qobject_cast<QQuickText *>(object.data());
+ QVERIFY(text);
+ QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(text);
+ QVERIFY(textPrivate);
+
+ QCOMPARE(text->textFormat(), QQuickText::AutoText);
+ QVERIFY(!textPrivate->layout.formats().isEmpty());
+
+ text->setTextFormat(QQuickText::StyledText);
+ QVERIFY(!textPrivate->layout.formats().isEmpty());
+
+ text->setTextFormat(QQuickText::PlainText);
+ QVERIFY(textPrivate->layout.formats().isEmpty());
+
+ text->setTextFormat(QQuickText::AutoText);
+ QVERIFY(!textPrivate->layout.formats().isEmpty());
+ }
+
+ {
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0\nText { text: \"Hello\"; elide: Text.ElideRight }", QUrl::fromLocalFile(""));
+ QScopedPointer<QObject> object(component.create());
+ QQuickText *text = qobject_cast<QQuickText *>(object.data());
+ QVERIFY(text);
+ QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(text);
+ QVERIFY(textPrivate);
+
+ // underline a mnemonic
+ QVector<QTextLayout::FormatRange> formats;
+ QTextLayout::FormatRange range;
+ range.start = 0;
+ range.length = 1;
+ range.format.setFontUnderline(true);
+ formats << range;
+
+ // the mnemonic format should be retained
+ textPrivate->layout.setFormats(formats);
+ text->forceLayout();
+ QCOMPARE(textPrivate->layout.formats(), formats);
+
+ // and carried over to the elide layout
+ text->setWidth(text->implicitWidth() - 1);
+ QVERIFY(textPrivate->elideLayout);
+ QCOMPARE(textPrivate->elideLayout->formats(), formats);
+
+ // but cleared when the text changes
+ text->setText("Changed");
+ QVERIFY(textPrivate->elideLayout);
+ QVERIFY(textPrivate->layout.formats().isEmpty());
+ }
}
//the alignment tests may be trivial o.oa
diff --git a/tests/auto/quick/qquickwindow/BLACKLIST b/tests/auto/quick/qquickwindow/BLACKLIST
new file mode 100644
index 0000000000..3c000b36f3
--- /dev/null
+++ b/tests/auto/quick/qquickwindow/BLACKLIST
@@ -0,0 +1,4 @@
+# QTBUG-62177
+[attachedProperty]
+windows
+osx
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index daa5e53730..91d577fb6f 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -1353,12 +1353,6 @@ void tst_qquickwindow::headless()
if (isGL)
QVERIFY(!window->isSceneGraphInitialized());
}
-#if QT_CONFIG(opengl)
- if (QGuiApplication::platformName() == QLatin1String("windows")
- && QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) {
- QSKIP("Crashes on Windows/ANGLE, QTBUG-42967");
- }
-#endif
// Destroy the native windowing system buffers
window->destroy();
QVERIFY(!window->handle());
diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro
index 00be8240e5..2ff606488c 100644
--- a/tests/auto/quick/quick.pro
+++ b/tests/auto/quick/quick.pro
@@ -69,6 +69,7 @@ QUICKTESTS = \
qquickmousearea \
qquickmultipointtoucharea \
qquickpainteditem \
+ qquickshape \
qquickpathview \
qquickpincharea \
qquickpositioners \
diff --git a/tests/benchmarks/qml/creation/tst_creation.cpp b/tests/benchmarks/qml/creation/tst_creation.cpp
index 9fc67ada71..c0907b5dd1 100644
--- a/tests/benchmarks/qml/creation/tst_creation.cpp
+++ b/tests/benchmarks/qml/creation/tst_creation.cpp
@@ -385,7 +385,7 @@ void tst_creation::bindings_qml()
return;
}
- QQuickItem *obj = dynamic_cast<QQuickItem *>(component.create());
+ QQuickItem *obj = qobject_cast<QQuickItem *>(component.create());
QVERIFY(obj != nullptr);
int height = 0;
@@ -407,7 +407,7 @@ void tst_creation::bindings_parent_qml()
return;
}
- QQuickItem *obj = dynamic_cast<QQuickItem *>(component.create());
+ QQuickItem *obj = qobject_cast<QQuickItem *>(component.create());
QVERIFY(obj != nullptr);
int height = 0;
diff --git a/tests/manual/scenegraph_lancelot/data/shape/shape_arc.qml b/tests/manual/scenegraph_lancelot/data/shape/shape_arc.qml
new file mode 100644
index 0000000000..0b2396012e
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shape/shape_arc.qml
@@ -0,0 +1,112 @@
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Item {
+ width: 320
+ height: 480
+
+ Column {
+ Item {
+ width: 200
+ height: 100
+
+ Repeater {
+ model: 2
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: model.index === 0 ? "red" : "blue"
+ strokeStyle: ShapePath.DashLine
+ strokeWidth: 4
+
+ startX: 4; startY: 4
+ PathArc {
+ id: arc
+ x: 96; y: 96
+ radiusX: 100; radiusY: 100
+ direction: model.index === 0 ? PathArc.Clockwise : PathArc.Counterclockwise
+ }
+ }
+ }
+ }
+ }
+
+ Item {
+ width: 200
+ height: 100
+
+ Repeater {
+ model: 2
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: model.index === 0 ? "red" : "blue"
+ strokeStyle: ShapePath.DashLine
+ strokeWidth: 4
+
+ startX: 50; startY: 100
+ PathArc {
+ x: 100; y: 150
+ radiusX: 50; radiusY: 50
+ useLargeArc: model.index === 1
+ }
+ }
+ }
+ }
+ }
+
+ Item {
+ width: 200
+ height: 100
+
+ Repeater {
+ model: 2
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: model.index === 0 ? "red" : "blue"
+ strokeStyle: ShapePath.DashLine
+ strokeWidth: 4
+
+ startX: 50; startY: 150
+ PathArc {
+ x: 150; y: 150
+ radiusX: 50; radiusY: 20
+ xAxisRotation: model.index === 0 ? 0 : 45
+ }
+ }
+ }
+ }
+
+ Repeater {
+ model: 2
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: model.index === 0 ? "red" : "blue"
+
+ startX: 50; startY: 150
+ PathArc {
+ x: 150; y: 150
+ radiusX: 50; radiusY: 20
+ xAxisRotation: model.index === 0 ? 0 : 45
+ direction: PathArc.Counterclockwise
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shape/shape_arc_fill.qml b/tests/manual/scenegraph_lancelot/data/shape/shape_arc_fill.qml
new file mode 100644
index 0000000000..fefc2ec3eb
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shape/shape_arc_fill.qml
@@ -0,0 +1,112 @@
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Item {
+ width: 320
+ height: 480
+
+ Column {
+ Item {
+ width: 200
+ height: 100
+
+ Repeater {
+ model: 2
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ fillColor: "lightBlue"
+ strokeColor: model.index === 0 ? "red" : "blue"
+ strokeStyle: ShapePath.DashLine
+ strokeWidth: 4
+
+ startX: 4; startY: 4
+ PathArc {
+ id: arc
+ x: 96; y: 96
+ radiusX: 100; radiusY: 100
+ direction: model.index === 0 ? PathArc.Clockwise : PathArc.Counterclockwise
+ }
+ }
+ }
+ }
+ }
+
+ Item {
+ width: 200
+ height: 100
+
+ Repeater {
+ model: 2
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ fillColor: "green"
+ strokeColor: model.index === 0 ? "red" : "blue"
+ strokeStyle: ShapePath.DashLine
+ strokeWidth: 4
+
+ startX: 50; startY: 100
+ PathArc {
+ x: 100; y: 150
+ radiusX: 50; radiusY: 50
+ useLargeArc: model.index === 1
+ }
+ }
+ }
+ }
+ }
+
+ Item {
+ width: 200
+ height: 100
+
+ Repeater {
+ model: 2
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ fillColor: "gray"
+ strokeColor: model.index === 0 ? "red" : "blue"
+ strokeStyle: ShapePath.DashLine
+ strokeWidth: 4
+
+ startX: 50; startY: 150
+ PathArc {
+ x: 150; y: 150
+ radiusX: 50; radiusY: 20
+ xAxisRotation: model.index === 0 ? 0 : 45
+ }
+ }
+ }
+ }
+
+ Repeater {
+ model: 2
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ fillColor: "lightGray"
+ strokeColor: model.index === 0 ? "red" : "blue"
+
+ startX: 50; startY: 150
+ PathArc {
+ x: 150; y: 150
+ radiusX: 50; radiusY: 20
+ xAxisRotation: model.index === 0 ? 0 : 45
+ direction: PathArc.Counterclockwise
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shape/shape_cubic.qml b/tests/manual/scenegraph_lancelot/data/shape/shape_cubic.qml
new file mode 100644
index 0000000000..1d2f9fd40d
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shape/shape_cubic.qml
@@ -0,0 +1,35 @@
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Item {
+ width: 320
+ height: 480
+
+ Column {
+ Repeater {
+ model: 4
+ Item {
+ width: 200
+ height: 100
+
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ strokeWidth: (model.index + 2) * 2
+ strokeColor: "black"
+ fillColor: "lightBlue"
+
+ startX: 50; startY: 100
+ PathCubic {
+ x: 150; y: 100
+ control1X: model.index * 10; control1Y: model.index * 5
+ control2X: model.index * -10; control2Y: model.index * 10
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shape/shape_linear_gradient.qml b/tests/manual/scenegraph_lancelot/data/shape/shape_linear_gradient.qml
new file mode 100644
index 0000000000..1caaec7781
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shape/shape_linear_gradient.qml
@@ -0,0 +1,33 @@
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Item {
+ width: 320
+ height: 480
+
+ Shape {
+ vendorExtensionsEnabled: false
+
+ anchors.fill: parent
+
+ ShapePath {
+ strokeWidth: 4
+ strokeColor: "red"
+ fillGradient: LinearGradient {
+ x1: 20; y1: 20
+ x2: 180; y2: 130
+ GradientStop { position: 0; color: "blue" }
+ GradientStop { position: 0.2; color: "green" }
+ GradientStop { position: 0.4; color: "red" }
+ GradientStop { position: 0.6; color: "yellow" }
+ GradientStop { position: 1; color: "cyan" }
+ }
+ strokeStyle: ShapePath.DashLine
+ dashPattern: [ 1, 4 ]
+ startX: 20; startY: 20
+ PathLine { x: 180; y: 130 }
+ PathLine { x: 20; y: 130 }
+ PathLine { x: 20; y: 20 }
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shape/shape_lines.qml b/tests/manual/scenegraph_lancelot/data/shape/shape_lines.qml
new file mode 100644
index 0000000000..56045cb5ae
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shape/shape_lines.qml
@@ -0,0 +1,92 @@
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Item {
+ width: 320
+ height: 480
+
+ Shape {
+ vendorExtensionsEnabled: false
+
+ anchors.fill: parent
+
+ ShapePath {
+ strokeWidth: 1
+ strokeColor: "red"
+ fillColor: "transparent"
+ PathLine { x: 50; y: 50 }
+ }
+ ShapePath {
+ strokeWidth: 2
+ strokeColor: "blue"
+ fillColor: "transparent"
+ startX: 20
+ PathLine { x: 70; y: 50 }
+ }
+ ShapePath {
+ strokeWidth: 3
+ strokeColor: "green"
+ fillColor: "transparent"
+ startX: 40
+ PathLine { x: 90; y: 50 }
+ }
+ ShapePath {
+ strokeWidth: 4
+ strokeColor: "yellow"
+ fillColor: "transparent"
+ startX: 60
+ PathLine { x: 110; y: 50 }
+ }
+ ShapePath {
+ strokeWidth: 5
+ strokeColor: "black"
+ fillColor: "transparent"
+ strokeStyle: ShapePath.DashLine
+ startX: 80
+ PathLine { x: 130; y: 50 }
+ }
+
+ ShapePath {
+ strokeWidth: 20
+ strokeColor: "gray"
+ fillColor: "transparent"
+ capStyle: ShapePath.RoundCap
+ startX: 120; startY: 20
+ PathLine { x: 200; y: 100 }
+ }
+
+ ShapePath {
+ strokeColor: "black"
+ strokeWidth: 16
+ fillColor: "transparent"
+ capStyle: ShapePath.RoundCap
+ joinStyle: ShapePath.BevelJoin
+ startX: 20
+ startY: 100
+ PathLine { x: 120; y: 200 }
+ PathLine { x: 50; y: 200 }
+ }
+ ShapePath {
+ strokeColor: "black"
+ strokeWidth: 16
+ fillColor: "transparent"
+ capStyle: ShapePath.RoundCap
+ joinStyle: ShapePath.MiterJoin
+ startX: 150
+ startY: 100
+ PathLine { x: 250; y: 200 }
+ PathLine { x: 180; y: 200 }
+ }
+ ShapePath {
+ strokeColor: "black"
+ strokeWidth: 16
+ fillColor: "transparent"
+ capStyle: ShapePath.RoundCap
+ joinStyle: ShapePath.RoundJoin
+ startX: 270
+ startY: 100
+ PathLine { x: 310; y: 200 }
+ PathLine { x: 280; y: 200 }
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shape/shape_quad.qml b/tests/manual/scenegraph_lancelot/data/shape/shape_quad.qml
new file mode 100644
index 0000000000..a4c95f7c15
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shape/shape_quad.qml
@@ -0,0 +1,34 @@
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Item {
+ width: 320
+ height: 480
+
+ Column {
+ Repeater {
+ model: 4
+ Item {
+ width: 200
+ height: 100
+
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ strokeWidth: (model.index + 2) * 2
+ strokeColor: "black"
+ fillColor: "lightBlue"
+
+ startX: 50; startY: 100
+ PathQuad {
+ x: 150; y: 100
+ controlX: model.index * 10; controlY: model.index * 5
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shape/shape_spread.qml b/tests/manual/scenegraph_lancelot/data/shape/shape_spread.qml
new file mode 100644
index 0000000000..f310f08773
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shape/shape_spread.qml
@@ -0,0 +1,35 @@
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Item {
+ width: 320
+ height: 480
+
+ Column {
+ Repeater {
+ model: 3
+ Shape {
+ vendorExtensionsEnabled: false
+ width: 200
+ height: 150
+ ShapePath {
+ strokeColor: "transparent"
+
+ fillGradient: LinearGradient {
+ id: grad
+ y1: 50; y2: 80
+ spread: model.index === 0 ? ShapeGradient.PadSpread : (model.index === 1 ? ShapeGradient.RepeatSpread : ShapeGradient.ReflectSpread)
+ GradientStop { position: 0; color: "black" }
+ GradientStop { position: 1; color: "red" }
+ }
+
+ startX: 10; startY: 10
+ PathLine { relativeX: 180; relativeY: 0 }
+ PathLine { relativeX: 0; relativeY: 100 }
+ PathLine { relativeX: -180; relativeY: 0 }
+ PathLine { relativeX: 0; relativeY: -100 }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/text/text_advance_bidi_ltr.qml b/tests/manual/scenegraph_lancelot/data/text/text_advance_bidi_ltr.qml
new file mode 100644
index 0000000000..2f40aece89
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/text/text_advance_bidi_ltr.qml
@@ -0,0 +1,56 @@
+import QtQuick 2.0
+
+Item {
+ width: 320
+ height: 480
+
+ property string firstWord: "One, שתיים, "
+ property string secondWord: "Three"
+
+ Text {
+ id: referenceText
+ text: firstWord + secondWord
+ anchors.centerIn: parent
+ font.italic: true
+ font.pixelSize: 30
+ }
+
+ Text {
+ id: firstWordItem
+ anchors.left: referenceText.left
+ anchors.top: referenceText.bottom
+ text: firstWord
+ font: referenceText.font
+ }
+
+ Text {
+ id: secondWordItem
+ anchors.left: firstWordItem.left
+ anchors.leftMargin: firstWordItem.advance.width
+ anchors.baseline: firstWordItem.baseline
+ anchors.baselineOffset: firstWordItem.advance.height
+ text: secondWord
+ font: referenceText.font
+ }
+
+ Text {
+ id: firstWordItemRichText
+ anchors.left: referenceText.left
+ anchors.top: secondWordItem.bottom
+ text: firstWord
+ font: referenceText.font
+ textFormat: Text.RichText
+ }
+
+ Text {
+ id: secondWordItemRichText
+ anchors.left: firstWordItemRichText.left
+ anchors.leftMargin: firstWordItemRichText.advance.width
+ anchors.baseline: firstWordItemRichText.baseline
+ anchors.baselineOffset: firstWordItemRichText.advance.height
+ text: secondWord
+ font: referenceText.font
+ textFormat: Text.RichText
+ }
+
+}
diff --git a/tests/manual/scenegraph_lancelot/data/text/text_advance_hebrew.qml b/tests/manual/scenegraph_lancelot/data/text/text_advance_hebrew.qml
new file mode 100644
index 0000000000..0a9dce4d82
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/text/text_advance_hebrew.qml
@@ -0,0 +1,54 @@
+import QtQuick 2.0
+
+Item {
+ width: 320
+ height: 480
+
+ property string firstWord: "תורת רב־לשוני אנא "
+ property string secondWord: "של"
+
+ Text {
+ id: referenceText
+ text: firstWord + secondWord
+ anchors.centerIn: parent
+ font.italic: true
+ font.pixelSize: 30
+ }
+
+ Text {
+ id: firstWordItem
+ anchors.right: referenceText.right
+ anchors.top: referenceText.bottom
+ text: firstWord
+ font: referenceText.font
+ }
+
+ Text {
+ id: secondWordItem
+ anchors.right: firstWordItem.left
+ anchors.baseline: firstWordItem.baseline
+ anchors.baselineOffset: firstWordItem.advance.height
+ text: secondWord
+ font: referenceText.font
+ }
+
+ Text {
+ id: firstWordItemRichText
+ anchors.right: referenceText.right
+ anchors.top: secondWordItem.bottom
+ text: firstWord
+ font: referenceText.font
+ textFormat: Text.RichText
+ }
+
+ Text {
+ id: secondWordItemRichText
+ anchors.right: firstWordItemRichText.left
+ anchors.baseline: firstWordItemRichText.baseline
+ anchors.baselineOffset: firstWordItemRichText.advance.height
+ text: secondWord
+ font: referenceText.font
+ textFormat: Text.RichText
+ }
+
+}
diff --git a/tests/manual/scenegraph_lancelot/data/text/text_advance_latin.qml b/tests/manual/scenegraph_lancelot/data/text/text_advance_latin.qml
new file mode 100644
index 0000000000..ccab5d8c64
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/text/text_advance_latin.qml
@@ -0,0 +1,55 @@
+import QtQuick 2.0
+
+Item {
+ width: 320
+ height: 480
+
+ property string firstWord: "Hello "
+ property string secondWord: "World"
+
+ Text {
+ id: referenceText
+ text: firstWord + secondWord
+ anchors.centerIn: parent
+ font.italic: true
+ font.pixelSize: 30
+ }
+
+ Text {
+ id: firstWordItem
+ anchors.left: referenceText.left
+ anchors.top: referenceText.bottom
+ text: firstWord
+ font: referenceText.font
+ }
+
+ Text {
+ id: secondWordItem
+ anchors.left: firstWordItem.left
+ anchors.leftMargin: firstWordItem.advance.width
+ anchors.baseline: firstWordItem.baseline
+ anchors.baselineOffset: firstWordItem.advance.height
+ text: secondWord
+ font: referenceText.font
+ }
+
+ Text {
+ id: firstWordItemRichText
+ anchors.left: referenceText.left
+ anchors.top: secondWordItem.bottom
+ text: firstWord
+ font: referenceText.font
+ textFormat: Text.RichText
+ }
+
+ Text {
+ id: secondWordItemRichText
+ anchors.left: firstWordItemRichText.left
+ anchors.leftMargin: firstWordItemRichText.advance.width
+ anchors.baseline: firstWordItemRichText.baseline
+ anchors.baselineOffset: firstWordItemRichText.advance.height
+ text: secondWord
+ font: referenceText.font
+ textFormat: Text.RichText
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/text/text_advance_multiline.qml b/tests/manual/scenegraph_lancelot/data/text/text_advance_multiline.qml
new file mode 100644
index 0000000000..ae0f10718c
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/text/text_advance_multiline.qml
@@ -0,0 +1,55 @@
+import QtQuick 2.0
+
+Item {
+ width: 320
+ height: 480
+
+ property string firstWord: "One,\nTwo, "
+ property string secondWord: "Three"
+
+ Text {
+ id: referenceText
+ text: firstWord + secondWord
+ anchors.centerIn: parent
+ font.italic: true
+ font.pixelSize: 30
+ }
+
+ Text {
+ id: firstWordItem
+ anchors.left: referenceText.left
+ anchors.top: referenceText.bottom
+ text: firstWord
+ font: referenceText.font
+ }
+
+ Text {
+ id: secondWordItem
+ anchors.left: firstWordItem.left
+ anchors.leftMargin: firstWordItem.advance.width
+ anchors.baseline: firstWordItem.baseline
+ anchors.baselineOffset: firstWordItem.advance.height
+ text: secondWord
+ font: referenceText.font
+ }
+
+ Text {
+ id: firstWordItemRichText
+ anchors.left: referenceText.left
+ anchors.top: secondWordItem.bottom
+ text: firstWord
+ font: referenceText.font
+ textFormat: Text.RichText
+ }
+
+ Text {
+ id: secondWordItemRichText
+ anchors.left: firstWordItemRichText.left
+ anchors.leftMargin: firstWordItemRichText.advance.width
+ anchors.baseline: firstWordItemRichText.baseline
+ anchors.baselineOffset: firstWordItemRichText.advance.height
+ text: secondWord
+ font: referenceText.font
+ textFormat: Text.RichText
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/text/text_advance_multiparagraph.qml b/tests/manual/scenegraph_lancelot/data/text/text_advance_multiparagraph.qml
new file mode 100644
index 0000000000..76f0910680
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/text/text_advance_multiparagraph.qml
@@ -0,0 +1,39 @@
+import QtQuick 2.0
+
+Item {
+ width: 320
+ height: 480
+
+ property string firstWord: "<p>One,</p><p>Two, "
+ property string secondWord: "Three</p>"
+
+ Text {
+ id: referenceText
+ text: firstWord + secondWord
+ anchors.centerIn: parent
+ font.italic: true
+ font.pixelSize: 30
+ textFormat: Text.RichText
+ }
+
+
+ Text {
+ id: firstWordItemRichText
+ anchors.left: referenceText.left
+ anchors.top: referenceText.bottom
+ text: firstWord
+ font: referenceText.font
+ textFormat: Text.RichText
+ }
+
+ Text {
+ id: secondWordItemRichText
+ anchors.left: firstWordItemRichText.left
+ anchors.leftMargin: firstWordItemRichText.advance.width
+ anchors.baseline: firstWordItemRichText.baseline
+ anchors.baselineOffset: firstWordItemRichText.advance.height
+ text: secondWord
+ font: referenceText.font
+ textFormat: Text.RichText
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/text/text_advance_multiparagraph_multifontsizes.qml b/tests/manual/scenegraph_lancelot/data/text/text_advance_multiparagraph_multifontsizes.qml
new file mode 100644
index 0000000000..de33d65cdc
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/text/text_advance_multiparagraph_multifontsizes.qml
@@ -0,0 +1,39 @@
+import QtQuick 2.0
+
+Item {
+ width: 320
+ height: 480
+
+ property string firstWord: "<p style=\"font-size: 40pt\">One,</p><p>Two, "
+ property string secondWord: "Three</p>"
+
+ Text {
+ id: referenceText
+ text: firstWord + secondWord
+ anchors.centerIn: parent
+ font.italic: true
+ font.pixelSize: 30
+ textFormat: Text.RichText
+ }
+
+
+ Text {
+ id: firstWordItemRichText
+ anchors.left: referenceText.left
+ anchors.top: referenceText.bottom
+ text: firstWord
+ font: referenceText.font
+ textFormat: Text.RichText
+ }
+
+ Text {
+ id: secondWordItemRichText
+ anchors.left: firstWordItemRichText.left
+ anchors.leftMargin: firstWordItemRichText.advance.width
+ anchors.baseline: firstWordItemRichText.baseline
+ anchors.baselineOffset: firstWordItemRichText.advance.height
+ text: secondWord
+ font: referenceText.font
+ textFormat: Text.RichText
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/text/text_nokerning_latin.qml b/tests/manual/scenegraph_lancelot/data/text/text_nokerning_latin.qml
new file mode 100644
index 0000000000..fd1d082c99
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/text/text_nokerning_latin.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.0
+
+Item {
+ width: 320
+ height: 480
+
+ Text {
+ text: "OATS FLAVOUR WAY"
+ anchors.centerIn: parent
+
+ font.family: "Times New Roman"
+ font.italic: true
+ font.pixelSize: 30
+ font.kerning: false
+ }
+}
diff --git a/tests/manual/shapestest/main.cpp b/tests/manual/shapestest/main.cpp
new file mode 100644
index 0000000000..b9b93fbf9f
--- /dev/null
+++ b/tests/manual/shapestest/main.cpp
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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 The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QSurfaceFormat>
+#include <QQuickView>
+#include <QQmlEngine>
+
+int main(int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+
+ QQuickView view;
+
+ QSurfaceFormat fmt;
+ fmt.setDepthBufferSize(24);
+ fmt.setStencilBufferSize(8);
+ if (app.arguments().contains(QStringLiteral("--multisample")))
+ fmt.setSamples(4);
+ if (app.arguments().contains(QStringLiteral("--coreprofile"))) {
+ fmt.setVersion(4, 3);
+ fmt.setProfile(QSurfaceFormat::CoreProfile);
+ }
+ view.setFormat(fmt);
+
+ view.setResizeMode(QQuickView::SizeRootObjectToView);
+ view.resize(1024, 768);
+ view.setSource(QUrl("qrc:/shapestest/shapestest.qml"));
+ view.show();
+
+ return app.exec();
+}
diff --git a/tests/manual/shapestest/shapestest.pro b/tests/manual/shapestest/shapestest.pro
new file mode 100644
index 0000000000..1776175134
--- /dev/null
+++ b/tests/manual/shapestest/shapestest.pro
@@ -0,0 +1,6 @@
+TEMPLATE = app
+
+QT += quick qml
+SOURCES += main.cpp
+RESOURCES += shapestest.qrc
+OTHER_FILES += shapestest.qml
diff --git a/tests/manual/shapestest/shapestest.qml b/tests/manual/shapestest/shapestest.qml
new file mode 100644
index 0000000000..df53f088ae
--- /dev/null
+++ b/tests/manual/shapestest/shapestest.qml
@@ -0,0 +1,396 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ id: root
+ width: 1024
+ height: 768
+
+ property color col: "lightsteelblue"
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: Qt.tint(root.col, "#20FFFFFF") }
+ GradientStop { position: 0.1; color: Qt.tint(root.col, "#20AAAAAA") }
+ GradientStop { position: 0.9; color: Qt.tint(root.col, "#20666666") }
+ GradientStop { position: 1.0; color: Qt.tint(root.col, "#20000000") }
+ }
+
+ Row {
+ anchors.top: parent.top
+ anchors.centerIn: parent
+ spacing: 20
+
+ Column {
+ spacing: 20
+
+ Rectangle {
+ border.color: "purple"
+ color: "transparent"
+ width: 200
+ height: 100
+ Shape {
+ id: triangle
+ anchors.fill: parent
+ ShapePath {
+ strokeWidth: 4
+ strokeColor: "red"
+ fillGradient: LinearGradient {
+ x1: 0; y1: 0
+ x2: 200; y2: 100
+ GradientStop { position: 0; color: "blue" }
+ GradientStop { position: 0.2; color: "green" }
+ GradientStop { position: 0.4; color: "red" }
+ GradientStop { position: 0.6; color: "yellow" }
+ GradientStop { position: 1; color: "cyan" }
+ }
+ fillColor: "blue" // ignored with the gradient set
+ strokeStyle: ShapePath.DashLine
+ dashPattern: [ 1, 4 ]
+ PathLine { x: 200; y: 100 }
+ PathLine { x: 0; y: 100 }
+ PathLine { x: 0; y: 0 }
+ }
+ transform: Rotation { origin.x: 100; origin.y: 50; axis { x: 0; y: 1; z: 0 }
+ SequentialAnimation on angle {
+ NumberAnimation { from: 0; to: 75; duration: 2000 }
+ NumberAnimation { from: 75; to: -75; duration: 4000 }
+ NumberAnimation { from: -75; to: 0; duration: 2000 }
+ loops: Animation.Infinite
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ border.color: "purple"
+ color: "transparent"
+ width: 200
+ height: 100
+ Shape {
+ anchors.fill: parent
+ ShapePath {
+ id: someCurve
+ property color sc: "gray"
+ strokeColor: sc
+ property color fc: "yellow"
+ fillColor: fc
+ startX: 20; startY: 10
+ PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 }
+ PathLine { x: 150; y: 80 }
+ PathQuad { x: 180; y: 10; controlX: 200; controlY: 80 }
+ PathLine { x: 20; y: 10 }
+ // Dynamic changes via property bindings etc. all work but can
+ // be computationally expense with the generic backend for properties
+ // that need retriangulating on every change. Should be cheap with NVPR.
+ NumberAnimation on strokeWidth {
+ from: 1; to: 20; duration: 10000
+ }
+ }
+ }
+ // Changing colors for a solid stroke or fill is simple and
+ // (relatively) cheap. However, changing to/from transparent
+ // stroke/fill color and stroke width 0 are special as these
+ // change the scenegraph node tree (with the generic backend).
+ Timer {
+ interval: 2000
+ running: true
+ repeat: true
+ onTriggered: someCurve.fillColor = (someCurve.fillColor === someCurve.fc ? "transparent" : someCurve.fc)
+ }
+ Timer {
+ interval: 1000
+ running: true
+ repeat: true
+ onTriggered: someCurve.strokeColor = (someCurve.strokeColor === someCurve.sc ? "transparent" : someCurve.sc)
+ }
+ }
+
+ Rectangle {
+ border.color: "purple"
+ color: "transparent"
+ width: 300
+ height: 100
+ Shape {
+ id: linesAndMoves
+ anchors.fill: parent
+ ShapePath {
+ strokeColor: "black"
+ startX: 0; startY: 50
+ PathLine { relativeX: 100; y: 50 }
+ PathMove { relativeX: 100; y: 50 }
+ PathLine { relativeX: 100; y: 50 }
+ }
+ }
+ }
+
+ Rectangle {
+ border.color: "purple"
+ color: "transparent"
+ width: 200
+ height: 120
+ Shape {
+ anchors.fill: parent
+ ShapePath {
+ id: joinTest
+ strokeColor: "black"
+ strokeWidth: 16
+ fillColor: "transparent"
+ capStyle: ShapePath.RoundCap
+ startX: 30
+ startY: 30
+ PathLine { x: 100; y: 100 }
+ PathLine { x: 30; y: 100 }
+ }
+ }
+ Timer {
+ interval: 1000
+ repeat: true
+ running: true
+ property variant styles: [ ShapePath.BevelJoin, ShapePath.MiterJoin, ShapePath.RoundJoin ]
+ onTriggered: {
+ for (var i = 0; i < styles.length; ++i)
+ if (styles[i] === joinTest.joinStyle) {
+ joinTest.joinStyle = styles[(i + 1) % styles.length];
+ break;
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ border.color: "purple"
+ color: "transparent"
+ width: 200
+ height: 100
+ Shape {
+ anchors.fill: parent
+ ShapePath {
+ id: star
+ strokeColor: "blue"
+ fillColor: "lightGray"
+ strokeWidth: 2
+ PathMove { x: 90; y: 50 }
+ PathLine { x: 50 + 40 * Math.cos(0.8 * 1 * Math.PI); y: 50 + 40 * Math.sin(0.8 * 1 * Math.PI) }
+ PathLine { x: 50 + 40 * Math.cos(0.8 * 2 * Math.PI); y: 50 + 40 * Math.sin(0.8 * 2 * Math.PI) }
+ PathLine { x: 50 + 40 * Math.cos(0.8 * 3 * Math.PI); y: 50 + 40 * Math.sin(0.8 * 3 * Math.PI) }
+ PathLine { x: 50 + 40 * Math.cos(0.8 * 4 * Math.PI); y: 50 + 40 * Math.sin(0.8 * 4 * Math.PI) }
+ PathLine { x: 90; y: 50 }
+ }
+ }
+ Timer {
+ interval: 1000
+ onTriggered: star.fillRule = (star.fillRule === ShapePath.OddEvenFill ? ShapePath.WindingFill : ShapePath.OddEvenFill)
+ repeat: true
+ running: true
+ }
+ }
+
+ Rectangle {
+ border.color: "purple"
+ color: "transparent"
+ width: 200
+ height: 100
+ Shape {
+ anchors.fill: parent
+ ShapePath {
+ strokeWidth: 4
+ strokeColor: "black"
+ fillColor: "transparent"
+ startX: 20; startY: 10
+ PathCubic {
+ id: cb
+ x: 180; y: 10
+ control1X: -10; control1Y: 90; control2Y: 90
+ NumberAnimation on control2X { from: 400; to: 0; duration: 5000; loops: Animation.Infinite }
+ }
+ }
+ }
+ }
+ }
+
+ Column {
+ spacing: 20
+
+ Rectangle {
+ border.color: "purple"
+ color: "transparent"
+ width: 200
+ height: 100
+ Shape {
+ anchors.fill: parent
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: "red"
+ strokeWidth: 4
+ startX: 10; startY: 40
+ PathArc {
+ x: 10; y: 60
+ radiusX: 40; radiusY: 40
+ useLargeArc: true
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ border.color: "purple"
+ color: "transparent"
+ width: 200
+ height: 200
+ Rectangle {
+ anchors.centerIn: parent
+ // have a size smaller than 150x150
+ width: 100
+ height: 100
+ // and enable clipping. Normally this goes via scissoring, unless
+ // some transform triggers the stencil-based path. Ensure this via rotation.
+ clip: true
+ NumberAnimation on rotation {
+ from: 0; to: 360; duration: 5000; loops: Animation.Infinite
+ }
+
+ Shape {
+ width: 150
+ height: 150
+
+ ShapePath {
+ fillColor: "blue"
+ strokeColor: "red"
+ strokeWidth: 4
+ startX: 10; startY: 10
+ PathLine { x: 140; y: 140 }
+ PathLine { x: 10; y: 140 }
+ PathLine { x: 10; y: 10 }
+ }
+ }
+ }
+ }
+
+ // stencil clip test #2, something more complicated:
+ Rectangle {
+ border.color: "purple"
+ color: "transparent"
+ width: 150
+ height: 150
+ Rectangle {
+ anchors.centerIn: parent
+ width: 60
+ height: 60
+ clip: true
+ NumberAnimation on rotation {
+ from: 0; to: 360; duration: 5000; loops: Animation.Infinite
+ }
+ Shape {
+ width: 100
+ height: 100
+ ShapePath {
+ id: clippedStar
+ strokeColor: "blue"
+ fillColor: "lightGray"
+ strokeWidth: 2
+ PathMove { x: 90; y: 50 }
+ PathLine { x: 50 + 40 * Math.cos(0.8 * 1 * Math.PI); y: 50 + 40 * Math.sin(0.8 * 1 * Math.PI) }
+ PathLine { x: 50 + 40 * Math.cos(0.8 * 2 * Math.PI); y: 50 + 40 * Math.sin(0.8 * 2 * Math.PI) }
+ PathLine { x: 50 + 40 * Math.cos(0.8 * 3 * Math.PI); y: 50 + 40 * Math.sin(0.8 * 3 * Math.PI) }
+ PathLine { x: 50 + 40 * Math.cos(0.8 * 4 * Math.PI); y: 50 + 40 * Math.sin(0.8 * 4 * Math.PI) }
+ PathLine { x: 90; y: 50 }
+ }
+ }
+ Timer {
+ interval: 1000
+ onTriggered: clippedStar.fillRule = (clippedStar.fillRule === ShapePath.OddEvenFill ? ShapePath.WindingFill : ShapePath.OddEvenFill)
+ repeat: true
+ running: true
+ }
+ }
+ }
+
+ Rectangle {
+ border.color: "purple"
+ color: "transparent"
+ width: 100
+ height: 100
+ Shape {
+ anchors.fill: parent
+ ShapePath {
+ strokeColor: "red"
+ PathLine { x: 100; y: 100 }
+ }
+ ShapePath {
+ strokeColor: "blue"
+ startX: 100; startY: 0
+ PathLine { x: 0; y: 100 }
+ }
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ id: stackTestRect
+ SequentialAnimation on opacity {
+ NumberAnimation { from: 0; to: 1; duration: 5000 }
+ PauseAnimation { duration: 2000 }
+ NumberAnimation { from: 1; to: 0; duration: 5000 }
+ PauseAnimation { duration: 2000 }
+ loops: Animation.Infinite
+ id: opAnim
+ }
+ color: "blue"
+ anchors.margins: 10
+ anchors.fill: parent
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: stackTestRect.visible = !stackTestRect.visible
+ }
+}
diff --git a/tests/manual/shapestest/shapestest.qrc b/tests/manual/shapestest/shapestest.qrc
new file mode 100644
index 0000000000..6bfc953997
--- /dev/null
+++ b/tests/manual/shapestest/shapestest.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/shapestest">
+ <file>shapestest.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/v4/typedarrays.js b/tests/manual/v4/typedarrays.js
index 8cf2b8c75a..f727df7185 100644
--- a/tests/manual/v4/typedarrays.js
+++ b/tests/manual/v4/typedarrays.js
@@ -670,12 +670,12 @@ function TestDataViewConstructor() {
/* This is wrong according to ecma 6 and should throw:
- var d4 = new DataView(ab, 1, 3.1415926);
+ var d4 = new DataView(ab, 1, Math.PI);
assertSame(ab, d4.buffer);
assertSame(1, d4.byteOffset);
assertSame(3, d4.byteLength);
*/
- assertThrows(function() { new DataView(ab, 3.1415926); }, RangeError);
+ assertThrows(function() { new DataView(ab, Math.PI); }, RangeError);
// error cases
assertThrows(function() { new DataView(ab, -1); }, RangeError);
diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp
index 9b5fcc74c2..83680a5ba1 100644
--- a/tools/qml/main.cpp
+++ b/tools/qml/main.cpp
@@ -134,7 +134,7 @@ class LoaderApplication : public QGuiApplication
public:
LoaderApplication(int& argc, char **argv) : QGuiApplication(argc, argv) {}
- bool event(QEvent *ev)
+ bool event(QEvent *ev) override
{
if (ev->type() == QEvent::FileOpen) {
if (exitTimerId >= 0) {
@@ -148,7 +148,7 @@ public:
return true;
}
- void timerEvent(QTimerEvent *) {
+ void timerEvent(QTimerEvent *) override {
noFilesGiven();
}
};
diff --git a/tools/qml/qml.pro b/tools/qml/qml.pro
index d0083c0e78..3aa8af18bc 100644
--- a/tools/qml/qml.pro
+++ b/tools/qml/qml.pro
@@ -6,14 +6,7 @@ HEADERS += conf.h
SOURCES += main.cpp
RESOURCES += qml.qrc
-QMAKE_TARGET_PRODUCT = qml
-QMAKE_TARGET_DESCRIPTION = Utility that loads and displays QML documents
-
-win32 {
- VERSION = $${QT_VERSION}.0
-} else {
- VERSION = $${QT_VERSION}
-}
+QMAKE_TARGET_DESCRIPTION = QML Runtime
mac {
OTHER_FILES += Info.plist
diff --git a/tools/qmlcachegen/qmlcachegen.pro b/tools/qmlcachegen/qmlcachegen.pro
index 25afc2860d..be92ef435e 100644
--- a/tools/qmlcachegen/qmlcachegen.pro
+++ b/tools/qmlcachegen/qmlcachegen.pro
@@ -11,4 +11,6 @@ build_integration.path = $$[QT_HOST_DATA]/mkspecs/features
prefix_build: INSTALLS += build_integration
else: COPIES += build_integration
+QMAKE_TARGET_DESCRIPTION = QML Cache Generator
+
load(qt_tool)
diff --git a/tools/qmleasing/qmleasing.pro b/tools/qmleasing/qmleasing.pro
index 534bc9fe98..4267ecc5ad 100644
--- a/tools/qmleasing/qmleasing.pro
+++ b/tools/qmleasing/qmleasing.pro
@@ -17,13 +17,6 @@ FORMS += \
pane.ui \
import.ui
-QMAKE_TARGET_PRODUCT = qmleasing
-QMAKE_TARGET_DESCRIPTION = QML easing curve editor
-
-win32 {
- VERSION = $${QT_VERSION}.0
-} else {
- VERSION = $${QT_VERSION}
-}
+QMAKE_TARGET_DESCRIPTION = QML Easing Curve Editor
load(qt_app)
diff --git a/tools/qmlimportscanner/main.cpp b/tools/qmlimportscanner/main.cpp
index bac7694e17..26a83395c8 100644
--- a/tools/qmlimportscanner/main.cpp
+++ b/tools/qmlimportscanner/main.cpp
@@ -291,7 +291,7 @@ struct ImportCollector : public QQmlJS::Directives
{
QVariantList imports;
- virtual void importFile(const QString &jsfile, const QString &module, int line, int column)
+ void importFile(const QString &jsfile, const QString &module, int line, int column) override
{
QVariantMap entry;
entry[typeLiteral()] = QStringLiteral("javascript");
@@ -303,7 +303,7 @@ struct ImportCollector : public QQmlJS::Directives
Q_UNUSED(column);
}
- virtual void importModule(const QString &uri, const QString &version, const QString &module, int line, int column)
+ void importModule(const QString &uri, const QString &version, const QString &module, int line, int column) override
{
QVariantMap entry;
if (uri.contains(QLatin1Char('/'))) {
diff --git a/tools/qmlimportscanner/qmlimportscanner.pro b/tools/qmlimportscanner/qmlimportscanner.pro
index 363424f948..0b3a03abf3 100644
--- a/tools/qmlimportscanner/qmlimportscanner.pro
+++ b/tools/qmlimportscanner/qmlimportscanner.pro
@@ -5,13 +5,6 @@ DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII
SOURCES += main.cpp
-QMAKE_TARGET_PRODUCT = qmlimportscanner
-QMAKE_TARGET_DESCRIPTION = Tool to scan projects for QML imports
-
-win32 {
- VERSION = $${QT_VERSION}.0
-} else {
- VERSION = $${QT_VERSION}
-}
+QMAKE_TARGET_DESCRIPTION = QML Import Scanner
load(qt_tool)
diff --git a/tools/qmljs/qmljs.cpp b/tools/qmljs/qmljs.cpp
index 14a20731c0..182547490d 100644
--- a/tools/qmljs/qmljs.cpp
+++ b/tools/qmljs/qmljs.cpp
@@ -69,9 +69,7 @@ static void showException(QV4::ExecutionContext *ctx, const QV4::Value &exceptio
if (!e) {
std::cerr << "Uncaught exception: " << qPrintable(ex->toQString()) << std::endl;
} else {
- QV4::ScopedString m(scope, scope.engine->newString(QStringLiteral("message")));
- QV4::ScopedValue message(scope, e->get(m));
- std::cerr << "Uncaught exception: " << qPrintable(message->toQStringNoThrow()) << std::endl;
+ std::cerr << "Uncaught exception: " << qPrintable(e->toQStringNoThrow()) << std::endl;
}
for (const QV4::StackFrame &frame : trace) {
diff --git a/tools/qmljs/qmljs.pro b/tools/qmljs/qmljs.pro
index 9f82f48980..c2c4cb3cc4 100644
--- a/tools/qmljs/qmljs.pro
+++ b/tools/qmljs/qmljs.pro
@@ -5,13 +5,6 @@ SOURCES = qmljs.cpp
include($$PWD/../../src/3rdparty/masm/masm-defs.pri)
-QMAKE_TARGET_PRODUCT = qmljs
-QMAKE_TARGET_DESCRIPTION = QML Javascript tool
-
-win32 {
- VERSION = $${QT_VERSION}.0
-} else {
- VERSION = $${QT_VERSION}
-}
+QMAKE_TARGET_DESCRIPTION = QML JavaScript Tool
load(qt_tool)
diff --git a/tools/qmllint/qmllint.pro b/tools/qmllint/qmllint.pro
index 27af880c8c..91ab2f8afc 100644
--- a/tools/qmllint/qmllint.pro
+++ b/tools/qmllint/qmllint.pro
@@ -4,13 +4,6 @@ QT = core qmldevtools-private
SOURCES += main.cpp
-QMAKE_TARGET_PRODUCT = qmllint
-QMAKE_TARGET_DESCRIPTION = QML syntax verifier
-
-win32 {
- VERSION = $${QT_VERSION}.0
-} else {
- VERSION = $${QT_VERSION}
-}
+QMAKE_TARGET_DESCRIPTION = QML Syntax Verifier
load(qt_tool)
diff --git a/tools/qmlmin/main.cpp b/tools/qmlmin/main.cpp
index 6877ca7442..5641e6348e 100644
--- a/tools/qmlmin/main.cpp
+++ b/tools/qmlmin/main.cpp
@@ -83,12 +83,12 @@ public:
//
// Handle the .pragma/.import directives
//
- virtual void pragmaLibrary()
+ void pragmaLibrary() override
{
_directives += QLatin1String(".pragma library\n");
}
- virtual void importFile(const QString &jsfile, const QString &module, int line, int column)
+ void importFile(const QString &jsfile, const QString &module, int line, int column) override
{
_directives += QLatin1String(".import");
_directives += QLatin1Char('"');
@@ -101,7 +101,7 @@ public:
Q_UNUSED(column);
}
- virtual void importModule(const QString &uri, const QString &version, const QString &module, int line, int column)
+ void importModule(const QString &uri, const QString &version, const QString &module, int line, int column) override
{
_directives += QLatin1String(".import ");
_directives += uri;
@@ -201,7 +201,7 @@ public:
protected:
void append(const QString &s);
- bool parse(int startToken);
+ bool parse(int startToken) override;
void escape(const QChar &ch, QString *out);
};
@@ -409,7 +409,7 @@ public:
QStringList tokenStream() const;
protected:
- virtual bool parse(int startToken);
+ bool parse(int startToken) override;
};
Tokenize::Tokenize()
diff --git a/tools/qmlmin/qmlmin.pro b/tools/qmlmin/qmlmin.pro
index f5248e1b69..32d9e3343b 100644
--- a/tools/qmlmin/qmlmin.pro
+++ b/tools/qmlmin/qmlmin.pro
@@ -2,13 +2,6 @@ option(host_build)
QT = core qmldevtools-private
SOURCES += main.cpp
-QMAKE_TARGET_PRODUCT = qmlmin
-QMAKE_TARGET_DESCRIPTION = QML/JS minifier
-
-win32 {
- VERSION = $${QT_VERSION}.0
-} else {
- VERSION = $${QT_VERSION}
-}
+QMAKE_TARGET_DESCRIPTION = QML/JS Minifier
load(qt_tool)
diff --git a/tools/qmlplugindump/qmlplugindump.pro b/tools/qmlplugindump/qmlplugindump.pro
index 2749ec943f..62b08e9334 100644
--- a/tools/qmlplugindump/qmlplugindump.pro
+++ b/tools/qmlplugindump/qmlplugindump.pro
@@ -22,13 +22,6 @@ macx {
CONFIG -= app_bundle
}
-QMAKE_TARGET_PRODUCT = qmlplugindump
-QMAKE_TARGET_DESCRIPTION = QML plugin dump tool
-
-win32 {
- VERSION = $${QT_VERSION}.0
-} else {
- VERSION = $${QT_VERSION}
-}
+QMAKE_TARGET_DESCRIPTION = QML Plugin Metadata Dumper
load(qt_tool)
diff --git a/tools/qmlprofiler/qmlprofiler.pro b/tools/qmlprofiler/qmlprofiler.pro
index b5bb1dcc46..a2522e9267 100644
--- a/tools/qmlprofiler/qmlprofiler.pro
+++ b/tools/qmlprofiler/qmlprofiler.pro
@@ -14,13 +14,6 @@ HEADERS += \
qmlprofilerdata.h \
qmlprofilerclient.h
-QMAKE_TARGET_PRODUCT = qmlprofiler
-QMAKE_TARGET_DESCRIPTION = QML profiler
-
-win32 {
- VERSION = $${QT_VERSION}.0
-} else {
- VERSION = $${QT_VERSION}
-}
+QMAKE_TARGET_DESCRIPTION = QML Profiler
load(qt_tool)
diff --git a/tools/qmlprofiler/qmlprofilerdata.cpp b/tools/qmlprofiler/qmlprofilerdata.cpp
index 0044af0b52..7dcfa4cdaa 100644
--- a/tools/qmlprofiler/qmlprofilerdata.cpp
+++ b/tools/qmlprofiler/qmlprofilerdata.cpp
@@ -33,7 +33,7 @@
#include <QHash>
#include <QFile>
#include <QXmlStreamReader>
-#include <QRegExp>
+#include <QRegularExpression>
#include <limits>
@@ -232,10 +232,10 @@ void QmlProfilerData::addQmlEvent(QQmlProfilerDefinitions::RangeType type,
if (!data.isEmpty()) {
details = data.join(QLatin1Char(' ')).replace(
QLatin1Char('\n'), QLatin1Char(' ')).simplified();
- QRegExp rewrite(QStringLiteral("\\(function \\$(\\w+)\\(\\) \\{ (return |)(.+) \\}\\)"));
- bool match = rewrite.exactMatch(details);
- if (match) {
- details = rewrite.cap(1) +QLatin1String(": ") + rewrite.cap(3);
+ QRegularExpression rewrite(QStringLiteral("^\\(function \\$(\\w+)\\(\\) \\{ (return |)(.+) \\}\\)$"));
+ QRegularExpressionMatch match = rewrite.match(details);
+ if (match.hasMatch()) {
+ details = match.captured(1) +QLatin1String(": ") + match.captured(3);
}
if (details.startsWith(QLatin1String("file://")))
details = details.mid(details.lastIndexOf(QLatin1Char('/')) + 1);
diff --git a/tools/qmlscene/main.cpp b/tools/qmlscene/main.cpp
index 7741c4c45b..f411c6becc 100644
--- a/tools/qmlscene/main.cpp
+++ b/tools/qmlscene/main.cpp
@@ -33,7 +33,7 @@
#include <QtCore/qpointer.h>
#include <QtCore/qscopedpointer.h>
#include <QtCore/qtextstream.h>
-#include <QtCore/qregexp.h>
+#include <QtCore/qregularexpression.h>
#include <QtGui/QGuiApplication>
#include <QtGui/QOpenGLFunctions>
@@ -133,6 +133,17 @@ void RenderStatistics::printTotalStats()
struct Options
{
+ enum QmlApplicationType
+ {
+ QmlApplicationTypeGui,
+ QmlApplicationTypeWidget,
+#ifdef QT_WIDGETS_LIB
+ DefaultQmlApplicationType = QmlApplicationTypeWidget
+#else
+ DefaultQmlApplicationType = QmlApplicationTypeGui
+#endif
+ };
+
Options()
: originalQml(false)
, originalQmlRaster(false)
@@ -145,7 +156,9 @@ struct Options
, quitImmediately(false)
, resizeViewToRootItem(false)
, multisample(false)
+ , coreProfile(false)
, verbose(false)
+ , applicationType(DefaultQmlApplicationType)
{
// QtWebEngine needs a shared context in order for the GPU thread to
// upload textures.
@@ -164,9 +177,11 @@ struct Options
bool quitImmediately;
bool resizeViewToRootItem;
bool multisample;
+ bool coreProfile;
bool verbose;
QVector<Qt::ApplicationAttribute> applicationAttributes;
QString translationFile;
+ QmlApplicationType applicationType;
};
#if defined(QMLSCENE_BUNDLE)
@@ -259,8 +274,8 @@ static bool checkVersion(const QUrl &url)
return false;
}
- QRegExp quick1("^\\s*import +QtQuick +1\\.\\w*");
- QRegExp qt47("^\\s*import +Qt +4\\.7");
+ QRegularExpression quick1("^\\s*import +QtQuick +1\\.\\w*");
+ QRegularExpression qt47("^\\s*import +Qt +4\\.7");
QTextStream stream(&f);
bool codeFound= false;
@@ -270,10 +285,11 @@ static bool checkVersion(const QUrl &url)
codeFound = true;
} else {
QString import;
- if (quick1.indexIn(line) >= 0)
- import = quick1.cap(0).trimmed();
- else if (qt47.indexIn(line) >= 0)
- import = qt47.cap(0).trimmed();
+ QRegularExpressionMatch match = quick1.match(line);
+ if (match.hasMatch())
+ import = match.captured(0).trimmed();
+ else if ((match = qt47.match(line)).hasMatch())
+ import = match.captured(0).trimmed();
if (!import.isNull()) {
fprintf(stderr, "qmlscene: '%s' is no longer supported.\n"
@@ -291,15 +307,17 @@ static bool checkVersion(const QUrl &url)
static void displayFileDialog(Options *options)
{
#if defined(QT_WIDGETS_LIB) && QT_CONFIG(filedialog)
- QString fileName = QFileDialog::getOpenFileName(0, "Open QML file", QString(), "QML Files (*.qml)");
- if (!fileName.isEmpty()) {
- QFileInfo fi(fileName);
- options->url = QUrl::fromLocalFile(fi.canonicalFilePath());
+ if (options->applicationType == Options::QmlApplicationTypeWidget) {
+ QString fileName = QFileDialog::getOpenFileName(0, "Open QML file", QString(), "QML Files (*.qml)");
+ if (!fileName.isEmpty()) {
+ QFileInfo fi(fileName);
+ options->url = QUrl::fromLocalFile(fi.canonicalFilePath());
+ }
+ return;
}
-#else
+#endif // QT_WIDGETS_LIB && QT_CONFIG(filedialog)
Q_UNUSED(options);
puts("No filename specified...");
-#endif
}
#if QT_CONFIG(translation)
@@ -343,6 +361,7 @@ static void usage()
puts(" --fullscreen ..................... Run fullscreen");
puts(" --transparent .................... Make the window transparent");
puts(" --multisample .................... Enable multisampling (OpenGL anti-aliasing)");
+ puts(" --core-profile ................... Request a core profile OpenGL context");
puts(" --no-version-detection ........... Do not try to detect the version of the .qml file");
puts(" --slow-animations ................ Run all animations in slow motion");
puts(" --resize-to-root ................. Resize the window to the size of the root item");
@@ -355,6 +374,9 @@ static void usage()
puts(" --scaling..........................Enable High DPI scaling (AA_EnableHighDpiScaling)");
puts(" --no-scaling.......................Disable High DPI scaling (AA_DisableHighDpiScaling)");
puts(" --verbose..........................Print version and graphical diagnostics for the run-time");
+#ifdef QT_WIDGETS_LIB
+ puts(" --apptype [gui|widgets] ...........Select which application class to use. Default is widgets.");
+#endif
puts(" -I <path> ........................ Add <path> to the list of import paths");
puts(" -P <path> ........................ Add <path> to the list of plugin paths");
puts(" -translation <translationfile> ... Set the language to run in");
@@ -444,30 +466,38 @@ int main(int argc, char ** argv)
// Parse arguments for application attributes to be applied before Q[Gui]Application creation.
for (int i = 1; i < argc; ++i) {
const char *arg = argv[i];
- if (!qstrcmp(arg, "--disable-context-sharing"))
+ if (!qstrcmp(arg, "--disable-context-sharing")) {
options.applicationAttributes.removeAll(Qt::AA_ShareOpenGLContexts);
- else if (!qstrcmp(arg, "--gles"))
+ } else if (!qstrcmp(arg, "--gles")) {
options.applicationAttributes.append(Qt::AA_UseOpenGLES);
- else if (!qstrcmp(arg, "--software"))
+ } else if (!qstrcmp(arg, "--software")) {
options.applicationAttributes.append(Qt::AA_UseSoftwareOpenGL);
- else if (!qstrcmp(arg, "--desktop"))
+ } else if (!qstrcmp(arg, "--desktop")) {
options.applicationAttributes.append(Qt::AA_UseDesktopOpenGL);
- else if (!qstrcmp(arg, "--scaling"))
+ } else if (!qstrcmp(arg, "--scaling")) {
options.applicationAttributes.append(Qt::AA_EnableHighDpiScaling);
- else if (!qstrcmp(arg, "--no-scaling"))
+ } else if (!qstrcmp(arg, "--no-scaling")) {
options.applicationAttributes.append(Qt::AA_DisableHighDpiScaling);
+ } else if (!qstrcmp(arg, "--apptype")) {
+ if (++i >= argc)
+ usage();
+ if (!qstrcmp(argv[i], "gui"))
+ options.applicationType = Options::QmlApplicationTypeGui;
+ }
}
for (Qt::ApplicationAttribute a : qAsConst(options.applicationAttributes))
QCoreApplication::setAttribute(a);
+ QScopedPointer<QGuiApplication> app;
#ifdef QT_WIDGETS_LIB
- QApplication app(argc, argv);
-#else
- QGuiApplication app(argc, argv);
+ if (options.applicationType == Options::QmlApplicationTypeWidget)
+ app.reset(new QApplication(argc, argv));
#endif
- app.setApplicationName("QtQmlViewer");
- app.setOrganizationName("QtProject");
- app.setOrganizationDomain("qt-project.org");
+ if (app.isNull())
+ app.reset(new QGuiApplication(argc, argv));
+ QCoreApplication::setApplicationName(QStringLiteral("QtQmlViewer"));
+ QCoreApplication::setOrganizationName(QStringLiteral("QtProject"));
+ QCoreApplication::setOrganizationDomain(QStringLiteral("qt-project.org"));
QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR));
const QStringList arguments = QCoreApplication::arguments();
@@ -496,12 +526,16 @@ int main(int argc, char ** argv)
options.resizeViewToRootItem = true;
else if (lowerArgument == QLatin1String("--multisample"))
options.multisample = true;
+ else if (lowerArgument == QLatin1String("--core-profile"))
+ options.coreProfile = true;
else if (lowerArgument == QLatin1String("--verbose"))
options.verbose = true;
else if (lowerArgument == QLatin1String("-i") && i + 1 < size)
imports.append(arguments.at(++i));
else if (lowerArgument == QLatin1String("-p") && i + 1 < size)
pluginPaths.append(arguments.at(++i));
+ else if (lowerArgument == QLatin1String("--apptype"))
+ ++i; // Consume previously parsed argument
else if (lowerArgument == QLatin1String("--help")
|| lowerArgument == QLatin1String("-help")
|| lowerArgument == QLatin1String("--h")
@@ -515,14 +549,14 @@ int main(int argc, char ** argv)
QTranslator qtTranslator;
QString sysLocale = QLocale::system().name();
if (qtTranslator.load(QLatin1String("qt_") + sysLocale, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
- app.installTranslator(&qtTranslator);
+ app->installTranslator(&qtTranslator);
if (translator.load(QLatin1String("qmlscene_") + sysLocale, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
- app.installTranslator(&translator);
+ app->installTranslator(&translator);
QTranslator qmlTranslator;
if (!options.translationFile.isEmpty()) {
if (qmlTranslator.load(options.translationFile)) {
- app.installTranslator(&qmlTranslator);
+ app->installTranslator(&qmlTranslator);
} else {
fprintf(stderr, "Could not load the translation file \"%s\"\n",
qPrintable(options.translationFile));
@@ -612,6 +646,10 @@ int main(int argc, char ** argv)
window->setColor(QColor(Qt::transparent));
window->setFlags(Qt::FramelessWindowHint);
}
+ if (options.coreProfile) {
+ surfaceFormat.setVersion(4, 1);
+ surfaceFormat.setProfile(QSurfaceFormat::CoreProfile);
+ }
window->setFormat(surfaceFormat);
if (window->flags() == Qt::Window) // Fix window flags unless set by QML.
@@ -630,7 +668,7 @@ int main(int argc, char ** argv)
// Now would be a good time to inform the debug service to start listening.
- exitCode = app.exec();
+ exitCode = app->exec();
#ifdef QML_RUNTIME_TESTING
RenderStatistics::printTotalStats();
diff --git a/tools/qmlscene/qmlscene.pro b/tools/qmlscene/qmlscene.pro
index ec73f1871a..6a7df90ccc 100644
--- a/tools/qmlscene/qmlscene.pro
+++ b/tools/qmlscene/qmlscene.pro
@@ -7,13 +7,6 @@ SOURCES += main.cpp
DEFINES += QML_RUNTIME_TESTING
!contains(QT_CONFIG, no-qml-debug): DEFINES += QT_QML_DEBUG_NO_WARNING
-QMAKE_TARGET_PRODUCT = qmlscene
-QMAKE_TARGET_DESCRIPTION = Utility that loads and displays QML documents
-
-win32 {
- VERSION = $${QT_VERSION}.0
-} else {
- VERSION = $${QT_VERSION}
-}
+QMAKE_TARGET_DESCRIPTION = QML Scene Viewer
load(qt_tool)
diff --git a/tools/qmltestrunner/qmltestrunner.pro b/tools/qmltestrunner/qmltestrunner.pro
index 505537480c..47b9637199 100644
--- a/tools/qmltestrunner/qmltestrunner.pro
+++ b/tools/qmltestrunner/qmltestrunner.pro
@@ -3,13 +3,6 @@ SOURCES += main.cpp
QT += qml qmltest
CONFIG += no_import_scan
-QMAKE_TARGET_PRODUCT = qmltestrunner
-QMAKE_TARGET_DESCRIPTION = QML test runner
-
-win32 {
- VERSION = $${QT_VERSION}.0
-} else {
- VERSION = $${QT_VERSION}
-}
+QMAKE_TARGET_DESCRIPTION = QML Test Runner
load(qt_tool)
diff --git a/tools/qmltime/qmltime.pro b/tools/qmltime/qmltime.pro
index ec1bcb5a03..04a5fd5957 100644
--- a/tools/qmltime/qmltime.pro
+++ b/tools/qmltime/qmltime.pro
@@ -4,13 +4,5 @@ QT += qml quick
QT += quick-private
macx:CONFIG -= app_bundle
-QMAKE_TARGET_PRODUCT = qmltime
-QMAKE_TARGET_DESCRIPTION = Tool for benchmarking the instantiation of a QML component
-
-win32 {
- VERSION = $${QT_VERSION}.0
-} else {
- VERSION = $${QT_VERSION}
-}
-
+QMAKE_TARGET_DESCRIPTION = QML Time
SOURCES += qmltime.cpp